request和response这两个参数的作用
-
request:封装请求数据的对象
- 浏览器会发送HTTP请求到后台服务器[Tomcat]
- HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
- 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
- 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
- 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
-
response:封装响应数据的对象
- 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
- 把响应数据封装到response对象中
- 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
- 浏览器最终解析结果,把内容展示在浏览器给用户浏览
1. Request对象
1.1 Request继承体系:
小结
- Request的继承体系为ServletRequest-->HttpServletRequest-->RequestFacade
- Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法
- 使用request对象,可以查阅JavaEE API文档的HttpServletRequest接口中方法说明
1.2 Request获取请求数据
获取请求行数据
获取请求头数据
获取请求体数据
对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:
-
获取字节输入流,如果前端发送的是字节数据,如文件数据,用
ServletInputStream getInputStream()
-
获取字符输入流,如果是纯文本数据,则使用该方法
BufferedReader getReader()
BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,request对象被销毁后,BufferedReader流就会自动关闭,不需要手动关闭流。
请求参数和请求数据的关系是什么?
请求数据则是包含请求行、请求头和请求体的所有数据,请求参数是请求数据中的部分内容。
GET请求,请求参数在请求行中
POST请求,请求参数一般在请求体中
对于请求参数的获取
- GET方式:
String getQueryString()
- POST方式:
BufferedReader getReader();
request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可
- 获取所有参数Map集合
Map<String,String[]> getParameterMap()
- 根据名称获取参数值(数组)
String[] getParameterValues(String name)
- 根据名称获取参数值(单个值)
String getParameter(String name)
中文乱码解决方案
-
POST请求和GET请求的参数中如果有中文,后台接收数据就会出现中文乱码问题
GET请求在Tomcat8.0以后的版本就不会出现了
-
POST请求解决方案是:设置输入流的编码
request.setCharacterEncoding("UTF-8"); 注意:设置的字符集要和页面保持一致
-
通用方式(GET/POST):需要先解码,再编码
new String(username.getBytes("ISO-8859-1"),"UTF-8");
1.3 Request请求转发
请求转发(forward):一种在服务器内部的资源跳转方式。
req.getRequestDispatcher("资源B路径").forward(req,resp);
3. 请求转发资源间共享数据:使用Request对象
此处主要解决的问题是把请求从/req5
转发到/req6
的时候,如何传递数据给/req6
。
需要使用request对象提供的三个方法:
- 存储数据到request域[范围,数据是存储在request对象]中
void setAttribute(String name,Object o);
- 根据key获取值
Object getAttribute(String name);
- 根据key删除该键值对
void removeAttribute(String name);
请求转发的特点
-
浏览器地址栏路径不发生变化
虽然后台从
/req5
转发到/req6
,但是浏览器的地址一直是/req5
,未发生变化 -
只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器
-
一次请求,可以在转发资源间使用request共享数据
虽然后台从
/req5
转发到/req6
,但是这个只有一次请求
2. Response对象
2.1 Response设置响应数据功能介绍
- 响应行
对于响应头,比较常用的就是设置响应状态码:
void setStatus(int sc);
- 响应头
设置响应头键值对:
void setHeader(String name,String value);
- 响应体
对于响应体,是通过字符、字节输出流的方式往浏览器写,
获取字符输出流:
PrintWriter getWriter();
获取字节输出流
ServletOutputStream getOutputStream();
2.2 Respones请求重定向
一种资源跳转方式
resp.setStatus(302);
resp.setHeader("location","资源B的访问路径");
简化版写法:
resposne.sendRedirect("/request-demo/resp2")
重定向的特点
-
浏览器地址栏路径发生变化
当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化 -
可以重定向到任何位置的资源(服务器内、外部均可)
-
两次请求,不能在多个资源使用request共享数据
因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据
2.3 路径问题
- 浏览器使用:需要加虚拟目录(项目访问路径)
- 服务端使用:不需要加虚拟目录
对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录
对于重定向来说,路径最终是由浏览器来发送请求,就需要添加虚拟目录。
可以动态获取项目访问的虚拟路径,从而降低代码的耦合度。
//简化方式完成重定向
//动态获取虚拟目录
String contextPath = request.getContextPath();
response.sendRedirect(contextPath+"/resp2");
2.4 Response响应字符数据
// 返回一个简单的字符串`aaa`
response.setContentType("text/html;charset=utf-8");
//1. 获取字符输出流
PrintWriter writer = response.getWriter();
writer.write("aaa");
// 返回一串html字符串,并且能被浏览器解析
PrintWriter writer = response.getWriter();
//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
response.setHeader("content-type","text/html");
writer.write("<h1>aaa</h1>");
// 返回中文字符串
//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");
2.5 Response响应字节数据
对于流的copy的代码是比较复杂的,所以我们可以导入依赖,使用别人提供好的方法来简化代码的开发。