报错:nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response
错误原因:response的getWriter()方法已被调用。
报错场景:在有2个filter+1个interceptor的应用中,在interceptor中使用了response.getWriter()方法,在一个filter中使用response.getOutputStream()。当response.getWriter()方法调用后,response.getOutputStream()调用时即报错。
跟踪response.getWriter()方法,在类Response.class源码中,有如下代码:
在调用getWriter()方法时,首先会判断this.usingOutputStream,如果是true,就抛出异常,否则设置this.usingWriter=true;
所以调用getWriter()方法后,会导致:this.usingWriter=true;
同样跟踪response.getOutputStream()方法,在在类Response.class源码中,有如下代码:
在调用response.getOutputStream()方法时,首先会判断this.usingWriter,如果时true,就抛出异常,否则设置this.usingOutputStream=true;
所以调用getOutputStream()方法后,会导致:this.usingOutputStream=true;
在这样的设定下,就无法同时使用getWriter()和getOutputStream()方法,调用其中一个之后必然会使另一个的标记为true。
解决办法:在所有的filter和interceptor中,要么都使用getWriter()方法,要么都使用getOutputStream()方法,不能两者都使用。
现在我们知道了报错的原因是:在interceptor中使用了response.getWriter()方法,在一个filter中使用response.getOutputStream(),两者操作的都是同一个response对象,那么interceptor和filter的执行顺序是如何的。
本地创建demo程序,创建2个filter,创建1个interceptor,内容分别如下:
OneFilter
TwoFilter
interceptor
controller方法
启动程序,并访问controller方法,结果打印如下:
可以看出,过滤器的执行是包含了拦截器的,拦截器的执行会在过滤器的doFilter方法中执行。