2009-12-07 58 views
7

我想知道是否有簡單的方式來爲Java壓縮包內容提供GZip內容。我已經啓動了應用程序,因此所需的修改應該過於沉重。用Java Servlets處理Gzip壓縮的內容

我剛剛在的doPost/doGet方法結束訪問響應對象,所以我在尋找類似

response.setGzip(true); 

它不必是那麼容易但將是理想的。

非常感謝

回答

11

This article具有用於在飛行中自動壓縮ServletFilter中完整的(和簡單)的源代碼。

3

看看GzipOutputStream類。像這樣的東西:

response.setContentType(...) 
GzipOutputStream os = new GzipOutputStream(response.getOutputStream); 
//write to os 
Writer writer = new PrintWriter(os); 

然後用像你這樣的作家通常做。

+0

是的,但然後...我該怎麼做os? – 2009-12-07 21:19:38

+0

查看Jonathan Feinberg的解決方案:) – 2009-12-07 21:59:58

4

根據你的容器,容器很可能會爲你做這個。它可能會自動執行,或者您可能需要手動將其配置爲爲您執行。這種方法的優點是零代碼更改。再次,根據容器,您可以根據請求來自何處或源瀏覽器有條件地啓用/禁用壓縮。

對於Tomcat,請查看HTTP配置頁上的壓縮屬性(v5.5,v6.0)。

1

如果你確實真的不想再搗鼓Java代碼,那麼你也可以考慮在你的servlet容器之前掛接一個Apache服務器。

如果你有很多靜態內容,這實際上可以提高你的性能,因爲Apache的靜態頁面比任何servlet容器都要快一些。所以你應該將它配置爲只將servlet請求委託給localhost上的servlet容器。

Apache有便利的內置壓縮輸出選項。我不記得如何設置它們,但它很容易和多功能。它與瀏覽器協商他們可以處理什麼,等等。如有疑問,Apache一般會比任何Java容器更加精明和最新的壓縮方法。

2

基本上有2種方式:在應用程序服務器

  • 配置。例如在Tomcat中,您只需將Connectorcompression屬性的conf/server.xml設置爲on即可。
  • response.getOutputStream()換成new GzipOutputStream(),然後寫入它。

第一種方式影響整個webapp,但這真的不應該傷害,它幾乎是零努力和性能的大好處。而且,更重要的是,與第二種方式相反,如果客戶端在使用之前支持 Gzip,它實際上會檢查請求標頭。當你無前無後地去第二種方式時,約10%的萬維網用戶將無法訪問你的網絡應用程序。這實際上不是一個隨便的任務。

您可以在FileServlet的高級示例中找到here,該示例支持在每個Gzip下並根據請求標頭進行檢查。你可能會從中獲得新的見解。

+0

我看到一些servlets過濾器也可以這麼做嗎?第三種方式?哪個應該是首選? – 2013-08-30 13:43:55

+1

@ user01:servlet過濾器以第二種方式(以通用的可重用方式執行,而不需要在所有servlet上覆制泥漿邏輯)。 OmniFaces有一個:http://showcase.omnifaces.org/filters/GzipResponseFilter – BalusC 2013-08-30 13:44:47

+0

感謝您的快速評論!所以1st應該成爲所有Web應用程序資源的gzip的首選方式? – 2013-08-30 13:50:42

1

如果你在Tomcat上,連接器可以爲你做壓縮。這是我的配置,

<Connector port="8000" 
compression="on" 
compressionMinSize="1024" 
compressableMimeType="text/html,text/xml" 
... 
/> 

如果您運行在Tomcat中前面的Apache httpd的,你應該使用mod_gzip的,它做了更好的工作。

1

只是想讓你知道我結束了什麼。

我提出的要求類的包裝,看起來像這樣:

public class GzippedResponse extends HttpServletResponseWrapper{ 

    private PrintWriter pw; 

    private GzippedResponse(HttpServletResponse response){ 
    super(response); 
    try{ 
     pw = new PrintWriter(new GZIPOutputStream(response.getOutputStream())); 
    }catch(Exception e){ 
     throw new ApiInternalException("Failed to create a Gzipped Response", e); 
    } 
    } 

    public static GzippedResponse wrap(HttpServletResponse response){ 
    return new GzippedResponse(response); 
    } 

    @Override 
    public PrintWriter getWriter() throws IOException { 
    return pw; 
    } 
} 

,然後在我的BaseAction,這基本上是一個TemplateMethod其他「動作」我包這樣的迴應:

if(supportsCompression(request)){ 
    response.setHeader("Content-Encoding", "gzip"); 
    response = GzippedResponse.wrap(response); 
} 
action.macroExecute(request,response); 

我覺得它夠乾淨。如果你發現有什麼可以改進的地方,請告訴我。謝謝大家的答案!

+0

這並不包含最重要的部分,即輸出流。 – momomo 2015-11-14 20:00:23