getWriter() has already been called for this response

这个错误通常表明您尝试从Spring MVC返回一个已使用的HttpServletResponse对象。

原因:这可能是由于直接调用HttpServletResponsegetWriter()getOutputStream()方法,或者由于在控制器方法中抛出异常而自动调用HttpServletResponsewrite()方法。

修改建议:您可以确保在控制器方法中没有调用任何HttpServletResponse的方法,并且不要在控制器方法中抛出异常。

规避建议:如果需要向客户端返回响应,请使用返回相应的对象,例如StringModelAndViewRedirectView。 此外,您还可以使用@ResponseStatus@ExceptionHandler注解来处理异常情况,并生成适当的响应。

问题重现

ResponsePostInterceptor 里注入response.getWriter().write

package com.zhangziwa.practisesvr.interceptor;import com.zhangziwa.practisesvr.utils.response.ResponseContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Component
public class ResponsePostInterceptor implements HandlerInterceptor {# 调用 response.getWriter().write@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.err.println("***ResponsePostInterceptor.preHandle***");response.setHeader("test-test", "test-test");response.getWriter().write("Response content");response.flushBuffer();return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.err.println("***ResponsePostInterceptor.postHandle***");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.err.println("***ResponsePostInterceptor.afterCompletion***");ResponseContext.clear();}
}

Controller 正常返回 ResponseEntity

    @RequestMapping(value = "/getAllStudents4", method = RequestMethod.GET)public ResponseEntity<List<Student>> getAllStudents4() {System.err.println("***Controller.getAllStudents4***");List<Student> students = userService.listStudents3(1, 5);HttpHeaders httpHeaders = new HttpHeaders();httpHeaders.add("test", "test");return ResponseEntity.ok().headers(httpHeaders).contentType(MediaType.APPLICATION_JSON).body(students);}

ResponseBodyAdviceResponseEntity进行增强

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import static java.util.Objects.nonNull;@ControllerAdvice
public class ResponsePostAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {System.err.println("***ResponsePostAdvice.supports***");return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class clazz, ServerHttpRequest request, ServerHttpResponse response) {System.err.println("***ResponsePostAdvice.beforeBodyWrite***");HttpHeaders headers = response.getHeaders();// 分页信息添加到ServerHttpResponseHttpHeaders headersContext = ResponseContext.getHeaders();if (nonNull(headersContext) && !headersContext.isEmpty()) {headersContext.forEach((key, values) -> values.forEach((value) -> {headers.addIfAbsent(key, value);}));}// 状态码添加到ServerHttpResponseif (nonNull(ResponseContext.getResponseCode())) {response.setStatusCode(ResponseContext.getResponseCode());}# 这里会报错return body;}
}

异常拦截GlobalExceptionHandler

@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseEntity<String> handleException(Exception ex) {System.err.println("***GlobalExceptionHandler.handleException:" + ex.getMessage() + "***");return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred");}@ExceptionHandler(NotFoundException.class)public ResponseEntity<String> handleNotFoundException(NotFoundException ex) {System.err.println("***GlobalExceptionHandler.handleNotFoundException***");return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Resource not found");}
}

调用路径分析

# 拦截器的preHandle (这里注入了response.getWriter().write)
***ResponsePostInterceptor.preHandle***
# Controller层
***Controller.getAllStudents4***# ResponsePostAdvice进行增强后返回ServerHttpResponse
***ResponsePostAdvice.supports***
***ResponsePostAdvice.beforeBodyWrite***
## 这里报IllegalStateException了 被 @ControllerAdvice修饰的GlobalExceptionHandler 拦截到
***GlobalExceptionHandler.handleException:getWriter() has already been called for this response***# 异常返回ResponseEntity 又被ResponsePostAdvice捕捉然后进行增强
***ResponsePostAdvice.supports***
***ResponsePostAdvice.beforeBodyWrite***
# 又报IllegalStateException,但是此时没被GlobalExceptionHandler 拦截
java.lang.IllegalStateException: getWriter() has already been called for this response
# 吃啥程序蹦了,故ResponsePostInterceptor.postHandle未执行。但是afterCompletion是否异常都会执行,所以执行了
***ResponsePostInterceptor.afterCompletion***# 这里又执行一遍拦截器,但是未进入Controller层,不是很懂
***ResponsePostInterceptor.preHandle***
***ResponsePostInterceptor.postHandle***
***ResponsePostInterceptor.afterCompletion***

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/618228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python企业级技能

