记SpringBoot拦截器报错getWriter() has already been called for this response
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() ,将数据用字节传输则正常



浙公网安备 33010602011771号