javaweb--09

张开发
2026/4/17 6:53:19 15 分钟阅读

分享文章

javaweb--09
一、Response 继承体系与核心概念1. 继承结构plaintextServletResponseJava 提供的响应对象根接口通用协议响应 ↑ 继承 HttpServletResponseJava 提供的对 HTTP 协议封装的响应对象接口HTTP 专用 ↑ 实现 ResponseFacadeTomcat 定义的实现类Tomcat 内部使用开发者面向接口编程核心逻辑Tomcat 为每个请求创建Response对象传入 Servlet 的service()方法用于设置 HTTP 响应数据请求处理完成后销毁。2. Request Response 分工Request获取客户端发送的 HTTP 请求数据请求行、请求头、请求体Response设置服务器返回给客户端的 HTTP 响应数据响应行、响应头、响应体二、Response 设置响应数据3 大部分HTTP 响应分为响应行、响应头、响应体三部分对应不同的设置方法1. 响应行相关方法响应行格式HTTP/1.1 200 OK核心方法void setStatus(int sc)作用设置响应状态码常用状态码200成功、302重定向、404资源未找到、500服务器内部错误2. 响应头相关方法响应头是服务器发送的键值对信息如Content-Type: text/html核心方法void setHeader(String name, String value)作用设置响应头键值对常用响应头Content-Type告知浏览器响应数据类型、Location重定向地址、Refresh定时刷新3. 响应体相关方法响应体是服务器返回给客户端的核心数据如 HTML、文本、文件等PrintWriter getWriter()获取字符输出流用于输出文本数据HTML、普通字符串等ServletOutputStream getOutputStream()获取字节输出流用于输出二进制数据图片、文件下载等三、Response 响应字符数据常用场景1. 基础使用步骤java运行// 1. 通过Response对象获取字符输出流 PrintWriter writer resp.getWriter(); // 2. 写数据文本/HTML writer.write(aaa); writer.write(h1aaa/h1);2. 解决中文乱码问题关键必须在获取流之前设置响应的编码格式和Content-Type让浏览器以 UTF-8 解析java运行// 推荐写法一行代码同时设置编码和Content-Type response.setContentType(text/html;charsetutf-8); // 等价写法不推荐分两步 // response.setHeader(content-type, text/html); // response.setCharacterEncoding(utf-8); // 再获取流、写数据 PrintWriter writer response.getWriter(); writer.write(你好); writer.write(h1aaa/h1);核心要求必须在第一次获取流之前调用设置编码的方法否则设置无效四、Response 两种输出流核心对比表格流类型获取方法适用场景编码问题字符输出流PrintWriter getWriter()输出文本、HTML 等字符数据需手动设置 UTF-8解决中文乱码字节输出流ServletOutputStream getOutputStream()输出图片、文件等二进制数据无编码问题直接写字节五、字符输出流getWriter()详解1. 基础使用步骤java运行// 1. 通过Response对象获取字符输出流 PrintWriter writer resp.getWriter(); // 2. 写数据文本/HTML writer.write(aaa); writer.write(h1aaa/h1);2. 关键注意事项流的关闭该流不需要手动关闭随着响应结束、response 对象销毁由服务器自动关闭中文乱码问题乱码原因字符输出流默认编码为ISO-8859-1不支持中文解决方案在获取流之前设置响应编码和 Content-Typejava运行// 推荐写法一行代码同时设置编码和Content-Type resp.setContentType(text/html;charsetutf-8);必须在第一次获取流之前调用否则设置无效六、字节输出流getOutputStream()详解1. 基础使用步骤java运行// 1. 通过Response对象获取字节输出流 ServletOutputStream outputStream resp.getOutputStream(); // 2. 写数据字节数组/二进制数据 outputStream.write(字节数据);2. 工具类简化IOUtilscommons-io1导入 Maven 依赖xmldependency groupIdcommons-io/groupId artifactIdcommons-io/artifactId version2.6/version /dependency2使用方法java运行// 一行代码完成流的复制简化文件下载等操作 IOUtils.copy(输入流, 输出流);适用场景文件下载、图片回显等需要传输二进制数据的场景优势无需手动循环读写自动处理流的关闭七、重定向Redirect资源跳转方式1. 重定向原理重定向是一种客户端发起的资源跳转流程如下浏览器请求资源 A资源 A 返回302状态码 Location: 资源B路径响应头浏览器收到响应自动向资源 B 发起新的请求资源 B 处理请求返回响应给浏览器2. 实现方式方式 1原生写法分步设置java运行// 设置302状态码 resp.setStatus(302); // 设置Location响应头指定跳转路径 resp.setHeader(location, /request-demo/resp2);方式 2简化写法推荐java运行// 一行代码完成重定向自动设置302和Location response.sendRedirect(/request-demo/resp2);3. 重定向特点浏览器地址栏路径会发生变化变为资源 B 的路径可以跳转到任意外部资源其他服务器、其他网站是两次请求无法使用request共享数据每次请求对应独立的 request 对象八、请求转发Forward服务器内部跳转1. 转发原理请求转发是服务器内部的资源跳转流程如下浏览器请求资源 A资源 A 在服务器内部将请求转发给资源 B资源 B 处理请求返回响应给浏览器整个过程浏览器只发起一次请求感知不到转发2. 实现方式java运行// 获取请求转发器指定资源B路径调用forward方法完成转发 req.getRequestDispatcher(资源B路径).forward(req, resp);3. 转发特点浏览器地址栏路径不发生变化始终是资源 A 的路径只能转发到当前服务器的内部资源是一次请求可以在转发的资源间通过request共享数据4. Request 域对象转发共享数据通过request对象在转发的资源间传递数据方法如下表格方法作用void setAttribute(String name, Object o)存储数据到 request 域中Object getAttribute(String name)根据 key 获取值void removeAttribute(String name)根据 key 删除该键值对九、重定向 vs 请求转发 核心对比表格对比维度重定向Redirect请求转发Forward跳转本质客户端跳转两次请求服务器内部跳转一次请求地址栏变化变化显示目标资源路径不变显示原资源路径跳转范围可跳外部资源任意 URL仅可跳当前服务器内部资源请求共享无法共享 request 数据可共享 request 数据状态码302200路径要求需加虚拟目录项目访问路径无需加虚拟目录十、路径问题开发高频坑点1. 核心规则谁使用路径浏览器使用的路径必须加虚拟目录项目访问路径服务器端使用的路径不需要加虚拟目录2. 常见场景对照表表格场景使用者是否加虚拟目录示例a href路径超链接浏览器必须加a href/request-demo/resp1跳转/aform action路径表单提交浏览器必须加form action/request-demo/resp2resp.sendRedirect(路径)重定向浏览器必须加response.sendRedirect(/request-demo/resp3);req.getRequestDispatcher(路径)请求转发服务器不需要加request.getRequestDispatcher(resp4).forward(req, resp);3. 动态获取虚拟目录推荐避免硬编码java运行// 动态获取项目虚拟目录适配不同部署环境 String contextPath request.getContextPath(); // 重定向时拼接 response.sendRedirect(contextPath /resp2);十一、完整实战示例Servlet 综合使用java运行WebServlet(/resp1) public class ResponseDemo1 extends HttpServlet { Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 设置响应编码解决中文乱码 response.setContentType(text/html;charsetutf-8); // 2. 响应字符数据 PrintWriter writer response.getWriter(); writer.write(h1这是响应测试/h1); writer.write(你好Response); // 3. 重定向示例 // response.sendRedirect(request.getContextPath() /resp2); // 4. 请求转发示例共享数据 request.setAttribute(msg, 转发测试数据); request.getRequestDispatcher(/resp2).forward(request, response); } Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } WebServlet(/resp2) public class ResponseDemo2 extends HttpServlet { Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(text/html;charsetutf-8); // 获取转发共享的数据 Object msg request.getAttribute(msg); response.getWriter().write(h1resp2 收到数据 msg /h1); } Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

更多文章