Servlet Response 返回服务器的响应

Ramya ·
更新时间:2024-09-20
· 922 次阅读

目录Servlet Response1. Response 的体系结构2 设置 HTTP 响应消息a. 响应行b. 响应头c. 响应体3. 案例:响应重定向a. 主要需求b. 步骤分析c. 重定向特点d. 代码实现e. 效果展示4. 请求转发与请求重定向的区别a. Request 的请求转发b. 请求转发与请求重定向的原理c. 请求转发与请求重定向的区别d. 使用场景5. 案例:响应定时刷新a. 主要需求b. 步骤分析c. 代码实现6. 案例:响应中文a. 主要需求b. 步骤分析c. 解决中文乱码d. 代码实现7. 综合案例:点击切换验证码a. 主要需求b. 用 Java 制作一个验证码c. 前端页面8. 综合案例:文件下载a. 文件目录b. 主要需求c. 方式一:直接使用超文本链接下载文件i. 前端页面ii. 效果iii. 缺点d. 方式二:使用 Servlet 下载文件i. 步骤分析ii. 前端页面iii. DownloadServletiv. 解决文件名中文乱码问题v. 效果 Servlet Response Response 对象表示 web 服务器给浏览器返回的响应信息。 开发人员可以使用 Response 对象的方法,设置要返回给浏览器的响应信息。 1. Response 的体系结构 ServletResponse 接口 | HttpServletResponse 接口 | org.apache.catalina.connector.ResponseFacade 实现类(由 Tomcat 厂商提供的实现类) 2 设置 HTTP 响应消息 a. 响应行 格式:协议/版本号 状态码,例如 HTTP/1.1 200 相关 API: 设置状态码:
void setStatus(int ss) b. 响应头 格式:响应头名称:响应头的值,例如 Location:https://blog.csdn.net/Regino 相关 API: 设置指定头名称和对应的值:
void setHeader(String name, String value) c. 响应体 相关 API(输出流对象): 获取输出字符流:
PrintWriter getWriter() 获取输出字节流:
ServletOutputStream getOutputStream()

注意:

