我希望有人已經寫了這個:我在哪裏可以找到一個將Servlet應用到輸出的Java Servlet過濾器?
一個servlet過濾器,可以配置正則表達式搜索/替換模式,並將它們應用到HTML輸出。
這樣的事情是否存在?
我希望有人已經寫了這個:我在哪裏可以找到一個將Servlet應用到輸出的Java Servlet過濾器?
一個servlet過濾器,可以配置正則表達式搜索/替換模式,並將它們應用到HTML輸出。
這樣的事情是否存在?
我無法找到一個,所以我寫了一個:
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>
我不確定這是尋找什麼,但有一個URL重寫過濾器。它支持正則表達式。請看這裏http://www.tuckey.org/urlrewrite/
希望這會有所幫助。
你到底想改變什麼?請求URL或響應正文? Tuckey的UrlRewriteFilter非常出色,但它可以重寫URL(儘可能使用着名的Apache HTTPD的RewriteRule)。要更改響應主體,您必須更具體地瞭解功能需求。沒有想到這樣的過濾器,但這太過像消毒用戶控制的輸入以防止XSS。在這種情況下,正則表達式絕對是工作的錯誤工具。 – BalusC 2011-02-16 00:12:02
對不起,我不清楚。我編輯了這個問題來表明我想修改HTML輸出。 – 2011-02-17 13:59:35
HTML輸出究竟是什麼?由於使用正則表達式來解析和修改HTML是一種非常糟糕的做法,因此從未寫過這樣的過濾器。請詳細說明功能要求。爲什麼你需要一個這樣的過濾器?爲什麼不直接在視圖方面進行更改?等 – BalusC 2011-02-17 15:14:37