WEB前端培訓(xùn)之HttpServletRequestWrapper 用法
Servlet規(guī)范中所引入的filter令人心動(dòng)不已,因?yàn)樗肓艘粋€(gè)功能強(qiáng)大的攔截模式。Filter是這樣一種Java對(duì)象,它能在request到達(dá)servlet的服務(wù)方法之前攔截HttpServletRequest對(duì)象,而在服務(wù)方法轉(zhuǎn)移控制后又能攔截HttpServletResponse對(duì)象。你可以使用filter來(lái)實(shí)現(xiàn)特定的任務(wù),比如驗(yàn)證用戶輸入,以及壓縮web內(nèi)容。但你擬富有成效地使用過(guò)濾器的念頭卻被你不能改變HttpServletRequest對(duì)象的參數(shù)的現(xiàn)實(shí)掃了興,因?yàn)閖ava.util.Map所包裝的HttpServletRequest對(duì)象的參數(shù)是不可改變的。這極大地縮減了filter的應(yīng)用范圍。至少在一半的時(shí)間里,你希望可以改變準(zhǔn)備傳送給filter的對(duì)象。如果在HttpServletRequest對(duì)象到達(dá)Struts的action servlet之前,我們可以通過(guò)一個(gè)filter將用戶輸入的多余空格去掉,難道不是更美妙嗎?這樣的話,你就不必等到在Struts的action表單驗(yàn)證方法中才進(jìn)行這項(xiàng)工作了。
幸運(yùn)的是,盡管你不能改變不變對(duì)象本身,但你卻可以通過(guò)使用裝飾模式來(lái)改變其狀態(tài)。
現(xiàn)在,讓我們來(lái)看看,如何編寫自己的HttpServletRequest裝飾類。
一個(gè)刪除空白字符的Filter
本節(jié)將以上的理論投入實(shí)際使用,通過(guò)實(shí)現(xiàn)一個(gè)刪除空白字符的filter,來(lái)演示如何使用javax.servlet.http.HttpServletRequestWrapper類來(lái)裝飾HttpServletRequest對(duì)象。在本例中,這個(gè)filter將刪除所傳來(lái)的參數(shù)中多余的空白字符。
這在許多servlet/JSP應(yīng)用中是很有用的,包括Struts及JavaServer Faces等應(yīng)用。例如,Struts通過(guò)調(diào)用HttpServletRequest對(duì)象的getParameterValues()對(duì)象來(lái)處理action表單。通過(guò)覆蓋裝飾類中此方法,你可以改變當(dāng)前HttpServletRequest對(duì)象的狀態(tài)。
要?jiǎng)?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請(qǐng)求并裝飾HttpServletRequest對(duì)象。[i]列表6:刪除空白符的filter
列表6演示了如何載獲Http請(qǐng)求并裝飾HttpServletRequest對(duì)象。
[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);
}
}
這個(gè)程序使用了列表6所示的filter來(lái)修整用戶輸入。要使用這個(gè)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>
要測(cè)試這個(gè)filter,啟動(dòng)這個(gè)應(yīng)用后,在表單中輸入一些值,提交表單,看看這個(gè)filter是如何修整輸入數(shù)值的。這是一個(gè)實(shí)用的裝飾模式的應(yīng)用。
小結(jié)
Servlet filter可以在調(diào)用一個(gè)servlet的服務(wù)方法后,攔載或加工HTTP請(qǐng)求。盡管這非常誘人,但其實(shí)際使用卻有所限制,因?yàn)槟悴荒芨淖僅ttpServletRequest對(duì)象。
這時(shí)候裝飾模式派上了用場(chǎng)。本文演示了如何通過(guò)應(yīng)用裝飾模式來(lái)“修改”HttpServletRequest對(duì)象,從而使你的servlet filter更加有用。在上面filter例子中,filter改了request參數(shù)中的用戶輸入,而這一點(diǎn),如果沒(méi)有裝飾request對(duì)象,你是無(wú)論如何也不可能做到的。
---------------------------------------------------------
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);
}
/**
* 獲得被裝飾對(duì)象的引用和采用的字符編碼
* @param request
* @param charset
*/
public GetHttpServletRequestWrapper(HttpServletRequest request,
String charset) {
super(request);
this.charset = charset;
}
/**
* 實(shí)際上就是調(diào)用被包裝的請(qǐng)求對(duì)象的getParameter方法獲得參數(shù),然后再進(jìn)行編碼轉(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è)置請(qǐng)求響應(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("----請(qǐng)求被"+config.getFilterName()+"過(guò)濾");
//傳遞給目標(biāo)servlet或jsp的實(shí)際上時(shí)包裝器對(duì)象的引用,而不是原始的HttpServletRequest對(duì)象
chain.doFilter(req, response);
System.out.println("----響應(yīng)被"+config.getFilterName()+"過(guò)濾");
}
本文版權(quán)歸黑馬程序員web前端開發(fā)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處,謝謝!作者:黑馬程序員web前端培訓(xùn)學(xué)院;
首發(fā):http://web.itheima.com/ 8種