当前位置: 首页 > news >正文

Response对象

一、 Response设置响应数据

二、Response实现重定向

这会导致浏览器重新发起一次新的请求(第二次请求),所以用户能在地址栏看到跳转后的新地址。 


1、语法

response.sendRedirect("目标地址");

这个方法会返回一个状态码 302 Found,并在响应头中设置 Location

或者(比较麻烦的写法):

 


2、例子

示例1:重定向到同一个项目中的页面

response.sendRedirect("/myapp/login.jsp");

注意:这里的路径是以Web应用的根路径为起点,所以建议这样写:

response.sendRedirect(request.getContextPath() + "/login.jsp");

确保无论项目部署在哪,路径都能正确跳转


示例2:重定向到外部网站

response.sendRedirect("https://www.baidu.com");

3、和请求转发的区别

特性请求转发 forward()重定向 sendRedirect()
发出请求次数1 次2 次(浏览器又请求一次)
地址栏是否变化❌ 不变✅ 会变
是否共享 request 数据✅ 可以❌ 不可以(因为是两个请求)
是否只能跳转本项目✅ 是❌ 否,可以跳转外部网址
性能较高略低(多一次网络请求)
是否可以跳转到 WEB-INF✅ 可以❌ 不可以(浏览器无法访问 WEB-INF)

4、重定向过程图解

1. 浏览器请求 A↓
2. Servlet A 执行:response.sendRedirect("/home.jsp")↓
3. 服务器响应状态码 302,响应头 Location: /home.jsp↓
4. 浏览器再次请求 /home.jsp↓
5. 返回最终页面

重定向有两种:

        一种是302响应,称为临时重定向;

        一种是301响应,称为永久重定向。

两者的区别是,如果服务器发送301永久重定向响应,浏览器会缓存/hi/hello这个重定向的关联,下次请求/hi的时候,浏览器就直接发送/hello请求了。 

如果要实现301永久重定向,可以这么写:

resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301
resp.setHeader("Location", "/hello");

5、重定向的常见使用场景

场景原因
登录成功后跳转主页避免表单重复提交
未登录用户跳转登录页地址栏要变
完成注册后跳到成功页显式通知用户新页面
跳转到外部页面只能用重定向

请求转发的典型重用场景:

场景原因 / 好处
表单提交失败回显可保留 request 中错误信息
Servlet → JSP 显示JSP 放在 WEB-INF 更安全
多 Servlet 组合调用数据共享,模块化开发
页面控制器统一跳转动态页面跳转
错误页面处理web.xml 中统一配置
登录拦截失败 → 登录页路径私有、数据传递

判断标准(记忆口诀):

“数据要共享 → 用转发,地址需变 → 用重定向”


