实现需要注意二点:
- 1.使用HttpServletResponseWrapper包装response
- 2.覆盖sendError方法,遇到404错误不能触发错,如触发错误response就被托管,托管后就不能输出数据。
下面是HttpServletResponseWrapper具体实现:
private class Error404ResponseWrapper extends HttpServletResponseWrapper { private int status = SC_OK; public Error404ResponseWrapper(Error404Filter error404Filter, HttpServletResponse response){ super(response); } @Override public void sendError(int sc) throws IOException { this.status = sc; if(isFound()){ super.sendError(sc); }else{ super.setStatus(SC_OK); } } @Override public void sendError(int sc, String msg) throws IOException { this.status = sc; if(isFound()){ super.sendError(sc,msg); }else{ super.setStatus(SC_OK); } } public void setStatus(int status){ this.status = status; super.setStatus(status); } @Override public void reset() { this.status = SC_OK; super.reset(); } public boolean isFound(){ return status != SC_NOT_FOUND; } }
注意sendError处理,上面代码解决了核心两个问题。接下来完成过滤就可。
public class Error404Filter implements Filter { @Override public void destroy() { } @Override public void init(FilterConfig config) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse rep,FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) rep; Error404ResponseWrapper responseWrapper = new Error404ResponseWrapper(this, response); chain.doFilter(request, responseWrapper); if(responseWrapper.isFound()){ return ; } //TODO 实现读取资源 //readResource(request,response); //资源不存在返回错误 String uri = request.getRequestURI(); logger.warn("This is not resource = {}",uri); response.sendError(HttpServletResponse.SC_NOT_FOUND,uri); } }
注意:在web.xml中把该过滤器放在所有过滤器后。