什么是Request响应和Response对象
实际上就是指Request对象和Response对象。
一个get或者post请求实际上就是一些有规律的字符串,Tomcat将这些字符串获取并且封装成一个可操作的对象。
通过Response对象可以设置响应数据,也就是Tomcat想要给浏览器发送哪些内容。
举例:
response.setHeader()设置响应头
response.getWriter.write()设置响应体
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
请求头:User-Agent:Mozilla/5.0 Chrome/91.0.4472.106
(浏览器的版本信息)
请求体:username=xiaoming&password=123
//获取字符输入流
BufferedReader br=req.getReader();
//读取数据
String line=br.readLine();//按行读取
System.out.println(line);
总结:GET请求方式获取请求数据采用getQueryString方法。post请求方法获取请求参数采用字节输入流。
Request通用方式获取请求数据-GET和Post
我们可以采用以下通用逻辑,代码底层会自动的判断请求方式并且采用不同的处理逻辑。
//获取请求方式
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[]>泛型。
IDEA模版创建HttpServlet
Request请求中文乱码问题
1、POST解决方案
POST读取数据采用字符缓冲流,我们可以改变输入流的编码格式。
2、GET解决方案
首先来看一下我们的编码和解码流程
1、张三这两个汉字变成二进制是通过UTF-8进行编码。
2、浏览器通过URL编码将每个字节转换为两个十六进制数字,并且在前面加上%发送给服务端,服务端使用URL解码将这串字符转换成二进制数字。
3、解码采用的是ISO-8859-1这种解码方式。
由此我们可以发现问题,UTF-8编码,ISO-8859-1解码,出现错误。
但由于Tomcat无法修改解码方式,我们需要采取一种折中的方式解决这个问题。
解决方法:
这串数据的二进制数据其实是一样的,那么我们可以将ISO-8859-1编码的数据进行解码,得到正确的二进制数据,再将这个二进制数据通过UTF-8的方式进行编码。
注意:在8版本及以上,Tomcat默认编码已经修改为Utf-8,不存在中午跟乱码问题。
Request请求转发
随着转发,request对象被转发到下一个url目的地,我们将转发间共享的数据封装在request中。
请求转发的特点:
1、浏览器地址不发生改变
2、只能转发到当前服务器的内部资源。(不可以访问外部网站)
3、一次请求,可以在转发的request间共享数据。
Response对象
和request对象相似,为响应对象,用来设置响应数据。
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.setStatus(302);
resp.setHeader("location(资源头-固定的)","资源b的路径");
简化实现方式:
resp.sendRedirect(location:"xxxxxx");
重定向的特点:
1、浏览器路径发生变化
2、可以定位到任意位置的资源(服务器内部、外部都可以)(可以访问外部网站)
3、两个请求,不能再多个资源间使用request。
路径问题-我们如何书写路径?
我们要知道路径是给谁使用
浏览器使用:需要添加虚拟目录(项目访问目录)
服务端使用:不需要添加虚拟目录
1、href超链接给浏览器,需要。2、表单给超链接,需要。3、请求转发,服务端内部,不需要。4、重定向,浏览器跳转,需要。
为了降低代码的耦合性,我们可以在pom.xml文件中手动的配置虚拟路径。
<configuration>
<path> xxxx </path>
</configuration>
String contextPath=request.getContextPath();
Response响应字符/字节数据
字符数据
字节数据
byte[] buff=new byte[1024];
int len=0;
while((len=fis.read(buff))!=-1){
os.write(buff,0,len);
}
fis.close();
我们可以使用maven导入IO相关的工具类,非常好用简化书写。
IOUtils.copy(输入流,输出流);