servlet?filter
?
JSP
技術構建在
Servlet
技術之上,所以
Servlet
和
JSP
的技術本質是一樣的,
JSP
能做到的,
Servlet
都能做到,但是它們卻各有所長。
Servlet
比較適合作為控制類組件,比如視圖控制器等。另外,
Servlet
還可以作為過濾器、監聽器等。
Servlet
不僅可以動態生成
HTML
內容,還可以動態生成圖形。總而言之,
Servlet
在項目中作為控制類的組件,并且處理一些后臺業務,
JSP
則作為顯示組件。
?
????
在本節,我們將介紹
Servlet
常用的使用方法之一:作為過濾器。在
Servlet
作為過濾器使用時,它可以對客戶的請求進行過濾處理,當它處理完成后,它會交給下一個過濾器處理,就這樣,客戶的請求在過濾鏈里一個個處理,直到請求發送到目標。舉個例子,某個網站里有提交
"
修改的注冊信息
"
的網頁,當用戶填寫完成修改信息并提交后,服務端在進行真正的處理時需要做兩個處理:客戶端的會話是否有效;對提交的數據進行統一的編碼,比如
GB2312
。這兩個處理可以在由兩個過濾器組成的過濾鏈里進行處理。當過濾器處理成功后,把提交的數據發送到最終目標;如果過濾器處理不成功(比如客戶端的會話無效),它將把視圖派發到指定的錯誤頁面。可以看出,過濾器就像一扇門,客戶端要和服務端的某個目標交互,必須通過這扇門。
?
????
下面我們來看一個具體的例子,這個例子將介紹怎么開發過濾器,并且介紹怎么在
web.xml
文件里配置過濾器。這個例子里有兩個
JSP
頁面,前一個頁面用戶輸入一些信息然后提交,后一個頁面顯示用戶提交的信息。在提交信息后,要經過兩個過濾器的處理,一個檢查用戶是否登錄,一個把用戶的提交信息用
GB2312
進行重新編碼。
?
????
開發一個Filter,這個Filter需要實現Filter接口,Filter接口定義了以下的方法:?
destroy()?//由Web容器調用,銷毀此Filter
init(FilterConfig?filterConfig)?///由Web容器調用,初始化此Filter
doFilter(ServletRequest?request,?ServletResponse?response,?
FilterChain?chain)//具體過濾處理代碼
?
????下面我們來看對提交信息用GB2312進行重新編碼的Filter,見示例14-7、示例14-8。
????【程序源代碼】?
1?//?====================?Program?Discription?=====================
2?//?程序名稱:示例14-7?:?EncodingFilter?.java
3?//?程序目的:學習使用編碼過濾器
4?//?==============================================================
5?import?javax.servlet.FilterChain;
6?import?javax.servlet.ServletRequest;
7?import?javax.servlet.ServletResponse;
8?import?java.io.IOException;
9?import?javax.servlet.Filter;
10?import?javax.servlet.http.HttpServletRequest;
11?import?javax.servlet.http.HttpServletResponse;
12?import?javax.servlet.ServletException;
13?import?javax.servlet.FilterConfig;
14?
15?public?class?EncodingFilter?implements?Filter
16?{
17?????
18?????private?String?targetEncoding?=?"gb2312";
19?????protected?FilterConfig?filterConfig;
20?????
?
21?????public?void?init(FilterConfig?config)?throws?ServletException?{
22?????????this.filterConfig?=?config;
23?????????this.targetEncoding?=?config.getInitParameter("encoding");
24?????}
25?????
26????
27??????public??void?doFilter(ServletRequest?srequest,?
ServletResponse??sresponse,FilterChain?chain)
28?????????throws?IOException,?ServletException?{
29????????
30?????????HttpServletRequest?request?=?(HttpServletRequest)srequest;
31?????????request.setCharacterEncoding(targetEncoding);//把請求用指定的方式編碼
32?????????//?把處理發送到下一個過濾器
33????????chain.doFilter(srequest,sresponse);??
34?????}
35?????
36?????public?void?destroy()
37??{
38???this.filterConfig=null;
39??}
40?
41??public?void?setFilterConfig(final?FilterConfig?filterConfig)
42??{
43???this.filterConfig=filterConfig;
44??}
45?}
?
????【程序源代碼】?
1?//?====================?Program?Discription?=====================
2?//?程序名稱:示例14-8?:?LoginFilter.java
3?//?程序目的:學習使用登錄過濾器
4?//?==============================================================
5?import?javax.servlet.FilterChain;
6?import?javax.servlet.ServletRequest;
7?import?javax.servlet.ServletResponse;
8?import?java.io.IOException;
9?import?javax.servlet.Filter;
10?import?javax.servlet.http.HttpServletRequest;
11?import?javax.servlet.http.HttpServletResponse;
12?import?javax.servlet.ServletException;
13?import?javax.servlet.FilterConfig;
14
15?public?class?LoginFilter?implements?Filter
16?{
17??String?LOGIN_PAGE="init.jsp";
18??protected?FilterConfig?filterConfig;
?
19??public?void?doFilter(final?ServletRequest?req,final?ServletResponse?
res,FilterChain?chain)throws?IOException,ServletException
20??{
21????HttpServletRequest?hreq?=?(HttpServletRequest)req;
22??????????HttpServletResponse?hres?=?(HttpServletResponse)res;?
23??????????String?isLog=(String)hreq.getSession().getAttribute("isLog");??
24?if((isLog!=null)&&((isLog.equals("true"))||(isLog=="true")))//檢查是否登錄
25????{
26?????chain.doFilter(req,res);
27?????return?;
28????}
29????else
30?????hres.sendRedirect(LOGIN_PAGE);//如果沒有登錄,把視圖派發到登錄頁面
31??}
32??
33??public?void?destroy()
34??{
35???this.filterConfig=null;
36??}
37??public?void?init(FilterConfig?config)
38??{
39???this.filterConfig=config;
40??}
41??public?void?setFilterConfig(final?FilterConfig?filterConfig)
42??{
43???this.filterConfig=filterConfig;
44??}?
45?}
?
????【程序注解】
????正如前面所說,EncodingFilter的目的是把客戶端的請求用指定的方式編碼,具體的處理在request.setCharacterEncoding(targetEncoding)完成了。LoginFilter判斷用戶在進入目標之前是否登錄,if((isLog!=null)&&((isLog.equals("true"))||(isLog=="true")))將檢查用戶是否登錄,如果已登錄,那么把視圖讓過濾鏈繼續處理,如果沒有登錄,把視圖派發到登錄頁面,過濾鏈處理結束。
下面我們來看怎么在web.xml里配置這兩個過濾器,代碼如下所示:
????【程序源代碼】?
<web-app>
??<filter>
?????<filter-name>encoding</filter-name>?
???????????<filter-class>EncodingFilter</filter-class>?
???????????<init-param>
?????????????<param-name>encoding</param-name>
?????????????<param-value>gb2312</param-value>
?
?????</init-param>
????</filter>????
????<filter>
?????<filter-name>auth</filter-name>
?????<filter-class>LoginFilter</filter-class>
????</filter>
????
????<filter-mapping>?
???????<filter-name>encoding</filter-name>?
???????<url-pattern>/*</url-pattern>??
?????</filter-mapping>??
????<filter-mapping>
??????<filter-name>auth</filter-name>
?????<url-pattern>/target.jsp</url-pattern>
????</filter-mapping>????
</web-app>
?
????【程序注解】
????可以看出,配置Filter時,首先指定Filter的名字和Filter的實現類,如果有必要,還要配置Filter的初始參數;然后為Filter做映射,這個映射指定了需要過濾的目標(JSP、Servlet)。在上面的例子中,指定了EncodingFilter?為所有的JSP和Servlet做過濾,LoginFilter為target.jsp做過濾。這樣,當客戶請求target.jsp時,首先要經過EncodingFilter的處理,然后經過LoginFilter的處理,最后才把請求傳遞給target.jsp。?
????【運行程序】
????把程序部署到Web服務器里(比如Tomcat),然后啟動Web服務器,在瀏覽器里輸入以下URL(根據具體請求改變URL):http://127.0.0.1:8080/ch14/target.jsp?
????那么Filter將會把視圖派發到:http://127.0.0.1:8080/ch14/init.jsp?
????在init.jsp里,我們使用:?
<%?session.setAttribute("isLog","true");%>
?
????來設置用戶已經登錄(這里是簡化的,在實際項目中,可能要經過驗證處理)。在init.jsp里,可以提交一些中文的信息。由于提交的信息被EncodingFilter使用GB2312統一編碼了,故在target.jsp里能夠正確顯示中文。您可以做一個試驗,把?
<filter-mapping>?
???????<filter-name>encoding</filter-name>?
???????<url-pattern>/*</url-pattern>??
</filter-mapping>
?
改為?
<filter-mapping>?
???????<filter-name>encoding</filter-name>?
???????<url-pattern>/nothing</url-pattern>??
</filter-mapping>
????然后重新啟動Web服務器。那么在target.jsp里,中文將不能正確顯示