如何从ServletFilter中的ServletResponse中获取HTTP状态代码?

Set*_*ner 60 java servlets http-status-codes servlet-filters

我正在尝试报告从我的webapp返回的每个HTTP状态代码.但是,状态代码似乎无法通过ServletResponse访问,或者即使我将其转换为HttpServletResponse也是如此.有没有办法在ServletFilter中访问这个值?

Dav*_*itz 87

首先,您需要将状态代码保存在可访问的位置.最好用您的实现包装响应并将其保留在那里:

public class StatusExposingServletResponse extends HttpServletResponseWrapper {

    private int httpStatus;

    public StatusExposingServletResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void sendError(int sc) throws IOException {
        httpStatus = sc;
        super.sendError(sc);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        httpStatus = sc;
        super.sendError(sc, msg);
    }


    @Override
    public void setStatus(int sc) {
        httpStatus = sc;
        super.setStatus(sc);
    }

    public int getStatus() {
        return httpStatus;
    }

}
Run Code Online (Sandbox Code Playgroud)

为了使用这个包装器,您需要添加一个servlet过滤器,如果您可以进行报告:

public class StatusReportingFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        StatusExposingServletResponse response = new StatusExposingServletResponse((HttpServletResponse)res);
        chain.doFilter(req, response);
        int status = response.getStatus();
        // report
    }

    public void init(FilterConfig config) throws ServletException {
        //empty
    }

    public void destroy() {
        // empty
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 如果有人在页面结尾之前没有阅读,请注意下面的Joel评论也设置默认状态= 200并且还覆盖sendRedirect(..) (9认同)

Bal*_*usC 64

从Servlet 3.0开始,有一个HttpServletResponse#getStatus().

因此,如果有升级空间,请升级到Servlet 3.0(Tomcat 7,Glassfish 3,JBoss AS 6等),您不需要包装器.

chain.doFilter(request, response);
int status = ((HttpServletResponse) response).getStatus();
Run Code Online (Sandbox Code Playgroud)


小智 17

还需要包含#sendRedirect的包装器,将状态初始化为'200'而不是'0'会更好

private int httpStatus = SC_OK;

...

@Override
public void sendRedirect(String location) throws IOException {
    httpStatus = SC_MOVED_TEMPORARILY;
    super.sendRedirect(location);
}
Run Code Online (Sandbox Code Playgroud)


小智 12

上面David的回答中遗漏的一件事是你还应该覆盖另一种形式的sendError:

@Override
public void sendError(int sc, String msg) throws IOException {
    httpStatus = sc;
    super.sendError(sc, msg);
}
Run Code Online (Sandbox Code Playgroud)


Gré*_*eph 8

除了David的回答之外,您还需要覆盖重置方法:

@Override
public void reset() {
    super.reset();
    this.httpStatus = SC_OK;
}
Run Code Online (Sandbox Code Playgroud)

...以及弃用的setStatus(int,String)

@Override
public void setStatus(int status, String string) {
    super.setStatus(status, string);
    this.httpStatus = status;
}
Run Code Online (Sandbox Code Playgroud)


Lic*_*say 6

编写一个HttpServletResponseWrapper并覆盖所有setStatus(),sendError()和sendRedirect()方法来记录所有内容.编写一个过滤器,在每个请求中交换包装器以获取响应对象.