什么是Request响应和Response对象

实际上就是指Request对象和Response对象。

一个get或者post请求实际上就是一些有规律的字符串,Tomcat将这些字符串获取并且封装成一个可操作的对象。

 通过Response对象可以设置响应数据,也就是Tomcat想要给浏览器发送哪些内容。

举例:

response.setHeader()设置响应头

response.getWriter.write()设置响应体

resp对象适合返回枚举值吗_servlet

Request继承体系

Java没有提供实现类,Tomcat提供了实现类,这是因为数据被Tomcat解析封装。

谁来解析参数,谁就要对方法进行实现,所以Tomcat创建实现类。

由于Service方法由Tomcat调用,所以Service方法的参数也是Tomcat创建,也就是request和response对象。

我们想要使用request对象,只需要查阅Java EE中RequestFacade接口API就好。

Request获取请求数据

http协议结构之request: 

请求行:GET/request-demo/req?username=xiaoming

resp对象适合返回枚举值吗_java_02

请求头:User-Agent:Mozilla/5.0 Chrome/91.0.4472.106

(浏览器的版本信息)

resp对象适合返回枚举值吗_数据_03

请求体:username=xiaoming&password=123

resp对象适合返回枚举值吗_java_04

//获取字符输入流
BufferedReader br=req.getReader();
//读取数据
String line=br.readLine();//按行读取
System.out.println(line);

总结:GET请求方式获取请求数据采用getQueryString方法。post请求方法获取请求参数采用字节输入流。

Request通用方式获取请求数据-GET和Post

resp对象适合返回枚举值吗_servlet_05

我们可以采用以下通用逻辑,代码底层会自动的判断请求方式并且采用不同的处理逻辑。 

//获取请求方式
String method=this.getMethod();
if("GET".equals(method)){
    //GET方法获取参数
    params=this.getQueryString();
}else if("POST".equals(method)){
    //POST方法获取参数
    params=reader.readline();
}

此方法会将字符串自动的切割并且封装成一个map集合,其数据类型为Map<String,String[]>泛型。

resp对象适合返回枚举值吗_tomcat_06

 IDEA模版创建HttpServlet

resp对象适合返回枚举值吗_resp对象适合返回枚举值吗_07

 

Request请求中文乱码问题

1、POST解决方案

POST读取数据采用字符缓冲流,我们可以改变输入流的编码格式。

resp对象适合返回枚举值吗_数据_08

 2、GET解决方案

首先来看一下我们的编码和解码流程

1、张三这两个汉字变成二进制是通过UTF-8进行编码。

2、浏览器通过URL编码将每个字节转换为两个十六进制数字,并且在前面加上%发送给服务端,服务端使用URL解码将这串字符转换成二进制数字。

3、解码采用的是ISO-8859-1这种解码方式。

由此我们可以发现问题,UTF-8编码,ISO-8859-1解码,出现错误。

但由于Tomcat无法修改解码方式,我们需要采取一种折中的方式解决这个问题。

resp对象适合返回枚举值吗_tomcat_09

resp对象适合返回枚举值吗_java_10

 解决方法:

这串数据的二进制数据其实是一样的,那么我们可以将ISO-8859-1编码的数据进行解码,得到正确的二进制数据,再将这个二进制数据通过UTF-8的方式进行编码。

resp对象适合返回枚举值吗_resp对象适合返回枚举值吗_11

resp对象适合返回枚举值吗_java_12

注意:在8版本及以上,Tomcat默认编码已经修改为Utf-8,不存在中午跟乱码问题。 

 Request请求转发

resp对象适合返回枚举值吗_数据_13

随着转发,request对象被转发到下一个url目的地,我们将转发间共享的数据封装在request中。 

resp对象适合返回枚举值吗_java_14

 请求转发的特点:

1、浏览器地址不发生改变

2、只能转发到当前服务器的内部资源。(不可以访问外部网站)

3、一次请求,可以在转发的request间共享数据。

Response对象

和request对象相似,为响应对象,用来设置响应数据。

resp对象适合返回枚举值吗_数据_15

HTTP协议结构之response:

1、响应行:HTTP/1.1 200 OK

void setStatus(int sc);设置响应码

2、响应头:Content-Type:text/html

void setHeader(String name,String value);设置响应头(告诉浏览器以html的方式解析响应体)

3、响应体:<html><head></head><body></body></html>

PrintWriter getWriter();获取字符输出流,输出文本内容

ServletOutputStream getOutputStreama();获取字节输出流,输出音频图片内容

Response重定向

将请求拒绝并且跳转交给别人处理的方式。 

resp对象适合返回枚举值吗_tomcat_16

resp.setStatus(302);

resp.setHeader("location(资源头-固定的)","资源b的路径");

简化实现方式:

resp.sendRedirect(location:"xxxxxx");

重定向的特点:

1、浏览器路径发生变化

2、可以定位到任意位置的资源(服务器内部、外部都可以)(可以访问外部网站)

3、两个请求,不能再多个资源间使用request。

路径问题-我们如何书写路径?

我们要知道路径是给谁使用

浏览器使用:需要添加虚拟目录(项目访问目录)

服务端使用:不需要添加虚拟目录

resp对象适合返回枚举值吗_java_17

 1、href超链接给浏览器,需要。2、表单给超链接,需要。3、请求转发,服务端内部,不需要。4、重定向,浏览器跳转,需要。

为了降低代码的耦合性,我们可以在pom.xml文件中手动的配置虚拟路径。

<configuration>

<path> xxxx </path>

</configuration>
String contextPath=request.getContextPath();

Response响应字符/字节数据

字符数据 

resp对象适合返回枚举值吗_java_18

 

resp对象适合返回枚举值吗_resp对象适合返回枚举值吗_19

字节数据

byte[] buff=new byte[1024];
int len=0;
while((len=fis.read(buff))!=-1){
    os.write(buff,0,len);
}
fis.close();

 我们可以使用maven导入IO相关的工具类,非常好用简化书写。

resp对象适合返回枚举值吗_resp对象适合返回枚举值吗_20

IOUtils.copy(输入流,输出流);