在同一个 Servlet 中,二种类型的输出流不能同时存在,互斥。 向浏览器输出文件时用字节流,输出文本内容时用字符流。 3. 案例:响应重定向 a. 主要需求 用户访问 AServlet 后,服务器告诉浏览器重定向到 BServlet。 b. 步骤分析 方式一: 设置状态码(响应行):
response.setStatus(302); 设置响应头 Location:
response.setHeader("Location","重定向网络地址"); 方式二: Response 封装了专门处理重定向的方法:
response.sendRedirect("重定向网络地址"); c. 重定向特点 地址栏会发生改变; 重定向是二次请求; 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源。 不能使用 Request 域共享数据 d. 代码实现 AServlet: import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/AServlet") public class AServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /*System.out.println("AServlet执行了...."); // 1.设置状态码 response.setStatus(302); // 2.设置响应头 response.setHeader("Location","/webappPractice2/BServlet");*/ // 1.Response封装的专门处理重定向的方法 response.sendRedirect("/webappPractice2/BServlet"); } } BServlet: import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/BServlet") public class BServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } e. 效果展示 访问 http://localhost:8080/webappPractice2/AServlet,页面输出:
在这里插入图片描述 4. 请求转发与请求重定向的区别 a. Request 的请求转发 AServlet: import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/AServlet") public class AServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //往Request域中存储数据 request.setAttribute("name","Regino"); //请求转发到BServlet request.getRequestDispatcher("/BServlet").forward(request,response); } } BServlet: import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/BServlet") public class BServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决向浏览器输出中文乱码问题 response.setContentType("text/html;charset=utf-8"); //从Request域中取出数据 String name = (String) request.getAttribute("name"); //向浏览器输出 response.getWriter().write("从Request域中获取到的数据:"+ name); } } 访问 http://localhost:8080/webappPractice2/AServlet,页面输出:
在这里插入图片描述 b. 请求转发与请求重定向的原理 Request 转发请求原理: Tomcat 服务器创建 AServlet 的对象后,又创建一对 Request 与 Response 对象并用来调用 AServlet 的 doPost 方法。 当 Tomcat 服务器读到 AServlet 的转发请求时,会马上利用 AServlet 的那对 Request 与 Response 对象调用 BServlet 的 doPost 方法,并没有创建一对新的 Request 与 Response 对象。 Response 请求重定向的原理: Tomcat 服务器创建 AServlet 的对象后,又创建一对 Request 与 Response 对象并用来调用 AServlet 的 doPost 方法。 当 Tomcat 服务器读到 AServlet 的重定向请求时,会马上把该请求返回给浏览器;浏览器发送重定向请求后,Tomcat 服务器读到浏览器的第二次请求时,会马上创建 BServlet 的对象,然后用新的一对 Request 与 Response 对象调用 BServlet 的 doPost 方法。 c. 请求转发与请求重定向的区别 请求转发的时候浏览器地址栏不变化的,请求重定向浏览器地址栏是变化的。 请求转发浏览器发出一次请求,请求重定向浏览器发出了两次请求。 请求转发的服务器只有一对请求和响应对象,而请求重定向的服务器有两对请求和响应对象。 请求转发发生在服务器,而请求重定向发生在浏览器。 地址不同,重定向需要加 项目根路径/,而请求转发是模块内部的跳转,所以不用。 / 在进行资源跳转的时候,如果是给服务器去使用,那么 / 代表了 http://localhost:8080/项目根路径;如果是给浏览器去使用的时候,那么/ 代表了 http://localhost:8080/d. 使用场景 如果需要传递数据(Request域),使用转发; 如果不需要传递数据(Request域),使用重定向。 5. 案例:响应定时刷新 a. 主要需求 在当前页面停留 3 秒钟之后,跳转到个人博客首页。 b. 步骤分析 通过 Response 设置响应头 Refresh:
response.setHeader("Refresh","间隔时间(秒);跳转页面"); c. 代码实现 RefreshServlet: import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/refreshServlet") public class RefreshServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 通过Response设置响应头Refresh response.setHeader("Refresh", "3;https://blog.csdn.net/Regino"); response.setContentType("text/html;charset=utf-8"); response.getWriter().write("操作成功,3秒后跳转到Regino博客首页..."); } } 6. 案例:响应中文 a. 主要需求 向页面输出中文数据没有乱码。 b. 步骤分析 通过 Response 获取字符输出流:
PrintWriter pw = response.getWriter(); 通过字符输出输出文本:
pw.write("中文...."); c. 解决中文乱码 指定服务器响应编码方式:
response.setCharacterEncoding("GBK"); 统一浏览器和服务器编码:
response.setContentType("text/html;charset=utf-8");

request.setCharacterEncoding("utf-8"); 应该在获取请求参数之前设置,若已获取请求参数,此时还没有设置过编码,Tomcat 会设置默认 Post 请求参数编码为 ISO8859_1,那么再设置成 UTF-8 也无效了。所以应该用 response.setContentType("text/html;charset=utf-8");

d. 代码实现 EncodeServlet : import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/encodeServlet") public class EncodeServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 指定服务器响应编码方式 // response.setCharacterEncoding("UTF-8");//出现乱码 // 统一浏览器和服务器编码 response.setContentType("text/html;charset=utf-8"); // 1. 通过response获取字符输出流 PrintWriter pw = response.getWriter(); // 2. 通过字符输出输出文本 pw.write("中文...."); } } 7. 综合案例:点击切换验证码 a. 主要需求 在页面展示登录验证码,点击此验证码可以更换新的验证码 。 作用:防止表单的恶意提交。 b. 用 Java 制作一个验证码 使用画图工具; 指定宽和高; 指定背景色; 生成四位随机数; 制作干扰线; 通过 Response 响应到浏览器。 CheckcodeServlet: import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @WebServlet("/CheckcodeServlet") public class CheckcodeServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 创建画布 int width = 120; int height = 40; BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获得画笔 Graphics g = bufferedImage.getGraphics(); // 填充背景颜色 g.setColor(Color.white); g.fillRect(0, 0, width, height); // 绘制边框 g.setColor(Color.red); g.drawRect(0, 0, width - 1, height - 1); // 生成随机字符 // 准备数据 String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; // 准备随机对象 Random r = new Random(); // 声明一个变量 保存验证码 String code = ""; // 书写4个随机字符 for (int i = 0; i < 4; i++) { // 设置字体 g.setFont(new Font("宋体", Font.BOLD, 28)); // 设置随机颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); String str = data.charAt(r.nextInt(data.length())) + ""; g.drawString(str, 10 + i * 28, 30); // 将新的字符 保存到验证码中 code = code + str; } // 绘制干扰线 for (int i = 0; i < 6; i++) { // 设置随机颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height)); } // 将验证码 打印到控制台 System.out.println(code); // 将验证码放到session中 request.getSession().setAttribute("code_session", code); // 将画布显示在浏览器中 ImageIO.write(bufferedImage, "jpg", response.getOutputStream()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } c. 前端页面 index.html: Title Servlet随机验证码
// 给图片绑定一个点击事件 document.getElementById('img1').onclick=function () { // 重置src路径,重写发送请求 this.src='/webappPractice2/CheckcodeServlet?'+new Date().getTime(); // 后面加一个毫秒值的时间戳来欺骗浏览器,否则因为是同一个请求,验证码不刷新 }
访问 http://localhost:8080/webappPractice2/static/index.html,页面展示:
在这里插入图片描述 8. 综合案例:文件下载 a. 文件目录