6、注意事项

  • 重定向路径是客户端行为,必须是可被访问的 URL不能是 WEB-INF

  • 路径写法推荐加上 request.getContextPath(),避免部署路径问题

  • 重定向后不能再向浏览器输出内容(比如 response.getWriter().write(...)


7、总结:

response.sendRedirect() 是一种 客户端跳转,浏览器地址栏会改变,适合登录、退出、跳转外部页面等场景,但无法共享请求数据,不能访问 WEB-INF 中的资源

三、路径问题:是否需要加上虚拟目录

 

四、跨域的问题

1、什么是“跨域”?

跨域是指:浏览器中的 JavaScript 代码,请求了一个“不同源”的资源,就会触发浏览器的同源策略限制,从而引发跨域问题。


2、什么算“不同源”?

浏览器认为“源”由 三部分组成

协议(scheme) + 域名(host) + 端口(port)

只要这三者有任何一个不相同,就是跨域!


举例说明:

场景是否跨域原因
http://a.com 请求 http://a.com❌ 否同源
http://a.com 请求 http://a.com:8080✅ 是端口不同
http://a.com 请求 https://a.com✅ 是协议不同
http://a.com 请求 http://b.com✅ 是域名不同
http://localhost 请求 http://127.0.0.1✅ 是域名不同(即使指向同一台机器)

3、什么情况下会遇到跨域问题?

1. 浏览器中用 JavaScript 发请求(XHR、fetch、axios)

// 页面在 http://localhost:3000
fetch("http://localhost:8080/api/user"); // 跨域!不同端口

只有浏览器才有“同源策略”,所以你在:

  • Postman

  • curl

  • 后端服务器之间互相调用

是不会有跨域限制的!


2. 前端单独部署,后端单独部署

典型的开发结构:

  • 前端 Vue/React 项目:http://localhost:3000

  • 后端接口服务:http://localhost:8080

请求时就会报跨域问题(CORS error)。


常见错误提示:

Access to fetch at 'http://localhost:8080/api/user' 
from origin 'http://localhost:3000' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header...

4、跨域如何解决?

方法原理适用场景
✅ 设置响应头 Access-Control-Allow-Origin告诉浏览器:我允许你跨域来推荐方式,标准做法
反向代理由前端服务器转发请求比如用 Nginx 或 Vite 的 devServer.proxy
CORS 中间件后端框架(Spring Boot、Express 等)提供的跨域支持推荐

5、后端怎么设置 CORS(以 Java 为例)

Spring Boot:

@CrossOrigin(origins = "http://localhost:3000")
@RestController
public class MyController {@GetMapping("/api/user")public User getUser() {return new User("Tom");}
}

或全局配置:

@Configuration
public class CorsConfig {@Beanpublic WebMvcConfigurer config() {return new WebMvcConfigurer() {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://localhost:3000").allowedMethods("*");}};}
}

6、总结:

只要是浏览器中,JS 请求了一个“协议、域名或端口不同”的地址,就会有跨域问题。

解决跨域问题的根本方式是:后端允许这个请求源(设置 CORS 头),或前端使用代理绕过浏览器限制

五、Response设置响应体

  • 响应字符数据:response.getWriter()
  • 响应字节数据:response.getOutputStream()

 

5-1、响应字符数据

 

1. 设置响应内容类型(MIME)和编码

有时你需要设置额外的响应头,告诉浏览器怎么处理这段响应内容:

response.setContentType("text/html;charset=UTF-8");  // 返回 HTML
// 或者
response.setContentType("application/json;charset=UTF-8"); // 返回 JSON

【注意】:

Servlet 容器(比如 Tomcat)会设置默认Content-Type 响应头为 text/html;charset=ISO-8859-1,而浏览器默认会把响应体当作 HTML 解析。

 

若是不加Content-type的响应头,HTML标签默认会被解析,但是若是有中文会出现乱码!

2. 获取字符输出流并写出内容

PrintWriter writer = response.getWriter();
writer.write("<h1>Hello, Servlet!</h1>");
// 或写 JSON 字符串
writer.write("{\"status\": \"ok\"}");
writer.close();

示例:

@WebServlet("/responseDemo03")
public class ResponseDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=UTF-8");// // 必须放在 getWriter() 前面PrintWriter writer = resp.getWriter();// 放前了就会默认使用 ISO-8859-1 编码writer.write("<h1>Hello, Servlet!你好,世界</h1>");writer.write("{\"status\": \"ok\"}");writer.close();}
}

 ·

5-2、响应字节数据(如图片、文件下载)

1. 设置响应类型(以图片为例)

response.setContentType("image/png");

2. 获取字节输出流,写出二进制数据

ServletOutputStream out = response.getOutputStream();
FileInputStream in = new FileInputStream("d:/image.png");byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);
}in.close();
out.close();

【注意】:

        写入完毕后调用flush()却是必须的,因为大部分Web服务器都基于HTTP/1.1协议,会复用TCP连接。

        如果没有调用flush(),将导致缓冲区的内容无法及时发送到客户端

        此外,写入完毕后千万不要调用close(),原因同样是因为会复用TCP连接,如果关闭写入流,将关闭TCP连接,使得Web服务器无法复用此TCP连接。 

