记 SpringBoot 拦截器报错 getWriter() has already been called for this response


title: 记 SpringBoot 拦截器报错 getWriter() has already been called for this response
date: 2022-09-01 10:40:59
tags:

  • SpringBoot
    categories:
  • 问题记录
    cover: https://cover.png
    feature: false

1. 问题

在拦截器中返回信息时,使用 response.getWriter() 报错 getWriter() has already been called for this response。这里使用的 getWriter()操作的是字符,所以使用 print()write()都可以(print()wirte区别见 3)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 原因分析

这里先确定一个前提,上面的拦截器返回的是 true,还会走后面的拦截器或过滤器,假如返回 false 直接结束,则不会有上述问题。 通过跟踪 getWriter()方法,在类 Response.class 源码中

在这里插入图片描述

可以看到在调用 getWriter()方法时,首先会判断 usingOutputStream,如果是 true,就抛出异常,否则设置 usingWriter=true;。所以调用 getWriter()方法后,会导致:usingWriter=true;

同样在类 Response.class 源码中再查看 getOutputStream()的源码

在这里插入图片描述

可以看到在调用 getOutputStream()方法时,首先会判断 usingWriter,如果是 true,就抛出异常,否则设置 usingOutputStream=true;。所以调用 getOutputStream()方法后,会导致:usingOutputStream=true;

在这样的设定下,就无法同时使用 getWriter()getOutputStream() 方法,调用其中一个之后必然会使其标记为 true,从而调用另一个方法时会报错

之所以两者互相排斥,调用一个方法后不能再调用另一方法,因为 getWriter()是字符流,getOutputStream()是字节流,缓存区不可能同时存在两种格式

3. 解决

在所有的 Filter 和 Interceptor 中,要么都使用 getWriter() 方法,要么都使用 getOutputStream() 方法,不能两者都使用

我这里后面并没有再自定义拦截器或过滤器,推测 SpringBoot 可能默认使用的是 getOutputStream()返回白页等信息,而我并没有 retrun false,同时存在两种格式导致报错。重新修改如下(测试 return false 时下图忘记改成 return true 了,但不影响引出问题):

在这里插入图片描述

这里使用的是 print(),会报错 Not an ISO 8859-1 character,因为 Stream 输出的是二进制流,没有对字符进行编码,Stream 只适用于 ISO 8859-1编码的字符。Writer 输出的是文本的信息, 是进行过系统编码后的

在这里插入图片描述

使用 write() ,将数据用字节传输则正常

在这里插入图片描述

在这里插入图片描述

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fan 

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值