2011-08-11 21 views
10

我是servlet新手,並閱讀一些關於過濾器和包裝器的文章。我可以理解過濾器,但對包裝器感到困惑。在本書中,作者舉了一個例子:ServletResponse和HttpServletResponseWrapper的區別?

如果沒有包裝:

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) { 
     } 
    } 

在包裝的情況下:

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) { 
     } 
    } 

我們爲什麼需要HttpServletResponseWrapper,而我們可以做同樣的事情案例1中的ServletResponse?任何人都可以給我一個明確的例子,我們必須使用HttpServletResponseWrapper而不是ServletResponse?我試圖谷歌,但發現沒有運氣。

+0

此代碼看起來很奇怪。包裝servlet響應的目的是進一步傳遞它('chain.doFilter(request,resWrapper);')並攔截包裝器中的選定調用。例如,通過這種方式,您可以返回不同的響應編寫器,以便隨時更改或壓縮內容並將其發送到目標「響應」。這個例子沒有多少意義......你能提供這個(頁面,書嗎?)的來源 –

+0

我發現自己也很奇怪。這段代碼是我從一位大學講師的幻燈片中截取的。如果我們做chain.doFilter(request,resWrapper);作爲你的建議 – ipkiss

回答

8

這實在是一個愚蠢的例子,它沒有顯示請求/響應包裝的好處。實際上,整個過濾器的例子很差。發送HTML應該由JSP完成,或者在最高的servlet上完成(但仍然很差)。通過我們的filters wiki page來獲得關於什麼是過濾器可以使用的一些想法。

如果您想要修改響應的行爲或僅僅希望收集有關響應的信息,而在請求響應鏈中使用,則響應包裝器很有用。只要某個servlet或JSP在響應中調用某個方法,就會將被修改的行爲放置。如果你已經在你的包裝類中重寫了它,那麼將會調用這個。你可以改變行爲或收集信息。

這裏的Stackoverflow你可以找到someconcrete有用的HttpServletResponseWrapper實現的例子。

18

BalusC的回答是好,但如果你是剛剛起步,它可能是一個有點勢不可擋。

簡單地說:SerlvetResponse及其擴展HttpServletResponse是告訴你什麼方法可用來調用來做你需要的東西。在使用Filters,Servlets等的常規過程中,您經常會使用HttpServletResponse來告訴您的應用程序如何響應請求。

HttpServletResponseWrapper是HttpServletResponse的一個特定實現,它爲您提供了一種方便的方式來用現有的自己的邏輯封裝現有的響應,而無需編寫接口的全新實現。它有一個很多的方法,所以這真的很不錯。作爲一個微不足道的例子,假設你想禁止撥打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); 
     } 
     ... 
    } 
    ... 
} 

注意,我們總結的響應竄進使用我們自己的包裝器的實例進行過濾。然後,我們將包裝物交給過濾器鏈中的下一個物品。因此,如果它調用flushBuffer(),因爲它將在我們的封裝器上調用它,那麼在此過濾器之後出現的任何內容都將得到一個異常。包裝由於其默認行爲,將任何其他調用委託給封裝的響應,這是真實的,因此除了調用該方法以外的所有內容都能正常工作。

+0

但原來的問題仍然沒有答案,即爲什麼我們不能用原始的HttpServletResponse對象本身來做這一切? –