HttpServletResponse
1.HttpServletResponse概述
服务器端发送给客户端的数据。 我们在创建Servlet时会覆盖service()⽅法,或doGet()/doPost(),这些⽅法都有两个参数,代表 请求的request和代表响应response。 service⽅法中的response的类型是ServletResponse,⽽doGet/doPost⽅法的response的类型 是HttpServletResponse,HttpServletResponse是ServletResponse的⼦接⼝,功能和⽅法更加 强⼤,所以我们学习HttpServletResponse。
2. response的运⾏流程![](https://i-blog.csdnimg.cn/blog_migrate/aa6f9f78a1c6e0286d7764670b17d791.png)
3.通过抓包⼯具抓取Http响应![](https://i-blog.csdnimg.cn/blog_migrate/e45a8d9bd05999784b81ccfbe92a6534.png)
因为response代表响应,所以我们可以通过该对象分别设置Http响应的响应⾏,响应头和响应体
4.通过response设置响应⾏
响应状态码:服务器告诉客户端浏览器本次请求和响应的⼀个状态。
- 1. 1xx:服务器就收客户端消息,但没有接受完成,等待⼀段时间后,发送1xx多状态码
- 2. 2xx:成功。代表:200
- 3. 3xx:重定向。代表:302(重定向),304(访问缓存)
- 4. 4xx:客户端错误 .。 代表: 404(请求路径没有对应的资源) 405:请求⽅式没有对应的doXxx⽅法
- 5. 服务器端错误。代表:500(服务器内部出现异常)
设置响应⾏的状态码 : setStatus(int sc)
5.通过response设置响应头
常⻅的响应头:
- 1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
- 2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据 in-line:默认值,在当前⻚⾯内打开 attachment;filename=xxx:以附件形式打开响应体。⽂件下载
设置响应头:可以设置也可以添加
- addHeader(String name, String value)
- addIntHeader(String name, int value)
- addDateHeader(String name, long date)
- setHeader(String name, String value)
- setDateHeader(String name, long date)
- setIntHeader(String name, int value) 其中,add表示添加,⽽set表示设置
6 通过response设置响应体
6.1 响应体设置⽂本
- PrintWriter getWriter()
获得字符流,通过字符流的write(String s)⽅法可以将字符串设置到response缓冲区中,随 后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。 - 关于设置中⽂的乱码问题
原因:response缓冲区的默认编码是ISO8859-1,此码表中没有中⽂。 可以通过response的setCharacterEncoding(String charset) 设置response的编码(在 获取流之前设置)。 - 但我们发现客户端还是不能正常显示⽂字
原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系统的编 码,因为我们都是中⽂系统,所以客户端浏览器的默认编码是GBK,我们可以⼿动修改浏览 器的编码是UTF-8。 - 我们还可以在代码中指定浏览器解析⻚⾯的编码⽅式,
通过response的setContentType(String type)⽅法指定⻚⾯解析时的编码是UTF-8:
上⾯的代码不仅可以指定浏览器解析⻚⾯时的编码,同时也内含 setCharacterEncoding 的 功能,所以在实际开发中只要编写response.setContentType("text/html;charset=UTF-8");就可以解决⻚⾯输出中⽂乱码问题response.setContentType("text/html;charset=UTF-8");
@WebServlet("/Demo1Servlet")
public class Demo1Servlet extends HttpServlet {
//响应体
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应输出缓冲区的字符集
// resp.setCharacterEncoding("UTF-8");
//设置响应体(内容)类型 MIME类型 ,在web.xml找对应的类型 ,同时设置输出流的字符集
resp.setContentType("text/html;charset=utf-8");
//获得字符输出流(缓冲流)
PrintWriter writer = resp.getWriter();
//字符流的三种方法 ,tomcat帮我们刷新缓冲区,也不用关闭资源
writer.print("hello ");
writer.print("hello 你好"); //设置缓冲区字符集才不会乱码
writer.println("javaweb ");
writer.write("<h1>"+new Date()+"</h1>");
writer.write("<h1>欢迎来到我的世界!</h1>"); //设置输出的响应体的类型 才会解释Html代码
//模拟表格 ---原理
Map<String , Date> map = Map.of("lucy",new Date(2021,8,4),
"tom",new Date(2012,8,4),
"jack",new Date(2020,8,4),
"rose",new Date(2018,8,4) );
writer.write("<table border='1' cellspacing='0' cellpadding='5'>");
for(String name : map.keySet()){
Date date = map.get(name);
System.out.println(name+map.get("lucy"));
writer.write("<tr><td>lucy</td><td>"+date+"</td></tr>");
}
writer.write("</table>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.2 响应头设置字节
ServletOutputStream getOutputStream() 获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写⼊字节,再由 Tomcat服务器将字节内容组成Http响应返回给浏览器。
6.3 案例 - - 下载文件
@WebServlet("/downloadServlet")
public class downloadServlet extends HttpServlet {
//文件下载
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获得要下载的文件的名字 - 是跟着文件请求的URL - 在html中设置他的名字
String filename = req.getParameter("filename");
System.out.println("2,"+filename);
//2.获得要下载的文件的绝对路径
String path = this.getServletContext().getRealPath("/download/"+filename);
System.out.println(path);
//问题3[下载后的文件名乱码] 解决
filename = URLEncoder.encode(filename, "utf-8");
//问题1 设置响应的内容类型 - MimeType - web.xml
resp.setContentType(this.getServletContext().getMimeType(filename));
//问题2 告诉浏览器,是以附件形式打开文件(下载)
resp.setHeader("Content-Disposition","attachment;filename="+filename);
System.out.println("2,"+filename);
//3.复制文件 - 创建读文件的输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
//4.复制文件 - 获得响应对的输出流
ServletOutputStream os = resp.getOutputStream();
//5.复制文件的过程
byte[] bytes = new byte[1024];
int ln = -1;
while((ln = bis.read(bytes)) != -1){
os.write(bytes,0,ln);
}
//servlet的输出流不需要关闭
bis.close();
System.out.println("下载成功!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<a href="/day04_war_exploded/downloadServlet?filename=a.zip" >a.zip</a><br>
<a href="/day04_war_exploded/downloadServlet?filename=a.jpg" >a.jpg</a><br>
<a href="/day04_war_exploded/downloadServlet?filename=美女.jpg" >美女.jpg</a><br>
</body>
</html>
7.重定向
重定向:资源跳转的⽅式 ,是客户端和服务器端的之间的行为 ,所以路径必须是带应用名的
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/day15/responseDemo2");
//简单的重定向⽅法
response.sendRedirect("/day15/responseDemo2");
7.1 重定向和转发
7.1.1 重定向的特点:redirect
- 1. 地址栏发⽣变化
- 2. 重定向可以访问其他站点(服务器)的资源
- 3. 重定向是两次请求。不能使⽤request对象来共享数据
7.1.2 转发的特点:forward
- 1. 转发地址栏路径不变
- 2. 转发只能访问当前服务器下的资源
- 3. 转发是⼀次请求,可以使⽤request对象来共享数据
7.2 路径写法
路径分类
- 1. 相对路径:通过相对路径不可以确定唯⼀资源
- 如:./index.html ,
- 不以 / 开头以 . 开头路径
- 规则:找到当前资源和⽬标资源之间的相对位置关系
- ./:当前⽬录
- ../:后退⼀级⽬录
- 2. 绝对路径:通过绝对路径可以确定唯⼀资源
- 如:http://localhost/day15/responseDemo2 /day15/responseDemo2
- 以 / 开头的路径
- 规则:判断定义的路径是给谁⽤的?判断请求将来从哪⼉发出
- 给客户端浏览器使⽤:需要加虚拟⽬录(项⽬的访问路径)
- 建议虚拟⽬录动态获取:request.getContextPath()
- <a> ,<form>
- 给服务器使⽤:不需要加虚拟⽬录 转发路径
- 给客户端浏览器使⽤:需要加虚拟⽬录(项⽬的访问路径)
8.JSP
//响应体
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置缓冲区的字符集
//设置响应体(内容)类型 MIME类型 ,在web.xml找对应的类型
resp.setContentType("text/html;charset=utf-8");
//获得字符输出流(缓冲流) ,有两个输出流一个字符流,另一个字节流
PrintWriter writer = resp.getWriter();
//模拟表格
Map<String , Date> map = Map.of("lucy",new Date(2021,8,4),
"tom",new Date(2012,8,4),
"jack",new Date(2020,8,4),
"rose",new Date(2018,8,4) );
req.setAttribute("map",map);
//转让以后上面的响应会被覆盖掉的 -- 在jsp 文件写表格
req.getRequestDispatcher("/table.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%@ page import="java.util.Date" %>
<%@ page import="java.util.Map" %><%--
Created by IntelliJ IDEA.
User: ASUS
Date: 2021/8/4
Time: 11:37
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>表格jsp</title>
<style>
td{
border-color: chartreuse;
}
</style>
</head>
<body>
<%-- body标签里面的<% %>这个标签里面写java代码 --%>
<%-- <% java脚本 %> --%>
<table border="1px" cellspacing="0" cellpadding="10">
<%-- jsp中已经提供了 request 和 response(jsp里面叫out) 对象 直接用就可以 --%>
<% Map<String, Date> map = (Map<String, Date>) request.getAttribute("map");
for(String name : map.keySet()){
Date date = map.get(name);
%>
<tr><td> <% out.write(name); %> </td><td> <% out.write(String.valueOf(date)); %></td></tr>
<% }%>
</table>
</body>
</html>
9.Cookie
用于在客户端存储数据
总结:
response
响应行 setStatus()
响应头 setHeader(name,value)
location Content-Disposition set-cookie
响应体: 输出流
resp.getOutputStream()
resp.getWriter()
注意: 两种流不能同时使用, 不需要关闭
输出流, 响应体内容是先写入到response缓冲区, 缓冲区的字符集就是ISO8859-1
设置缓冲区的字符集: response.setCharacterEncoding()
需要在获得输出流之前设置
客户端还是默认字符集(GBK UTF-8), 可能还需要在客户端手动设置字符集
字符流: 输出页面内容
字节流: 下载文件(文件复制) 验证码(图片)
会话技术: 客户端连接上服务器(应用)开始, 到客户端断掉连接结束, 一次会话
作用: 存数据 session cookie
存数据: 域对象(存任意类型数据) cookie(只能存字符串)
存在服务器上 存在浏览器[客户端]上
cookie: 存在客户端, 不安全, 服务器压力减小
session:存在服务器端, 安全, 服务器压力大
cookie的本质: 响应头信息 set-cookie 将cookie存到客户端
请求头信息 cookie 将cookie携带到服务器端
域对象:
ServletContext: 一个应用
session: 一次会话(可能会有多次请求)
request: 一次请求