python企业级技能 @contact: 微信 1257309054 @file: 书籍 @time: 2024/1/13 11:16 @author: LDC内容简介 ​ 通过本书籍可以学习到python在企业中是如何使用的,用来解决哪些业务问题? ​ python

C#人力资源管理系统源码

C#人力资源管理系统源码 源码描述&#xff1a; 该系统利用asp.net中mvc,linq搭建开发&#xff0c; 分权限管理 权限级别分为&#xff1a;管理员&#xff0c;经理&#xff0c;专员&#xff0c;员工等 管理员可以管理角色、菜单 经理可以管理 组织规划&#xff0c;员工管理&#…

python,序列的切片

序列的切片就是指从一个序列中取出子序列 语法&#xff1a; 序列[起始下标&#xff1a;结束下标&#xff1a;步长] 步长为1表示一个一个的取元素&#xff0c;步长为2表示每次跳过一个元素的取元素&#xff0c;步长为负数表示反向切片&#xff0c;取元素时取到结束下标&#…

分裂联邦学习论文-混合联邦分裂学习GAN驱动的预测性多目标优化

论文标题&#xff1a;《Predictive GAN-Powered Multi-Objective Optimization for Hybrid Federated Split Learning》 期刊&#xff1a;IEEE Transactions on Communications, 2023 一、论文介绍 背景&#xff1a;联邦学习作为一种多设备协同训练的边缘智能算法&#xff0…

linux 安装sipp

sudo apt-get install libnet1-dev libpcap0.8-dev openssl libssl-dev 从 sipp - Browse /sipp/3.2 at SourceForge.net 下载最新版的sipp.svn.tar.gz&#xff0c;解压之后就得到一个rpm文件 tar -zxvf sipp.svn.tar.gz cd sipp make pcapplay_ossl

SpringBoot中 如何优雅的 重试调用 第三方API?

引言 在实际的应用中&#xff0c;我们经常需要调用第三方API来获取数据或执行某些操作。然而&#xff0c;由于网络不稳定、第三方服务异常等原因&#xff0c;API调用可能会失败。为了提高系统的稳定性和可靠性&#xff0c;我们通常会考虑实现重试机制。 本文将深入探讨如何在…

MySQL深入——12

我们今天来谈谈临键锁 next-key lock&#xff08;临键锁&#xff09;是记录锁与间隙锁的结合&#xff0c;锁定一个范围。 他被主要应用于解决幻读的问题 临键锁的几个要点&#xff1a; 1.他是前开后闭区间 2.查找过程中访问到的对象会加锁 优化&#xff1a;1.在索引上的等…

2401C++,C++模板用来解耦

