2011-02-15 39 views
10

我希望有人已經寫了這個:我在哪裏可以找到一個將Servlet應用到輸出的Java Servlet過濾器?

一個servlet過濾器,可以配置正則表達式搜索/替換模式,並將它們應用到HTML輸出。

這樣的事情是否存在?

+0

你到底想改變什麼?請求URL或響應正文? Tuckey的UrlRewriteFilter非常出色,但它可以重寫URL(儘可能使用着名的Apache HTTPD的RewriteRule)。要更改響應主體,您必須更具體地瞭解功能需求。沒有想到這樣的過濾器,但這太過像消毒用戶控制的輸入以防止XSS。在這種情況下,正則表達式絕對是工作的錯誤工具。 – BalusC 2011-02-16 00:12:02

+0

對不起,我不清楚。我編輯了這個問題來表明我想修改HTML輸出。 – 2011-02-17 13:59:35

+0

HTML輸出究竟是什麼?由於使用正則表達式來解析和修改HTML是一種非常糟糕的做法,因此從未寫過這樣的過濾器。請詳細說明功能要求。爲什麼你需要一個這樣的過濾器?爲什麼不直接在視圖方面進行更改?等 – BalusC 2011-02-17 15:14:37

回答

14

我無法找到一個,所以我寫了一個:

RegexFilter.java

package com.example; 

import java.io.IOException; 
import java.io.PrintWriter; 
import java.util.ArrayList; 
import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.regex.Pattern; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletResponse; 

/** 
* Applies search and replace patterns. To initialize this filter, the 
* param-names should be "search1", "replace1", "search2", "replace2", etc. 
*/ 
public final class RegexFilter implements Filter { 
    private List<Pattern> searchPatterns; 
    private List<String> replaceStrings; 

    /** 
    * Finds the search and replace strings in the configuration file. Looks for 
    * matching searchX and replaceX parameters. 
    */ 
    public void init(FilterConfig filterConfig) { 
     Map<String, String> patternMap = new HashMap<String, String>(); 

     // Walk through the parameters to find those whose names start with 
     // search 
     Enumeration<String> names = (Enumeration<String>) filterConfig.getInitParameterNames(); 
     while (names.hasMoreElements()) { 
      String name = names.nextElement(); 
      if (name.startsWith("search")) { 
       patternMap.put(name.substring(6), filterConfig.getInitParameter(name)); 
      } 
     } 
     this.searchPatterns = new ArrayList<Pattern>(patternMap.size()); 
     this.replaceStrings = new ArrayList<String>(patternMap.size()); 

     // Walk through the parameters again to find the matching replace params 
     names = (Enumeration<String>) filterConfig.getInitParameterNames(); 
     while (names.hasMoreElements()) { 
      String name = names.nextElement(); 
      if (name.startsWith("replace")) { 
       String searchString = patternMap.get(name.substring(7)); 
       if (searchString != null) { 
        this.searchPatterns.add(Pattern.compile(searchString)); 
        this.replaceStrings.add(filterConfig.getInitParameter(name)); 
       } 
      } 
     } 
    } 

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
     // Wrap the response in a wrapper so we can get at the text after calling the next filter 
     PrintWriter out = response.getWriter(); 
     CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) response); 
     chain.doFilter(request, wrapper); 

     // Extract the text from the completed servlet and apply the regexes 
     String modifiedHtml = wrapper.toString(); 
     for (int i = 0; i < this.searchPatterns.size(); i++) { 
      modifiedHtml = this.searchPatterns.get(i).matcher(modifiedHtml).replaceAll(this.replaceStrings.get(i)); 
     } 

     // Write our modified text to the real response 
     response.setContentLength(modifiedHtml.getBytes().length); 
     out.write(modifiedHtml); 
     out.close(); 
    } 

    public void destroy() { 
     this.searchPatterns = null; 
     this.replaceStrings = null; 
    } 
} 

CharResponseWrapper.java

package com.example; 

import java.io.CharArrayWriter; 
import java.io.PrintWriter; 

import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpServletResponseWrapper; 

/** 
* Wraps the response object to capture the text written to it. 
*/ 
public class CharResponseWrapper extends HttpServletResponseWrapper { 
    private CharArrayWriter output; 

    public CharResponseWrapper(HttpServletResponse response) { 
     super(response); 
     this.output = new CharArrayWriter(); 
    } 

    public String toString() { 
     return output.toString(); 
    } 

    public PrintWriter getWriter() { 
     return new PrintWriter(output); 
    } 
} 

例的web.xml

<web-app> 
    <filter> 
     <filter-name>RegexFilter</filter-name> 
     <filter-class>com.example.RegexFilter</filter-class> 
     <init-param><param-name>search1</param-name><param-value><![CDATA[(<\s*a\s[^>]*)(?<=\s)target\s*=\s*(?:'_parent'|"_parent"|_parent|'_top'|"_top"|_top)]]></param-value></init-param> 
     <init-param><param-name>replace1</param-name><param-value>$1</param-value></init-param> 
    </filter> 
    <filter-mapping> 
     <filter-name>RegexFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
</web-app> 
相關問題