filter中流未关闭引发的问题getWriter() has already been called for this response

た 入场券 2021-12-22 20:45 502阅读 0赞

【引言】

在上一篇博客中,写了Spring MVC和Spring Boot框架中如何实现自定义filter,文章结尾提到了filter中遇到的问题,如下:

  1. IllegalStateException: getWriter() has already been called for this response

【问题代码】

  1. public class LoginFilter implements Filter{
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. }
  5. @Override
  6. public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
  7. ...
  8. PrintWriter out = null;
  9. ...
  10. out = resp.getWriter();
  11. //判断是否已经登录,没登录返回登录url
  12. if(user.notLogin()){
  13. ReturnMsg msg = new ReturnMsg();
  14. msg.setCode("111111");
  15. msg.setMessage("用户未登录");
  16. out.writer(JSON.toJSONString(msg));
  17. out.close();
  18. return;
  19. }
  20. ...
  21. chain.dofilter(req,resp);
  22. }
  23. @Override
  24. public void destroy() {
  25. }
  26. }

【问题原因】

在上面的代码中,可以发现,只有当进入未登录的逻辑才会将流关闭,而如果登录之后,再次进入这个filter,就会出现以上异常。所以将代码修改了一版,如下:

  1. public class LoginFilter implements Filter{
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. }
  5. @Override
  6. public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
  7. ...
  8. PrintWriter out = null;
  9. ...
  10. try {
  11. //判断是否已经登录,没登录返回登录url
  12. if(user.notLogin()){
  13. ReturnMsg msg = new ReturnMsg();
  14. msg.setCode();
  15. msg.setMessage();
  16. out = resp.getWriter();
  17. out.writer(JSON.toJSONString(msg));
  18. out.close();
  19. return;
  20. }
  21. } finally {
  22. if(out!=null){
  23. out.flush();
  24. out.close();
  25. }
  26. }
  27. ...
  28. chain.dofilter(req,resp);
  29. }
  30. @Override
  31. public void destroy() {
  32. }
  33. }

【其他原因】

我遇到的情况是因为流未关闭,导致的上述异常,在查解决方案,还看到了可能有其他原因导致此异常。比如:getWriter() 和getOutputStream() 只能用一个,一个字符输出流,一个字节输出流,都获取后就会出现这个异常。

【总结】

很简单的一个filter,接二连三出现代码错误。最开始忘记写验证通过,放行chain.dofilter(req,resp)一行代码;接着出现这个异常,给老大的解释是自己从其他filter粘贴过来的代码,也没看写的什么内容,删删减减,没报错,留下需要的就提交了。

另外,也存在一些外部原因,test环境与pre环境配置不一样,test通过了,pre却出问题了,而pre的日志我们开发人员也不能随便查,所以定位问题也花费了不少时间。

在这个流程复杂严格而又混乱的团队,让我在一个月的时间里看到了凌晨四点的中关村,我想,生活就是,选择放弃可以有很多理由,而选择坚持下去一个就足够了。

发表评论

表情:
评论列表 (有 0 条评论,502人围观)

还没有评论,来说两句吧...

相关阅读