HttpServletResponseWrapper

HttpServletResponseWrapper

我是servlet的新手,正在阅读一些有关过滤器和包装器的文本。我可以理解过滤器,但对包装感到困惑。在书中,作者举了一个例子:

如果没有包装器:

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {

        String name = request.getParameter("name").trim();

        try {
            chain.doFilter(request, response);
            PrintWriter out = response.getWriter();
            if (name.length() == 0) {
                out.println("Some message");
                out.println("</body>");
                out.println("</html>");
                out.close();
            }
        } catch (Throwable t) {
        }
    }

如果是 wrapper :
 public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {

        String name = request.getParameter("name").trim();

        HttpServletResponse httpRes = (HttpServletResponse) response;
        HttpServletResponseWrapper resWrapper = new HttpServletResponseWrapper(httpRes);
        try {
            chain.doFilter(request, response);

            PrintWriter out = resWrapper.getWriter(); // why dont we just use response.getWriter();
            if (name.length() == 0) {
                out.println("<h3>Some message");
                out.println("</body>");
                out.println("</html>");
                out.close();
            }
        } catch (Throwable t) {
        }
    }

为什么在情况1中我们可以用HttpServletResponseWrapper做同样的事情,为什么我们需要ServletResponse?谁能给我一个明确的例子,说明我们必须使用HttpServletResponseWrapper而不是ServletResponse吗?我曾尝试过Google,但没有发现运气。

最佳答案

BalusC的答案很好,但是如果您刚开始,可能会有些不知所措。

简而言之:SerlvetResponse及其扩展名HttpServletResponse是告诉您可以调用哪些方法来执行所需操作的接口(interface)。在使用Filters,Servlets等的正常过程中,您将经常使用HttpServletResponse来告诉您的应用程序如何响应请求。

HttpServletResponseWrapper是HttpServletResponse的一种特定实现,它为您提供了一种方便的方法,用您自己的某种逻辑包装现有响应,而无需编写接口(interface)的全新实现。它有很多方法,所以这真的很好。作为一个简单的示例,假设您要禁止调用response.flushBuffer()。这段代码使用HttpServletResponseWrapper可以做到:

class DisallowFlushResponseWrapper extends HttpServletResponseWrapper {
    public DisallowFlushResponseWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void flushBuffer() {
        throw new UnsupportedOperationException("Don't call this!");
    }
}

使用这种包装器的典型方法是创建一个如下所示的过滤器:
class DisallowFlushFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) {
        if (response instanceof HttpServletResponse) {
            HttpServletResponse newResponse =
                new DisallowFlushResponseWrapper((HttpServletResponse) response);
            chain.doFilter(request, newResponse);
        }
        ...
    }
    ...
}

请注意,我们使用自己的包装器实例包装进入过滤器的响应。然后,将 wrapper 递给过滤器链中的下一项。因此,此过滤器之后的所有内容如果调用flushBuffer()都会获得异常,因为它将在我们的包装器上对其进行调用。包装器由于其默认行为,将把任何其他调用委托(delegate)给包装的响应,这是真实的响应,因此除对该方法的调用之外的所有内容都将正常工作。

08-25 02:27