解决struts/spring偶尔出现java.lang.IllegalStateException: Cannot call sendRedirect() after the response的问题

本文探讨了一种常见的500错误——Cannot calls sendRedirect() after the response has been committed,并详细分析了其原因及解决方案。通过配置Spring的Bean作用域为prototype解决了由多线程并发引起的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近网站出现一个比较困扰的问题,就是浏览器访问时偶尔出现500错误, 并出现错误堆栈,错误信息如下:Cannot call sendRedirect() after the response has been committed.

google搜索了一下,多数文章提到的原因主要有二:

  1. 在sendRedirect()之前存在html输出.好象如果小量输出的话并且不刷新(flush)也可以.
  2. 在sendRedirect()之后应该马上执行return.

参考链接:http://www.newasp.net/tech/53042.html

但我经过反复分析都未发现上述提到的错误代码逻辑.

最后,竟然发现问题的根源是多线程并发导致的问题.

在spring的配置如下:

<bean id=”xxxAction” class=”com.xxx.XxxAction”>
</bean>

上述Bean的配置中需要添加scope=”prototype”参数才可解决,这个参数的意思是让spring针对一个http请求创建一个Action对象.如果没有这个参数,默认的参数是值是singleton,表示是单例.而单例对象在并发请求时导致多线程重入,从而出现标题中的提到的错误提示.

正确的配置如下:

<bean id=”xxxAction” class=”com.xxx.XxxAction” scope=”prototype”>
</bean>

### Java解决`java.lang.IllegalStateException: Cannot call sendRedirect()`异常 当处理HTTP请求时,在响应已经被提交给客户端后再尝试调用`sendRedirect()`或其他修改响应的方法会导致抛出`IllegalStateException`。这是因为一旦响应被提交,服务器就不能再更改该响应的内容或状态码。 #### 响应已提交的原因 通常情况下,响应会在以下几种情况之一下被认为已被提交: - 已经向客户端发送了一些数据。 - 输出缓冲区已满并刷新到网络连接。 - 显式地通过调用如`flushBuffer()`来清空缓冲区[^1]。 对于文件下载或导出场景中的问题,如果程序试图在一个已经部分完成的响应基础上继续操作,则会发生此错误。例如,在循环内多次执行数据库插入后重定向页面可能会触发这个问题,因为每次迭代都可能导致输出流的变化从而提前结束响应过程[^2]。 #### 解决方案建议 为了防止此类异常的发生,可以采取以下几个措施: 1. **确保逻辑顺序正确** 将所有的业务逻辑放在最后一步之前完成,即先做所有必要的计算、查询等工作,然后再决定是否要改变响应的状态(比如重定向)。这可以通过调整代码结构实现,如下所示: ```java // 执行一系列记录插入操作而不涉及任何与HttpServletResponse有关的操作 for (String id : ids) { try { recordService.insert(new Record(id)); } catch (Exception e) { logger.error("Failed to insert record", e); } } // 完成所有业务处理后再考虑如何回应前端请求 response.sendRedirect(targetUrl); ``` 2. **捕获潜在的早期终止条件** 如果存在某些条件下应该立即停止进一步处理并向用户反馈信息的情况,应当尽早检测这些条件并在适当时候中断流程而不是等到整个事务结束后才做出反应。这样做不仅可以提高性能还能减少不必要的资源消耗。 3. **优化缓冲机制配置** 调整Servlet容器设置以增加默认缓冲大小或者禁用自动冲洗功能可以帮助延迟实际的数据传输直到应用程序显式指示为止。具体做法取决于使用的Web框架和服务端环境,但对于Tomcat来说可以在web.xml里定义参数控制这一点[^3]。 4. **检查是否有其他地方影响了Response对象** 需要注意的是有时候并不是直接由当前代码片段引起的响应提交行为,而是由于第三方库或者其他组件间接改变了Response实例的状态所造成的。因此全面审查项目内的依赖关系也是很重要的。 ```xml <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" compression="on" bufferSize="32768"/> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值