Request&Response
一. Request和Response的概述
Request是请求对象,Response是响应对象。(这两个对象可以在servlet中使用)
1. request:获取请求数据
- 浏览器会发送HTTP请求到后台服务器[Tomcat]
- HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
- 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
- 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
- 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
2. response:设置响应数据
- 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
- 把响应数据封装到response对象中
- 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
- 浏览器最终解析结果,把内容展示在浏览器给用户浏览
3.request和response对象的使用。(在servlet的doGet或者doPost方法中使用)
//使用request对象 获取请求数据
String name = request.getParameter("name");//url?name=zhangsan
//使用response对象 设置响应数据
response.setHeader("content-type","text/html;charset=utf-8");
response.getWriter().write("<h1>"+name+",欢迎您!</h1>");
二. Request对象
1. Request继承体系
1. Request的继承体系为ServletRequest-->HttpServletRequest-->RequestFacade
2. Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法
3. 使用request对象,可以查阅JavaEE API文档的HttpServletRequest接口中方法说明
2. Request获取请求数据
HTTP请求数据总共分为三部分内容,分别是请求行、请求头、请求体
1. 获取请求行数据
请求行包含三块内容,分别是请求方式、请求资源路径、HTTP协议及版本
1. 获取请求方式: GET
String getMethod()
2. 获取虚拟目录(项目访问路径): /request-demo
String getContextPath()
3. 获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
StringBuffer getRequestURL()
4. 获取URI(统一资源标识符): /request-demo/req1
String getRequestURI()
5. 获取请求参数(GET方式): username=zhangsan&password=123
String getQueryString()
2. 获取请求头数据
对于请求头的数据,格式为key: value如下:
根据请求头名称获取对应值的方法为:
String getHeader(String name)
例如://获取请求头: user-agent: 浏览器的版本信息\
String agent = request.getHeader("user-agent");
3. 获取请求体数据
浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST,请求体中的数据格式如下:
1. 获取请求体中数据的两种方式:
a.ServletInputStream getInputStream() //该方法可以获取字节数据
获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
b.BufferedReader getReader()
获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
例如:
//获取post 请求体:请求参数
//1. 获取字符输入流
BufferedReader br = req.getReader();
//2. 读取数据
String line = br.readLine();
System.out.println(line);
2. 注意:BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,
request对象被销毁后,BufferedReader流就会自动关闭,所以此处就不需要手动关闭流了。
总结:
请求行
getMethod()获取请求方式
getContextPath()获取项目访问路径
getRequestURL()获取请求URL
getRequestURI()获取请求URI
getQueryString()获取GET请求方式的请求参数
请求头
getHeader(String name)根据请求头名称获取其对应的值
请求体
注意: 浏览器发送的POST请求才有请求体
如果是纯文本数据:getReader()
如果是字节数据如文件数据:getInputStream()
4. 获取请求参数的通用方式
1.请求参数: 比如登录的时候,提交的用户名和密码就是请求参数
2.请求数据: 请求数据则是包含请求行、请求头和请求体的所有数据
3.请求参数的获取,request对象为我们提供了如下方法:
a.获取所有参数Map集合
Map<String,String[]> getParameterMap()
b.根据名称获取参数值(数组)
String[] getParameterValues(String name)
c.根据名称获取参数值(单个值)
String getParameter(String name)
4.request的getParameterMap方法获取请求参数的原理是:
首先获取请求参数,然后将内容进行分割,将分割的数据放到一个Map集合中,Map的值的类型为String数组
总结:
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//采用request提供的获取请求参数的通用方式来获取请求参数
//编写其他的业务代码...
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
this.doGet(req,resp);
}
}
3. IDEA快速创建Servlet
使用IDEA提供的模板来制作一个Servlet的模板,后期创建servlet更高效
1.打开IDEA的setting设置 > Editor > File and Code Templates > 右侧找到other > Web > Servlet Annotated Class > 修改代码模板
4. 请求参数中文乱码问题
中文请求乱码问题的解决
1. Post请求中文乱码原因:
POST的请求参数是通过request的getReader()来获取流中的数据
TOMCAT在获取流的时候采用的编码是ISO-8859-1
ISO-8859-1编码是不支持中文的,所以会出现乱码
Post请求中文乱码解决方案:
页面设置的编码格式为UTF-8
把TOMCAT在获取流数据之前的编码设置为UTF-8
通过request.setCharacterEncoding("UTF-8")设置编码,UTF-8也可以写成小写
2. GET请求中文乱码原因:
浏览器把中文参数按照UTF-8进行URL编码
Tomcat对获取到的内容进行了ISO-8859-1的URL解码
在控制台就会出现类上å¼ ä¸的乱码,最后一位是个空格
Get请求中文乱码解决方案:
虽然编码不同会导致解码后得到的数据是乱码,但是如果将它们转换为字节,还是一样的
所以可以将得到的乱码转换为字节,在把字节通过UTF-8字符集转换为字符串就可以了
总结:
1.中文乱码解决方案
POST请求和GET请求的参数中如果有中文,后台接收数据就会出现中文乱码问题
GET请求在Tomcat8.0以后的版本就不会出现了
POST请求解决方案是:设置输入流的编码
request.setCharacterEncoding("UTF-8");
注意:设置的字符集要和页面保持一致
通用方式(GET/POST):需要先解码,再编码
new String(username.getBytes("ISO-8859-1"),"UTF-8");
2. URL编码实现方式:
编码: URLEncoder.encode(str,"UTF-8");
解码: URLDecoder.decode(s,"ISO-8859-1");
5. Request请求转发
-
请求转发(forward):一种在服务器内部的资源跳转方式.
-
请求转发的实现方式:
A转发到B,就在A里面写转发代码。 req.getRequestDispatcher("资源B路径").forward(req,resp); -
请求转发资源间共享数据:使用Request对象
需要使用request对象提供的三个方法: 1.存储数据到request域[范围,数据是存储在request对象]中 void setAttribute(String name,Object o); 2.根据key获取值 Object getAttribute(String name); 3.根据key删除该键值对 void removeAttribute(String name); 举例:A转发到B,并在转发的过程中,传递一个数据。 1.在A中通过setAttribute方法,将数据存入request域对象中 2.在B中从request域对象中,通过getAttribute方法获取数据。 -
请求转发的特点
1.请求转发后,浏览器地址栏路径不发生变化。 2.只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器 3.一次请求,可以在转发资源间使用request共享数据。
三. Response对象
Request:使用request对象来获取请求数据
Response:使用response对象来设置响应数据
1. Response设置响应数据功能介绍
- 响应行
设置响应状态码: void setStatus(int sc); - 响应头
设置响应头键值对:void setHeader(String name,String value); - 响应体
对于响应体,是通过字符、字节输出流的方式往浏览器写 获取字符输出流:PrintWriter getWriter(); 获取字节输出流:ServletOutputStream getOutputStream()
2. Respones请求重定向
- Response重定向(redirect):一种资源跳转方式。
重定向讲解:
1.浏览器发送请求给服务器,服务器中对应的资源A接收到请求
2.资源A无法处理请求,给浏览器响应302状态码+location的一个访问资料B路径
3.浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
4.资源B收到请求进行处理,并给浏览器响应结果,这个过程叫重定向。
- 重定向的实现方式
浏览器访问A资源地址,A处理不了请求,将B资源地址返回给浏览器并设置状态码和响应头, 响应头的key为Location,值为B的资源地址。A重定向到B,就在A中设置响应码和响应头。 重定向方法一: //重定向 //1.设置响应状态码 302 response.setStatus(302); //2. 设置响应头 Location response.setHeader("Location","/request-demo/resp2"); 重定向方法二: resposne.sendRedirect("要重定向到的资源地址") 该方法同时设置状态代码为302 - 重定向的特点
1.浏览器地址栏路径发送变化(重定向访问,浏览器是发送的2次请求,所以地址会变化) 2.可以重定向到任何位置的资源(服务内容、外部均可) 3.两次请求,不能在多个资源使用request共享数据(无法通过request对象进行共享数)
3. 路径问题
- 重定向和转发加不加虚拟目录问题
判断依据:重定向需要加虚拟目录,转发不需要加虚拟目录。 因为重定向是从浏览器发送的请求,转发是从内部服务器发送的请求。浏览器使用:需要加虚拟目录(项目访问路径) 服务端使用:不需要加虚拟目录 - 如果更改了虚拟目录地址,重定向的地址都要更改,如何解决?
通过request对象中的getContextPath()方法可以动态获取虚拟目录地址。
4. Response响应字符数据
1.返回一个简单的字符串aaa
将字符数据写回到浏览器:response.getWriter().write("aaa");
2.返回一串html字符串,并且能被浏览器解析
//content-type,告诉浏览器返回的数据类型是HTML类型数据,浏览器会调用浏览器内不同的程序嵌入模块来处理相应的数据。
response.setHeader("content-type","text/html");
writer.write("<h1>aaa</h1>");
3. 返回一个中文的字符串你好,需要注意设置响应数据的编码为utf-8
//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");
注意:一次请求响应结束后,response对象就会被销毁掉,所以不要手动关闭流。
5. Response响应字节数据
将字节数据写回到浏览器:resp.getOutputStream().write(字节数据);
1. 返回一个图片文件到浏览器
1.导入依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
2.调用工具类方法
//fis:输入流
//os:输出流
IOUtils.copy(fis,os);
3.代码
//1. 读取文件
FileInputStream fis = new FileInputStream("d://a.jpg");
//2. 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
//3. 完成流的copy
IOUtils.copy(fis,os);
fis.close();
四、重定向和转发的区别
五、SqlSessionFactory工具类抽取
public class SqlSessionFactoryUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//静态代码块会随着类的加载而自动执行,且只执行一次
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}