1 请求处理流程
1.浏览器(客户端)通过 HTTP 协议来访问服务器的资源,Servlet 主要用来处理 HTTP 请求。
2.Servlet 容器接收HTTP 请求,会针对该请求分别创建一个 HttpServletRequest 和 HttpServletReponse 对象。
3.容器将两个对象传入 service() 方法,并调用该方法。
4.在 service() 方法中,通过 HttpServletRequest 对象获取客户端信息以及请求的相关信息。
5.对 HTTP 请求进行处理。
6.请求处理完成后,将响应信息封装到 HttpServletReponse 对象中
7.Servlet 容器将响应信息返回给客户端
8.当 Servlet 容器将响应信息返回给客户端后,对象被销毁。

2 HttpServletRequest
该对象用于获取请求数据,例如请求方式、请求的资源以及请求中携带的参数等等。

request对象继承体系结构:
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)
2.1 请求行方法
获取请求行信息
GET /web/weather?city=101180101 HTTP/1.1
1. String getMethod(); 请求方式
GET
2. String getContextPath(); 获取虚拟目录
/web
3. String getServletPath(); 获取Servlet路径
/weather
4. String getQueryString(); 获取get方式请求参数
city=101180101
5. getRequestURI() / getRequestURL;获取请求URI
/web/weather 和 http:localhost:8080/web/weather
6. String getProtocol(); 获取协议及版本
HTTP/1.1
get请求方式

post请求方式

2.2 请求头方法
获取请求头信息
1. String getHeader(String name);
通过请求头的名称获取请求头的值
2. Enumeration<String> getHeaderNames();
获取所有的请求头名称
2.3 请求体方法
获取请求体信息
获取流对象
1. BufferedReader getReader(); 获取get方式请求参数
2. ServletInputStream getInputStream();获取字节输入流,可以操作所有类型数据
1.HTTP协议中没有明确规定GET请求是否能带body,市场上部分浏览器会不支持GET请求带body。
2.HTTP 协议未定义 GET 请求的 body 语义,如果想用 GET 请求发送 body,得先为其定义语义,并确保上下游都能很好的支持。
2.4 请求参数方法
获取请求参数
GET方式:参数放在URL后面 获取方式:request.getQueryString()
POST方式:参数放实体内容中 获取方式:request.getInputStream()
获取到的结果形式:

获取请求参数方法
1. Enumeration<String> request.getParameterNames();
获取所有参数名称列表
2.String request.getParameter("参数名");
根据参数名称获取参数值
3.String[] request.getParameterValues("参数名");
根据参数名获取参数值(可以获取多个值的参数,例如多选框提交的参数)
4. Map<String, String[]> request.getParameterMap()
得到名称和值的map集合
编码问题
在Tomcat7及之前的版本中,Tomcat默认GET方法传输的编码格式为ISO-8859-1,因此会产生乱码问题
编码问题解决办法:
在调用request.getParameter()方法之前设置解码所查询的码表: request.setCharacterEncoding("utf-8");
注意:该方法只能对请求实体内容的数据编码,由于POST提交的数据在实体内容中,所以该方法对POST方法有效,而GET方式提交参数在URI后面,所以该方法对GET方法无效!
修改POST方式参数编码:
request.setCharacterEncoding("utf-8");
修改GET方式参数编码:
手动解码: String name = new String(name.getBytes("iso-8859-1"),"utf-8");
2.5 请求转发
请求转发,一种在服务器内部的资源跳转方式。 是在服务端将请求交给另外一个资源来处理并返回给浏览器,在浏览器端并没有察觉到该过程。
请求转发步骤
1. 通过request对象获取请求转发器对象:RequestDispatcher request.getRequestDispatcher(String path)
2. 使用RequestDispatcher对象来进行转发:
forward(ServletRequest request, ServletResponse response)
请求转发特点
1. 在请求发送过程中,浏览器只是发送一次请求
2. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中
3. 转发是一次请求
过程分析:

1. 浏览器只发送了一次请求,浏览器的地址栏不会发生改变
2. 请求过程中只产生一个request和response对象
3. 多个Servlet共享同一个request和response对象
4. 通过 request.getRequestDispatcher("x").forward(request,response)方式实现
优点
1. 无论本次请求涉及到多少servlet,浏览器只是发送一次请求
2. Servlet之间调用发生在服务器计算机上,节省服务器与浏览器之间往返次数增加处理服务速度。
3. 可以在转发时利用共享的request对象进行数据传递。
3 HttpServletResponse
3.1 重点对象
Tomcat接收HTTP请求,则创建一个HttpServletResponse对象,供Servlet程序使用。
不仅包含了响应的数据,还可通过相关方法来操作这些数据,包括设置响应头、发送错误状态码、写入响应内容等。
传递数据
通过流来给客户端传递数据的
该对象用来设置响应数据。
字节流 getOutputStream() 常用于下载(传递二进制数据)
字符流 getWriter() 常用于回传字符串(非常常用)
HttpServletResponse
该对象用来设置响应数据,通过response对象可以改变响应的信息。
设置响应行
response.setStatus() 设置状态码
设置响应头
response.setHeader("name","value") 设置响应头
3.2 重定向
服务端根据逻辑,发送一个状态码(302),同时响应头中通过location属性,告诉浏览器重新去请求的地址.
1. 地址栏显示的是新的URL,浏览器地址栏会发生变化
2. 浏览器至少发送两次请求(只有第一次请求是用户手动发送的,后续请求都是浏览器自动发送的)

示例
例如登录成功后跳转到新的页面时就可以使用它。
response.setStatus(302);
response.setHeader("location", "/ObjectDemo/redirect.jsp");
由于功能的特殊性,可以简写为:
response.sendRedirect("/ObjectDemo/redirect.jsp ");
案例:定时刷新和延时跳转
/**
* 定时刷新 浏览器通过refresh响应头,得到刷新实践后会重新发起请求
*/
// response.setHeader("refresh", "1"); // 每隔1秒刷新页面
/**
* 隔n秒之后跳转到另外的页面
*/
response.setHeader("refresh", "3;url= /ObjectDemo_war_exploded/redirect.jsp "); // 3秒之后跳转
请求转发与重定向的区别
转发
a)地址栏不会改变
b)转发只能转发到当前web应用内的资源
c)可以在转发过程中,可以把数据保存到request对象中
重定向
a)地址栏会改变,变成重定向到地址。
b)重定向可以跳转到当前web应用,或其他web应用,甚至是外部域名网站。
c)不能在重定向的过程把数据保存到request中。
设置响应头
content-type:描述发送给浏览器的数据类型
response.setHeader("content-type", "text/html"); response.setContentType("text/html"); // 和上面等价,推荐此种写法
3.3 编码设置
实体内容
response.getWriter().write(); 发送字符实体内容
如果发送了中文会发现有乱码,为什么?
response.getOutputStream().write() 发送字节实体内容
响应编码格式问题
在Servlet中输出响应的编码格式:
System.out.println("响应编码格式:" + response.getCharacterEncoding());
可以发现输出的是:


解决方法:
在getWriter之前设置编码格式:
response.setCharacterEncoding("utf-8");
可以直接合并到content-type中:
response.setContentType("text/html; charset=utf-8");
如果使用response.getOutputStream().write(),则直接传递字节数据,此时将不会进行查询码表,所以会直接传递当前的编码格式数据。 所以response.setCharacterEncoding对字节流无效
项目中的编码问题统一解决方案
在请求方法的开头直接设置请求和响应的编码,然后再进行其他代码处理:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) . . . {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
}
2174

被折叠的 条评论
为什么被折叠?



