• 记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() ,将数据用字节传输则正常

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    ubuntu系统简单尝试
    2021-10《信息资源管理 02378》真卷(独家文字版),圈定章节考点+统计真题分布
    多态你真的了解吗?
    [附源码]java毕业设计壹家吃货店网站
    Linux 系统目录结构
    前端Canvas入门——怎么用Canvas画一些简单的图案
    Java客户端调用Websocket服务端(Springboot)
    Nginx学习(3)—— Nginx的应用
    PID的调节
    Go项目踩坑:go get下载超时,goFrame框架下的go项目里将vue项目的dist同步打包发布,go项目打包并压缩
  • 原文地址:https://blog.csdn.net/ACE_U_005A/article/details/126637958