原文 模板还可用来解耦. 看这样一个场景: 类 连接 { 公:空 发送() {//干活输出<<缓冲_<<"\n";//...} 私:串 缓冲_; };有这样一个连接对象,它里面有个发送函数,发送的逻辑比较复杂(这里省略具体逻辑),然后刚好另外一个A对象可复用这部分代码,于是就把发送…

多语言生成式语言模型用于零样本跨语言事件论证提取(ACL2023)

1、写作动机&#xff1a; 经过预训练的生成式语言模型更好地捕捉实体之间的结构和依赖关系&#xff0c;因为模板提供了额外的声明性信息。先前工作中模板的设计是依赖于语言的&#xff0c;这使得很难将其扩展到零样本跨语言转移设置。 2、主要贡献&#xff1a; 作者提出了一…

AI-图片转换中国风动漫人物

&#x1f3e1; 个人主页&#xff1a;IT贫道-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;私聊博主加WX好友&#xff0c;获取更多资料哦~ &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. AI卡通秀原理 2. …

【PyQt小知识 - 8】:QFileDialog — 文件选择对话框(选择文件夹/文件)

文章目录 QFileDialog的介绍和使用 QFileDialog的介绍和使用 QFileDialog是Qt框架中提供的一个文件选择对话框。它可以让用户通过图形界面的方式选择文件或目录&#xff0c;并提供了许多与文件操作相关的实用功能&#xff0c;例如文件过滤、文件类型限制、文件名默认值、默认目…

17. C++ static、const 和 static const 类型成员变量声明以及初始化

1. C static、const 和 static const 类型成员变量声明以及初始化 const 定义的常量在超出其作用域之后其空间会被释放&#xff1b; static 定义的静态常量在函数执行后不会释放其存储空间&#xff1b; 1.2 static static 表示的是静态的 类的静态成员函数、静态成员变量是…

ASP.NET进销存系统源码

ASP.NET进销存系统源码 功能介绍&#xff1a; 财务 销售清单&#xff0c;填写销售单&#xff0c;客户管理&#xff0c;添加客户资料 销售 销售清单&#xff0c;填写销售单&#xff0c;客户管理&#xff0c;添加客户资料 仓库 仓库结存&#xff0c;仓库盘点&#xff0c;盘点结…

初学unity学习七天,经验收获总结

初学unity七天&#xff0c;经验收获总结 学习就是认识新观念和新想法的过程。 假如人们始终以同一种思维方式来考虑问题的话&#xff0c;那么始终只会得到同样的结果。 因为我对你讲述的许多内容是你以前从未接触过的&#xff0c;所以我建议你&#xff0c;在你还没有做之前&…

确保CentOS系统中的静态HTTP服务器的数据安全

确保CentOS系统中的静态HTTP服务器的数据安全是一项重要的任务&#xff0c;它有助于保护网站免受未经授权的访问、数据泄露和其他安全威胁。以下是一些关键步骤和最佳实践&#xff0c;以确保CentOS系统中静态HTTP服务器的数据安全&#xff1a; 限制访问权限确保只有授权用户可…

Springboot+vue整合 支付宝沙箱支付

可以完成的功能&#xff1a; 一、拉起支付 二、异步回调 三、掉单处理 四、超时关闭 五、订单退款

使用ffmpeg对视频进行静音检测

1 原始视频信息 通过ffmpeg -i命令查看视频基本信息 ffmpeg version 6.1-essentials_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developersbuilt with gcc 12.2.0 (Rev10, Built by MSYS2 project)configuration: --enable-gpl --enable-version3 --enable-sta…

uniapp项目 插件市场下载pdd-date-picker【年月日选择器】路径不对的问题

从HBuilder插件市场下载pdd-date-picker年月日插件之后 按照t它的官方问的进行引入你会发现路径不对&#xff0c;我们需要再自己的项目中重新去查看一下路径 下面是官方文档给出的路径 import pddDatePicker from ../../components/pdd-date-picker/index.vue我们需要将上面的…

ASP.NET房屋中介管理系统源码

ASP.NET房屋中介管理系统源码 房屋中介系统是非常实用的&#xff0c;不仅可以详细的记录房源信息、用户信息等&#xff0c; 同时本系统能够自动去查找和客户需求匹配的房源&#xff0c;可以方便客户同时提高使用者的工作质量与效率。

D25XB80-ASEMI开关电源桥堆D25XB80

编辑&#xff1a;ll D25XB80-ASEMI开关电源桥堆D25XB80 型号&#xff1a;D25XB80 品牌&#xff1a;ASEMI 封装&#xff1a;GBJ-5&#xff08;带康铜丝&#xff09; 特性&#xff1a;插件、整流桥 平均正向整流电流&#xff08;Id&#xff09;&#xff1a;25A 最大反向击…