一.介绍
在介绍之前需要了解网络通信的三要素:
- IP:电子设备(计算机)在网络中的唯一标识。
- 端口:应用程序在计算机中的唯一标识。 0~65536
- 传输协议:规定了数据传输的规则
而先前的JavaWeb的前篇了解HTML,CSS,以及JavaScript的使用,静态资源和动态资源的分化,都是基于本地缓存的使用。以下是客户端以及浏览器端的交互方式和传递方向。
而在服务器端中,可以定义接受的响应到用户信息,就比如文件下载…在这个服务器端,可以接收用户的请求,处理请求,做出响应,当然在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目。
常见的java相关的web服务(一般我们使用Tomcat,Tomcat的安装自行下载)
webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范servlet/jsp。开源的,免费的。
二.Servlet: server applet
1.Servlet是什么
是:运行在服务器端的小程序,定义了Java类被浏览器访问到(tomcat识别)的规则,这样我们才能通过服务器端去定义用户的使用规则以及限制用户的使用规则,怎么去定义和限制,这就是我们接下来要说的。
首先定义一个实现Servlet的类,实现里面的方法,这些方法中有服务器的初始化,服务以及销毁…
我们需要了解它的一个运作方式,下图解释了它如何通过浏览器端的请求方式去做相应的事。
public class ServletDemo implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//提供服务的方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello Demo");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
在描述完其获取请求方式,再了解其配置规则,配置Servlet
看到这里,可能很多人看不懂,来看一张图片
首先通过TomCat根据请求的URL资源路径去找到全类名,再通过反射可以获取到对象,最后通过Servlet去调用其方法。
2. HTTP
那传过来的请求消息包括什么呢?这里讲到了HTTPHyper Text Transfer Protocol 超文本传输协议
做什么:传输协议:定义了,客户端和服务器端通信时,发送数据的格式
特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求/响应模型的:一次请求对应一次响应
- 无状态的:每次请求之间相互独立,不能交互数据
请求消息数据格式
请求行:
请求方式 请求url 请求协议/版本:GET /login.html HTTP/1.1
HTTP协议有7中请求方式,常用的有2种:
请求头:客户端浏览器告诉服务器一些信息(请求头名称: 请求头值)
常见的请求头:
referer的补充说明:
只有通过正规渠道的链接才能播放视屏,就比如上图的盗链模式。
请求空行:空行,就是用于分割POST请求的请求头,和请求体的。
请求体(正文):封装POST请求消息的请求参数的
响应消息:服务器端发送给客户端的数据
响应消息数据格式 :
响应行:
组成 协议/版本 响应状态码 状态码描述
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
- 状态码都是3位数字
- 分类
- 状态码都是3位数字
- 1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
- 2xx:成功。代表:200
- 3xx:重定向。代表:302(重定向),304(访问缓存)
- 4xx:客户端错误(404(请求路径没有对应的资源),405:请求方式没有对应的doXxx方法)
- 5xx:服务器端错误。代表:500(服务器内部出现异常)
响应头:格式:头名称: 值
常见的响应头:
Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
Content-disposition:服务器告诉客户端以什么格式打开响应体数据,其中in-line:默认值,在当前页面内打开;attachment;filename=xxx:以附件形式打开响应体。文件下载。
3.Request请求
在介绍request请求之前需要先了解它原作规则(服务器和浏览器怎么去交互的),一下图片解释:
通过获取到的数据,我们可以干什么呢?换句话说request可以用什么功能把接收到的数据(用户想要干什么的数据)展示出来
这里就讲到了request的功能介绍
获取请求消息数据:
(1)获取请求行数据
获取请求方式:String getMethod()
获取虚拟目录(重点):String getContextPath()
获取Servlet路径:String getServletPath()
获取get方式请求参数:String getQueryString()
获取请求URI(重点):URI:统一资源标识符 : /day14/demo1:String getRequestURI();URL:统一资源定位 http://localhost/day14/demo1 :StringBuffer getRequestURL()
获取协议及版本:HTTP/1.1 String getprotocol()
获取客户机的IP地址 String getRemoteAddr()
(2)获取请求头数据
(重点)String getHeader(String name):通过请求头的名称获取请求头的值
(迭代器Iterator)Enumeration getHeaderNames():获取所有的请求头名称
(3)获取请求体数据(请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数)
1. 获取流对象
BufferedReader getReader():获取字符输入流,只能操作字符数据
ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
2. 再从流对象中拿数据
(4)其他功能:
不论get还是post请求方式都可以使用下列方法来获取请求参数
- String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
- String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game 多用于复选框
- Enumeration getParameterNames():获取所有请求的参数名称
- Map<String,String[]> getParameterMap():获取所有参数的map集合
乱码问题
get:tomcat8解决了该问题
post:在获取参数前,设置request的编码request.setCharacterEncoding(“utf-8”)
- 请求转发:一种在服务器内部的资源跳转方式
步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
package jh.web;
/**
* @author BaBa
* @Version 1/0
*/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
//演示重定向
@WebServlet("/ResponseServlet1")
public class ResponseServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("当前是ResponseServlet1");
//基础重定向方法
//访问ResponseServlet1,会自动跳转到ResponseServlet2
//先设置状态码为302,为重定向
/*response.setStatus(302);
//设置响应头路径为ResponseServlet2
response.setHeader("location","/JavaEE/ResponseServlet2");*/
//动态的获取虚拟目录
String contextPath = request.getContextPath();
//简单的方法
response.sendRedirect(contextPath+"/ResponseServlet2");
/*实际上这一串是/JavaEE/ResponseServlet2*/
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
package jh.web; /**
* @author BaBa
* @Version 1/0
*/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/ResponseServlet2")
public class ResponseServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("当前是ResponseServlet1");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
特点:
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求
4. 它携带了数据
共享数据
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
1. void setAttribute(String name,Object obj):存储数据
2. Object getAttitude(String name):通过键获取值
3. void removeAttribute(String name):通过键移除键值对
注意:这个放于forward方法的上面,不然响应太快会导致无法获取信息!
(5)使用BeanUtils来完成参数的获取和封装对象
综合练习:
package com.web.servlet; /**
* @author BaBa
* @Version 1/0
*/
import com.dao.daoImpl.userDaoImpl;
import com.dao.userDao;
import com.entity.User;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
request.setCharacterEncoding("UTF-8");
userDao userDao = new userDaoImpl();
//基础:手动设置
/*//获取username和password
String username = request.getParameter("username");
String password = request.getParameter("password");
//封装对象
User users = new User();
users.setUsername(username);
users.setPassword(password);*/
//进阶:使用beanUtils工具类
//获取所有请求的参数
Map<String, String[]> map = request.getParameterMap();
User userlogin = new User();
//使用BeanUtils
try {
BeanUtils.populate(userlogin,map);
} catch (Exception e) {
e.printStackTrace();
}
//从数据库中找该用户,没有就返回空,有就继续往下执行
User user = userDao.select(userlogin);
if (user==null){
//为空就跳转到FailServlet(转发)
request.getRequestDispatcher("/FailServlet").forward(request,response);
}else {
//不为空就跳转SuccessServlet
//将用户储存起来,共享域里
request.setAttribute("user", user);
request.getRequestDispatcher("/SuccessServlet").forward(request,response);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
package com.web.servlet; /**
* @author BaBa
* @Version 1/0
*/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/FailServlet")
public class FailServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
response.setContentType("text/html;charset=utf-8");
//输出
response.getWriter().write("登录失败,用户名或密码错误!");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
package com.web.servlet; /**
* @author BaBa
* @Version 1/0
*/
import com.entity.User;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/SuccessServlet")
public class SuccessServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
response.setContentType("text/html;charset=utf-8");
//从共享域里拿出username
User user = (User) request.getAttribute("user");
if (user!=null) {
//输出
response.getWriter().write("登录成功,欢迎您" + user.getUsername());
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
4.Response:相应数据
它的原理和Request一样,只是在这里是通过请求的资源把用户需要的数据通过封装到response里,服务器在反馈到浏览器一端
功能:设置响应消息
(1)设置响应行
格式:HTTP/1.1 200 ok
设置状态码:setStatus(int sc)
(2)设置响应头:setHeader(String name, String value)
(3)设置响应体
使用步骤:
获取输出流
字符输出流:PrintWriter getWriter()
字节输出流:ServletOutputStream getOutputStream()
使用输出流,将数据输出到客户端浏览器
(4)重定向:资源跳转的方式
1. 设置状态码为302
response.setStatus(302);
2.设置响应头location
response.setHeader(“location”,“/day15/responseDemo2”);
综合简单的重定向方法
response.sendRedirect(“/day15/responseDemo2”);
重定向的特点:redirect(客户端使用)
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
(5)路径写法:
相对路径:通过相对路径不可以确定唯一资源
不以/开头,以.开头路径
如:./index.html
规则:找到当前资源和目标资源之间的相对位置关系
./:当前目录
…/:后退一级目录
绝对路径:通过绝对路径可以确定唯一资源
以/开头的路径
如:http://localhost/day15/responseDemo2------->/day15/responseDemo2
规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
建议虚拟目录动态获取:request.getContextPath()
<a> , <form> 重定向...
给服务器使用:不需要加虚拟目录
转发路径
(6)服务器输出字符数据到浏览器
1. 获取字符输出流
2. 输出数据
//获取字符串输出流
PrintWriter writer = response.getWriter();
writer.println(“拉十多个”);
乱码问题
//简单的形式,设置编码,是在获取流之前设置
response.setContentType(“text/html;charset=utf-8”);
(7)服务器输出字节数据到浏览器
1. 获取字节输出流
2. 输出数据
//获取字节输出流
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(“是打发”.getBytes(“utf-8”));
ServletContext对象:
概念:代表整个web应用,可以和程序的容器(服务器)来通信
获取
通过request对象获取:request.getServletContext();
通过HttpServlet获取:this.getServletContext();
功能
获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式: 大类型/小类型 text/html image/jpeg
获取:String getMimeType(String file)
域对象:共享数据
setAttribute(String name,Object value)
getAttribute(String name)
removeAttribute(String name)
注意:ServletContext对象范围:所有用户所有请求的数据
获取文件的真实(服务器)路径
String getRealPath(String path)
综合练习:
package jh.ResponseWeb; /**
* @author BaBa
* @Version 1/0
*/
import com.uitl.DownLoadUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet("/Response1")
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数(文件名称)
String filename = request.getParameter("filename");
//使用字节输入流加载文件进内存
// 首先找到文件服务器路径
ServletContext servletContext = this.getServletContext();
//获取文件的真实(服务器)路径
String realPath = servletContext.getRealPath("/img/" + filename);
System.out.println(realPath);
//用字节流关联
FileInputStream fileInputStream = new FileInputStream(realPath);
//设置response的响应头
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
//解决中文文件名问题
//1.获取user-agent请求头、
String agent = request.getHeader("user-agent");
//2.使用工具类方法编码文件名即可
filename = DownLoadUtils.getFileName(agent, filename);
//attachment;filename=xxx:以附件形式打开响应体。文件下载
response.setHeader("content-disposition","attachment:filename="+filename);
//流的对拷
//将输出流的数据写到输出流中
ServletOutputStream outputStream = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len=0;
while ((len=fileInputStream.read(buff))!=-1){
outputStream.write(buff,0,len);
}
fileInputStream.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
HTML:文章来源:https://www.toymoban.com/news/detail-502203.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/img/2.jpg">图片1</a>
<a href="/img/1.avi">视频</a>
<hr>
<a href="/Response1?filename=九尾.jpg">图片</a>
<a href="/Response1?filename=1.avi">视频</a>
</body>
</html>
Utils类:文章来源地址https://www.toymoban.com/news/detail-502203.html
package com.uitl;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
到了这里,关于JavaWeb之Servlet的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!