六、IOUtils工具类

这个工具类在 Java 中做 IO 流操作非常方便和常用,尤其是你处理 Servlet 请求/响应、上传下载文件时,非常好用。


1、什么是 IOUtils?

IOUtils 是 Apache Commons IO 库中的一个工具类:

org.apache.commons.io.IOUtils

它封装了大量操作 InputStream、OutputStream、Reader、Writer 的静态方法,大大简化了 Java 原本冗长的 IO 操作。


2、常用功能(核心方法)

方法名作用
copy(InputStream in, OutputStream out)复制数据流
toString(InputStream in, Charset encoding)把流转为字符串
toByteArray(InputStream in)把流转为 byte[]
closeQuietly(...)安全关闭流,不抛异常
write(String str, OutputStream out, Charset encoding)写字符串到字节输出流
readLines(InputStream in, Charset encoding)一行一行读取流
contentEquals(InputStream a, InputStream b)比较两个流的内容是否一样

3、使用场景举例


1. Servlet 中读取请求体字符串

String jsonBody = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);

2. 下载文件(把文件流写到响应里)

InputStream in = new FileInputStream("d:/logo.png");
ServletOutputStream out = response.getOutputStream();
IOUtils.copy(in, out);
in.close();
out.close();

3. 上传文件:保存上传的 InputStream 到硬盘

InputStream fileStream = uploadedPart.getInputStream();
FileOutputStream out = new FileOutputStream("upload/xxx.jpg");
IOUtils.copy(fileStream, out);

4. 安全关闭流(避免 try-catch-finally)

IOUtils.closeQuietly(inputStream);  // 不会抛出 IOException

4、引入方式(依赖)

它属于 Apache 的 commons-io 工具包:

<!-- Maven 依赖 -->
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version> <!-- 或最新版 -->
</dependency>
http://www.lryc.cn/news/580080.html

相关文章:

  • Qt应用快速启动的重要性:从系统上电到界面渲染的全链路加速实践
  • 数据结构 之 【堆】(堆的概念及结构、大根堆的实现、向上调整法、向下调整法)(C语言实现)
  • 浏览器中的 preview 和 response 的值不一致和精度问题解决
  • Spring Cloud网关与CI文件配置请求安全性对比
  • MySQL/MariaDB数据库主从复制之基于二进制日志的方式
  • 影楼精修-智能修图Agent
  • Python-将多张图片合并成一张图片调整指定区域的颜色选框工具
  • 应急响应靶场——web3 ——知攻善防实验室
  • 【Unity开发】Unity实现glb模型上传到场景中使用功能
  • 秘塔AI搜索的通过Prompt生成互动式网页探索(二)
  • python脚本编程:使用BeautifulSoup爬虫库获取热门单机游戏排行榜
  • Android发展历程
  • 面试版-前端开发核心知识
  • Oracle如何使用序列 Oracle序列使用教程
  • Java 大视界 -- Java 大数据实战:智能安防入侵检测的特征工程与模型融合全解析
  • 硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
  • Java教程——线程池和future
  • Spring Boot 应用启动时,端口 8080 已被其他进程占用,怎么办
  • 批量PDF转换工具,一键转换Word Excel
  • Jenkins 介绍
  • 后端密码加密:守护用户数据的钢铁长城
  • [尚庭公寓]06-Redis快速入门
  • 通过 Ansys Discovery CFD 仿真探索电池冷板概念
  • Excel 如何进行多条件查找或求和?
  • WPF 右键菜单 MenuItem 绑定图片时只显示最后一个 Icon
  • 深度分析:Microsoft .NET Framework System.Random 的 C++ 复刻实现
  • c# 使用GADL: Can‘t load requested DLL错误处理
  • PixiJS教程(004):点击事件交互
  • gic 中断触发类型
  • Python 中线程和进程在实际项目使用中的区别和联系