在这里插入图片描述

b. 主要需求 用户点击页面的链接,浏览器开始下载文件。 c. 方式一:直接使用超文本链接下载文件 i. 前端页面 Download

文件下载

超文本链接下载
word文档
压缩包下载
图片下载
ii. 效果 访问 http://localhost:8080/webappPractice2/static/index.html 后,页面显示:
在这里插入图片描述 压缩包和word文档能直接下载,但是图片被直接被打开了。 iii. 缺点 如果要下载的是浏览器可解析的媒体类型,是直接打开而不是下载。 不能判断用户是否登录(VIP 权限问题),并进行限制。 d. 方式二:使用 Servlet 下载文件 i. 步骤分析 被下载文件的字节输入流:
FileInputStream Response 字节输出流:
ServletOutputStream 告知客户端下载文件的 MIME 类型(最新的浏览器此步骤可以省略):
Content-Type:MIME类型 告知浏览器以附件的方式保存:
Content-Disposition:attachment;filename=文件名 ii. 前端页面 Download

文件下载

超文本链接下载
word文档
压缩包下载
图片下载
Servlet下载
word文档
word文档
图片下载
iii. DownloadServlet import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; @WebServlet("/downloadServlet") public class DownloadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.获取请求文件名 String filename = request.getParameter("filename"); // 2.获取文件真实路径,封装到字节输入流 ServletContext servletContext = request.getServletContext(); String realPath = servletContext.getRealPath("/download/" + filename); FileInputStream in = new FileInputStream(realPath); // 3.告诉浏览器MIME类型 String mimeType = servletContext.getMimeType(filename); response.setContentType(mimeType); // 4.告诉浏览器以附件方式保存 // 解决中文乱码和浏览器兼容性 String userAgent = request.getHeader("user-agent"); // 调用工具类处理 filename = DownLoadUtils.getName(userAgent, filename); response.setHeader("content-disposition", "attachment;filename=" + filename); // 5.获取字节输出流 ServletOutputStream out = response.getOutputStream(); // 6.IO流的拷贝 byte[] b = new byte[4096];// 4kb int len = -1; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } // 7.释放资源 out.close(); // out流对象,可以交给Tomcat关闭 in.close(); } } iv. 解决文件名中文乱码问题 如果该下载文件名是中文的话,会出现乱码。 需要考虑浏览器兼容性问题: 谷歌和绝大多数的浏览器是通过 URL编码,相关方法:
URLEncode() 编码
URLDecode() 解码 火狐浏览器是 base64编码 判断浏览器不同编码的工具类 DownLoadUtils: import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import sun.misc.BASE64Encoder; public class DownLoadUtils { public static String getName(String agent, String filename) throws UnsupportedEncodingException { if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filename = URLEncoder.encode(filename, "utf-8"); } return filename; } } v. 效果 访问 http://localhost:8080/webappPractice2/static/index.html 后,页面显示:
在这里插入图片描述 图片、压缩包和word文档都能被直接下载。

原文链接:https://qwert.blog.csdn.net/article/details/105556856


作者:Regino



服务器 response Servlet

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章