Springboot thymeleaf 异常:getOutputStream() has already been called for this response 解决

本文记录了一次在实现验证码功能时遇到的输出流冲突问题及其解决方案。通过在控制器方法上添加@ResponseBody注解,解决了因先后调用getOutputStream()和getWriter()导致的java.lang.IllegalStateException异常。

问题产生背景:博主最近加了一个生成验证码的功能,然后配置巴拉巴拉配置好了,发出请求获取验证码。


这个是controller的代码

    @RequestMapping("/vaildCode")
    public void defaultKaptcha() {
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        OutputStream out = null;
        try {
            //生产验证码字符串并保存到session中
            String createText = defaultKaptcha.createText();
            request.getSession().setAttribute("vrifyCode", createText);
            //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
            //定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组
            byte[] captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("image/jpeg");
            out = response.getOutputStream();
            out.write(captchaChallengeAsJpeg);
            out.flush();
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                jpegOutputStream.close();
                if (out != null) {
                    out.close();
                }
                System.gc();
            } catch (IOException e) {
                logger.error(e.getMessage());
            }
        }
    }

idea控制台报错了,简单点说就是这一段的报错,其中问题出现在ThymeleafView.java:354

java.lang.IllegalStateException: getOutputStream() has already been called for this response
    at org.apache.catalina.connector.Response.getWriter(Response.java:624) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:211) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:109) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:354) ~[thymeleaf-spring5-3.0.9.RELEASE.jar:3.0.9.RELEASE]

定到源码发现
viewTemplateEngine.process(templateName, processMarkupSelectors, context, response.getWriter());
response.getWriter(),而且网上多数答案都说是因为这里引起的,好吧╮(╯-╰)╭,但是大多数给出的方案是在jsp页面里对response这个做清楚,具体百度啦,可是我用的是thymeleaf啊这可咋办,经过我的百般思考,掉了几根头发以后尝试加了个@ResponseBody代码就变成了这样

    @RequestMapping("/vaildCode")
    @ResponseBody
    public void defaultKaptcha() {
        这一段略了,都是一样的。。。
    }

然后,然后再次发出获取请求。。。然后控制台就不报错了。。。emmm
感觉自己呆呆的。。。

                                                                    此文终!
                                                                    谨以此纪念蠢蠢的自己
### Thymeleaf 请求转发时出现 `java.lang.IllegalStateException` 的解决方案 当在使用 Thymeleaf 进行视图渲染并尝试请求转发时遇到 `java.lang.IllegalStateException: getOutputStream() has already been called for this response` 错误,通常是因为响应对象已经被部分处理过。具体来说,在同一个 HTTP 响应周期内,不能同时使用 `getWriter()` 和 `getOutputStream()` 方法[^1]。 #### 问题根源 此异常的根本原因是 Servlet 容器不允许在一个请求中多次获取不同类型的输出流。一旦调用了其中一个方法,则不能再调用另一个;否则就会触发上述提到的状态非法异常。对于 JSP 页面而言,默认情况下会自动创建一个字符流用于页面内容输出,而如果开发者再显式地去获取字节流来发送二进制数据(比如图片),就容易引发冲突[^4]。 #### 解决方案 为了防止此类情况发生,建议采取如下措施之一: - **避免混合使用**:确保在同一请求范围内只选择一种方式来进行输出操作——要么全部采用字符流(`getWriter`),要么完全依赖于字节流(`getOutputStream`)。 - **调整控制器逻辑**:如果是 Spring MVC 应用程序中的 Controller 层出现问题,可以考虑为导出功能添加 `@ResponseBody` 注解以指示框架直接返回实体内容而不是试图解析模板引擎的结果。 ```java @GetMapping("/export") @ResponseBody public void export(HttpServletResponse response) throws IOException { // 设置响应头信息... OutputStream out = response.getOutputStream(); // 执行导出业务逻辑... } ``` - **配置 Thymeleaf 版本兼容性**:有时由于 Thymeleaf 或其集成库之间的版本不匹配也会间接造成类似的问题。因此确认项目所使用的 Thymeleaf 及相关组件版本是否一致非常重要[^3]。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <!-- 使用稳定版 --> <version>${thymeleaf.version}</version> </dependency> ``` 通过以上手段应该能够有效减少甚至消除因不当访问 Response 对象而导致的 IllegalStateException 异常现象。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值