【引言】
在上一篇博客中,寫了Spring MVC和Spring Boot框架中如何實現自定義filter,文章結尾提到了filter中遇到的問題,如下:
IllegalStateException: getWriter() has already been called for this response
【問題代碼】
public class LoginFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
...
PrintWriter out = null;
...
out = resp.getWriter();
//判斷是否已經登錄,沒登錄返回登錄url
if(user.notLogin()){
ReturnMsg msg = new ReturnMsg();
msg.setCode();
msg.setMessage();
out.writer(JSON.toJSONString(msg));
out.close();
return;
}
...
chain.dofilter(req,resp);
}
@Override
public void destroy() {
}
}
【問題原因】
在上面的代碼中,可以發現,只有當進入未登錄的邏輯纔會將流關閉,而如果登錄之後,再次進入這個filter,就會出現以上異常。所以將代碼修改了一版,如下:
public class LoginFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
...
PrintWriter out = null;
...
try {
//判斷是否已經登錄,沒登錄返回登錄url
if(user.notLogin()){
ReturnMsg msg = new ReturnMsg();
msg.setCode();
msg.setMessage();
out = resp.getWriter();
out.writer(JSON.toJSONString(msg));
out.close();
return;
}
} finally {
if(out!=null){
out.flush();
out.close();
}
}
...
chain.dofilter(req,resp);
}
@Override
public void destroy() {
}
}
【其他原因】
我遇到的情況是因爲流未關閉,導致的上述異常,在查解決方案,還看到了可能有其他原因導致此異常。比如:getWriter() 和getOutputStream() 只能用一個,一個字符輸出流,一個字節輸出流,都獲取後就會出現這個異常。
【總結】
很簡單的一個filter,接二連三出現代碼錯誤。最開始忘記寫驗證通過,放行chain.dofilter(req,resp)一行代碼;接着出現這個異常,給老大的解釋是自己從其他filter粘貼過來的代碼,也沒看寫的什麼內容,刪刪減減,沒報錯,留下需要的就提交了。
另外,也存在一些外部原因,test環境與pre環境配置不一樣,test通過了,pre卻出問題了,而pre的日誌我們開發人員也不能隨便查,所以定位問題也花費了不少時間。
在這個流程複雜嚴格而又混亂的團隊,讓我在一個月的時間裏看到了凌晨四點的中關村,我想,生活就是,選擇放棄可以有很多理由,而選擇堅持下去一個就足夠了。