1 Request
- request:获取请求数据
- 浏览器会发送HTTP请求到后台服务器
Tomcat
- HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
- 后台服务器
Tomcat
会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中 - 所存入的对象即为
request
对象,所以我们可以从request
对象中获取请求的相关参数 - 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
- 浏览器会发送HTTP请求到后台服务器
2 Request继承体系
ServletRequest
和HttpServletRequest
都是接口,无法创建对象,这时候就需要用到Request继承体系中的RequestFacade
:
- 该类实现了
HttpServletRequest
接口,也间接实现了ServletRequest
接口。 - Servlet类中的
service
方法、doGet
方法或者是doPost
方法最终都是由Web服务器Tomcat
来调用的,所以Tomcat
提供了方法参数接口的具体实现类,并完成了对象的创建
3 Request获取请求数据
HTTP请求数据总共分为三部分内容,分别是请求行、请求头、请求体
3.1 获取请求行数据
方法 | 说明 |
---|---|
String getMethod() | 获取请求方式 |
String getContextPath() | 获取虚拟目录(项目访问路径): /request-demo |
StringBuffer getRequestURL() | 获取URL(统一资源定位符): http://localhost:8080/request-demo/req1 |
String getRequestURI() | 获取URI(统一资源标识符): /request-demo/req1 |
String getQueryString() | 获取请求参数(GET方式): username=zhangsan&password=123 |
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
System.out.println(method);//GET
String contextPath = req.getContextPath();
System.out.println(contextPath);
StringBuffer url = req.getRequestURL();
System.out.println(url.toString());
String uri = req.getRequestURI();
System.out.println(uri);
String queryString = req.getQueryString();
System.out.println(queryString);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
3.2 获取请求头数据
对于请求头的数据,格式为key: value
方法 | 说明 |
---|---|
String getHeader(String name) | 以根据请求头名称获取对应值 |
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求头: user-agent: 浏览器的版本信息
String agent = req.getHeader("user-agent");
System.out.println(agent);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
3.3 获取请求体数据(只有POST请求有)
对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:
- 获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
// ServletInputStream getInputStream()
- 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
// BufferedReader getReader()
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取post 请求体:请求参数
//1. 获取字符输入流
BufferedReader br = req.getReader();
//2. 读取数据
String line = br.readLine();
System.out.println(line);
}
}
BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,request对象被销毁后,BufferedReader流就会自动关闭,所以此处就不需要手动关闭流了。
3.4 获取请求参数通用方式
- GET请求,请求参数在请求行中
String getQueryString()
- 是POST请求,请求参数一般在请求体中
BufferedReader getReader()
此处需要注意的是GET请求和POST请求接收参数的方式不一样,具体实现的代码如下:
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String result = req.getQueryString();
System.out.println(result);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
BufferedReader br = req.getReader();
String result = br.readLine();
System.out.println(result);
}
}
对于上述的代码,导致出现了重复代码(System.out.println(result)
),所以request
对象为我们提供了如下方法
方法 | 说明 |
---|---|
Map<String,String[]> getParameterMap() | 获取所有参数Map集合 |
String[] getParameterValues(String name) | 根据名称获取参数值(数组) |
String getParameter(String name) | 根据名称获取参数值(单个值) |
- 获取所有请求参数
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 获取所有参数的Map集合
Map<String, String[]> map = req.getParameterMap();
for (String key : map.keySet()) {
// username:zhangsan lisi
System.out.print(key+":");
//获取值
String[] values = map.get(key);
for (String value : values) {
System.out.print(value + " ");
}
System.out.println();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
- 获取请求参数中的爱好,结果是数组值
/**
* request 通用方式获取请求参数
*/
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
- 获取请求参数中的用户名和密码,结果是单个值
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username);
System.out.println(password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
4 请求参数中文乱码问题
4.1 POST请求解决方案
原因:
- POST的请求参数是通过
request
的getReader()
来获取流中的数据 Tomcat
在获取流的时候采用的编码是ISO-8859-1
ISO-8859-1
编码是不支持中文的,所以会出现乱码
解决方案:
- 页面设置的编码格式为
UTF-8
- 把
Tomcat
在获取流数据之前的编码设置为UTF-8
- 通过
request.setCharacterEncoding("UTF-8")
设置编码,UTF-8
也可以写成小写
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 解决乱码: POST getReader()
//设置字符输入流的编码,设置的字符集要和页面保持一致
request.setCharacterEncoding("UTF-8");
//2. 获取username
String username = request.getParameter("username");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
4.2 GET请求解决方案
GET请求获取请求参数的方式是request.getQueryString()
POST请求获取请求参数的方式是request.getReader()
request.setCharacterEncoding("utf-8")
是设置request
处理流的编码
getQueryString
方法并没有通过流的方式获取数据
所以GET请求不能用设置编码的方式来解决中文乱码问题
原因:
- 浏览器把中文参数按照
UTF-8
进行URL
编码 Tomcat
对获取到的内容进行了ISO-8859-1
的URL
解码- 在控制台就会出现类上
å¼ ä¸
解决方案:
- 考虑把
å¼ ä¸‰
转换成字节,在把字节转换成张三
,在转换的过程中是它们的编码一致,就可以解决中文乱码问题。 - 按照
ISO-8859-1
编码获取乱码å¼ ä¸‰
对应的字节数组 - 按照
UTF-8
编码获取字节数组对应的字符串
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 解决乱码:POST,getReader()
//request.setCharacterEncoding("UTF-8");//设置字符输入流的编码
//2. 获取username
String username = request.getParameter("username");
System.out.println("解决乱码前:"+username);
//3. GET,获取参数的方式:getQueryString
// 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
/* //3.1 先对乱码数据进行编码:转为字节数组
byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
//3.2 字节数组解码
username = new String(bytes, StandardCharsets.UTF_8);*/
username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
System.out.println("解决乱码后:"+username);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
Tomcat8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
5 Request请求转发
- 请求转发(forward):一种在服务器内部的资源跳转方式(从资源A到资源B)。
- 实现方式:
req.getRequestDispatcher("资源B路径").forward(req,resp);
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器
- 一次请求,可以在转发资源间使用request共享数据
5.1 资源共享
- 请求转发资源间共享数据:使用
Request
对象
方法 | 说明 |
---|---|
void setAttribute(String name,Object o) | 存储数据到request域中 |
Object getAttribute(String name) | 根据key获取值 |
void removeAttribute(String name) | 根据key删除该键值对 |
实现从/demo5转发到/demo6去:
- 修改RequestDemo5中的方法
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo5...");
//存储数据
request.setAttribute("msg","hello");
//请求转发
request.getRequestDispatcher("/req6").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- 修改RequestDemo6中的方法
@WebServlet("/req6")
public class RequestDemo6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo6...");
//获取数据
Object msg = request.getAttribute("msg");
System.out.println(msg);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}