WEB前端培訓(xùn)之HttpServletRequestWrapper 用法
Servlet規(guī)范中所引入的filter令人心動不已,因為它引入了一個功能強大的攔截模式。Filter是這樣一種Java對象,它能在request到達servlet的服務(wù)方法之前攔截HttpServletRequest對象,而在服務(wù)方法轉(zhuǎn)移控制后又能攔截HttpServletResponse對象。你可以使用filter來實現(xiàn)特定的任務(wù),比如驗證用戶輸入,以及壓縮web內(nèi)容。但你擬富有成效地使用過濾器的念頭卻被你不能改變HttpServletRequest對象的參數(shù)的現(xiàn)實掃了興,因為java.util.Map所包裝的HttpServletRequest對象的參數(shù)是不可改變的。這極大地縮減了filter的應(yīng)用范圍。至少在一半的時間里,你希望可以改變準備傳送給filter的對象。如果在HttpServletRequest對象到達Struts的action servlet之前,我們可以通過一個filter將用戶輸入的多余空格去掉,難道不是更美妙嗎?這樣的話,你就不必等到在Struts的action表單驗證方法中才進行這項工作了。
幸運的是,盡管你不能改變不變對象本身,但你卻可以通過使用裝飾模式來改變其狀態(tài)。
現(xiàn)在,讓我們來看看,如何編寫自己的HttpServletRequest裝飾類。
一個刪除空白字符的Filter
本節(jié)將以上的理論投入實際使用,通過實現(xiàn)一個刪除空白字符的filter,來演示如何使用javax.servlet.http.HttpServletRequestWrapper類來裝飾HttpServletRequest對象。在本例中,這個filter將刪除所傳來的參數(shù)中多余的空白字符。
這在許多servlet/JSP應(yīng)用中是很有用的,包括Struts及JavaServer Faces等應(yīng)用。例如,Struts通過調(diào)用HttpServletRequest對象的getParameterValues()對象來處理action表單。通過覆蓋裝飾類中此方法,你可以改變當(dāng)前HttpServletRequest對象的狀態(tài)。
要創(chuàng)建HttpServletRequest的裝飾類,你需要繼承HttpServletRequestWrapper并且覆蓋你希望改變的方法。列表5中,MyRequestWrapper類將刪除getParameterValues()方法返回值的多余空白字符。
列表5:HttpServerletRequest裝飾類
程序代碼:
package trimmer.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public final class MyRequestWrapper extends HttpServletRequestWrapper {
public MyRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
}
public String[] getParameterValues(String parameter) {
String[] results = super.getParameterValues(parameter);
if (results == null)
return null;
int count = results.length;
String[] trimResults = new String[count];
for (int i = 0; i < count; i++) {
trimResults[i] = results[i].trim();
}
return trimResults;
}
}
列表6演示了如何載獲Http請求并裝飾HttpServletRequest對象。[i]列表6:刪除空白符的filter
列表6演示了如何載獲Http請求并裝飾HttpServletRequest對象。
[i]列表6:刪除空白符的filter
程序代碼:
package trimmer.filter;
import java.io.IOException;
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.HttpServletRequest;
public class MyFilter implements Filter {
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter initialized");
this.filterConfig = filterConfig;
}
public void destroy() {
System.out.println("Filter destroyed");
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(new MyRequestWrapper((HttpServletRequest) request),
response);
}
}
這個程序使用了列表6所示的filter來修整用戶輸入。要使用這個filter,你需要在web.xml文件中如下設(shè)置filter及filter-mapping的元素。
<filter>
<filter-name>TrimmerFilter</filter-name>
<filter-class>trimmer.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TrimmerFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
要測試這個filter,啟動這個應(yīng)用后,在表單中輸入一些值,提交表單,看看這個filter是如何修整輸入數(shù)值的。這是一個實用的裝飾模式的應(yīng)用。
小結(jié)
Servlet filter可以在調(diào)用一個servlet的服務(wù)方法后,攔載或加工HTTP請求。盡管這非常誘人,但其實際使用卻有所限制,因為你不能改變HttpServletRequest對象。
這時候裝飾模式派上了用場。本文演示了如何通過應(yīng)用裝飾模式來“修改”HttpServletRequest對象,從而使你的servlet filter更加有用。在上面filter例子中,filter改了request參數(shù)中的用戶輸入,而這一點,如果沒有裝飾request對象,你是無論如何也不可能做到的。
---------------------------------------------------------
package wrapper;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {
private String charset = "UTF-8";
public GetHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
/**
* 獲得被裝飾對象的引用和采用的字符編碼
* @param request
* @param charset
*/
public GetHttpServletRequestWrapper(HttpServletRequest request,
String charset) {
super(request);
this.charset = charset;
}
/**
* 實際上就是調(diào)用被包裝的請求對象的getParameter方法獲得參數(shù),然后再進行編碼轉(zhuǎn)換
*/
public String getParameter(String name) {
String value = super.getParameter(name);
value = value == null ? null : convert(value);
return value;
}
public String convert(String target) {
System.out.println("編碼轉(zhuǎn)換之前:" + target);
try {
return new String(target.trim().getBytes("ISO-8859-1"), charset);
} catch (UnsupportedEncodingException e) {
return target;
}
}
}
------------
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//設(shè)置請求響應(yīng)字符編碼
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
//新增加的代碼
HttpServletRequest req = (HttpServletRequest)request;
if(req.getMethod().equalsIgnoreCase("get"))
{
req = new GetHttpServletRequestWrapper(req,charset);
}
System.out.println("----請求被"+config.getFilterName()+"過濾");
//傳遞給目標servlet或jsp的實際上時包裝器對象的引用,而不是原始的HttpServletRequest對象
chain.doFilter(req, response);
System.out.println("----響應(yīng)被"+config.getFilterName()+"過濾");
}
本文版權(quán)歸黑馬程序員web前端開發(fā)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處,謝謝!作者:黑馬程序員Web前端培訓(xùn)學(xué)院;
首發(fā):http://pantone-color.com.cn/news/web.html 8種