文章目录
- Request
- Request继承体系
- Request获取请求数据
- 获取请求数据基本使用
- 通用方式获取请求参数
- Request请求参数中文乱码处理
- 请求转发
Request
Request: 使用 request对象来获取请求数据
Response: 使用 response对象来设置响应数据
Request继承体系
Request的继承体系如下
Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中; 因此Tomcat需要实现HttpServletRequest接口
学习实现类RequestFacade的使用,可以查阅JavaEE API文档的HttpServletRequest接口
Request获取请求数据
获取请求数据基本使用
请求数据分为三部分:
请求头
请求行
请求体
获取请求头的方法如下:
方法名 | 描述 |
String getHeader(String name) | 根据请求头名称,获取值 |
@WebServlet("/req")
public class RequestDemo 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);
}
}
获取请求行的方法如下:
方法名 | 描述 |
String getMethod() | 获取的请求方式 |
String getContextPath() | 获取虚拟目录(项目访问路径) |
StringBuffer getRequestURL() | 获取URL(统一资源定位符) |
String getRequestURI() | 获取URI(统一资源标识符) |
String getQueryString() | 获取请求参数(GET方式) |
演示代码: 启动服务器后通过查询字符串传递参数, 访问URL:
http://localhost:8080/request-demo/req?name=chenyq&age=18
@WebServlet("/req")
public class RequestDemo 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); // /request-demo
// 获取URL统一资源定位符
StringBuffer requestURL = req.getRequestURL();
System.out.println(requestURL.toString()); // http://localhost:8080/request-demo/req
// 获取URI统一资源标识符
String requestURI = req.getRequestURI();
System.out.println(requestURI); // /request-demo/req
// 获取请求参数
String queryString = req.getQueryString();
System.out.println(queryString); // name=chenyq&age=18
}
}
获取请求体(post请求才有请求体)的方法如下:
方法名 | 描述 |
ServletInputStream getInputStream() | 获取字节输入流 |
BufferedReader getReader() | 获取字符输入流 |
我们编写一个html文件, 在文件中使用表单模拟post请求
<form method="post" action="http://localhost:8080/request-demo/req">
<div>
<span>请输入账号: </span>
<input type="text" name="username">
</div>
<div>
<span>请输入密码: </span>
<input type="password" name="password">
</div>
<input type="submit" value="提交">
</form>
通过post获取到请求体
@WebServlet("/req")
public class RequestDemo extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取post请求体(post的请求的参数)
// 1. 获取字符输入流
BufferedReader br = req.getReader();
// 2. 读取数据
String line = br.readLine();
System.out.println(line); // username=admin&password=1234
}
}
通用方式获取请求参数
上面我们说了请求参数获取方式:
GET 方式:
String getQueryString()
POST 方式:
BufferedReader getReader()
思考:
GET 请求方式 和 POST 请求方式 区别主要在于获取请求参数的方式不一样,是否可以提供一种统一获取请求参数的方式,从而统一doGet 和 doPost方法内的代码?
Request 通用获取请求参数的方法如下:
通用指的是: 获取参数的方法既可以被用于Get, 又可以被用于Post请求;
既然有了统一获取参数的方法, 那么我们doPost方法中直接调用doGet即可, 无需再编写重复逻辑的代码
方法名 | 描述 |
Map<String, String[ ]> getParameterMap() | 获取所有参数Map集合, 如果key相同, 会将值放入一个数组中 |
String[ ] getParameterValues(String name) | 根据名称获取一个参数值的数组 |
String getParameter(String name) | 根据名称获取一个单个参数值 |
示例代码:
获取所有参数Map集合
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取所有参数Map集合
Map<String, String[]> map = req.getParameterMap();
// 遍历展示
for (String key : map.keySet()) {
String[] values = map.get(key);
System.out.print(key + ":");
for (String value : values) {
System.out.print(value + " ");
}
System.out.println();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 调用doGet方法, 避免编写重复逻辑
this.doGet(req, resp);
}
}
根据名称获取一个参数值的数组
@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 {
// 调用doGet方法, 避免编写重复逻辑
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");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 调用doGet方法, 避免编写重复逻辑
this.doGet(req, resp);
}
}
Request请求参数中文乱码处理
请求参数如果存在中文数据,是会出现乱码问题的
POST请求解决方案:
设置输入流的编码为"UTF-8"
request.setCharacterEncoding("UTF-8");
演示代码
@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 解决Post乱码
request.setCharacterEncoding("UTF-8"); // 设置字符输入流的编码为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);
}
}
GET和POST的通用方式
浏览器进行URL编码默认使用的是UTF-8, 而Tomcat进行URL解码默认的是ISO-8859-1;
所以我们需要拿到Tomcat解码的结果, 对其先编码,再解码;
Tomcat 8.0 之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
new String(username.getBytes("ISO-8859-1"),"UTF-8");
演示代码
@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取username参数
String username = request.getParameter("username");
// 2. 对获取到的username先通过ISO-8859-1编码再通过UTF-8解码
username = new String(username.getBytes("ISO-8859-1"), "UTF-8");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
请求转发
请求转发(forward):一种在服务器内部的资源跳转方式
例如下图, 浏览器向Tomcat请求资源A; 资源A又将请求转发给资源B
实现方式:
req.getRequestDispatcher("资源B路径").forward(req,resp);
示例代码如下:
分别创建一个RequestDemo4, 访问路径为/req4和一个RequestDemo5, 访问路径为/req5
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo4...");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo5...");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
再在demo4中将请求转发发哦demo5中
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo4...");
// 请求转发, 将请求转发到/req5
request.getRequestDispatcher("/req5").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
访问/req4的打印结果
demo4...
demo5...
在很多时候, 我们通常是在资源A中处理一部分数据, 然后再转发给资源B继续处理; 那么就需要请求转发资源间数据共享: 转发资源间数据共享使用的是request对象, request对象提供了如下数据共享常用的方法:
方法名 | 描述 |
void setAttribute(String name, Object o) | 存储数据到 request域中 |
Object getAttribute(String name) | 根据 key,获取值 |
void removeAttribute(String name) | 根据 key,删除该键值对 |
示例代码:
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo4...");
// 向request域中存储数据
request.setAttribute("name", "chenyq");
// 请求转发, 将请求转发到/req5
request.getRequestDispatcher("/req5").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo5...");
// 从request中获取数据
Object message = request.getAttribute("name");
System.out.println(message); // chenyq
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
请求转发的特点:
请求转发后, 浏览器地址栏路径不发生变化
只能转发到当前服务器的内部资源
一次请求,可以在转发的资源间使用request共享数据