我思故我強

          使用filter過濾請求

          package anni;
          public class EncodingFilter implements Filter {
          ??? public void init(FilterConfig config) throws ServletException {}
          ??? public void destroy() {}
          ??? public void doFilter(ServletRequest request,
          ??????????? ServletResponse response,
          ??????????? FilterChain chain)
          ??????????? throws IOException, ServletException {
          ??????? request.setCharacterEncoding("gb2312");
          ??????? chain.doFilter(request, response);
          ??? }
          }

          web.xml中
          <filter>
          ??? <filter-name>EncodingFilter</filter-name>
          ??? <filter-class>anni.EncodingFilter</filter-class>
          </filter>
          <filter-mapping>
          ??? <filter-name>EncodingFilter</filter-name>
          ??? <url-pattern>/*</url-pattern>
          </filter-mapping>

          filter標(biāo)簽部分定義使用的過濾器,filter-mapping標(biāo)簽告訴服務(wù)器把哪些請求交給過濾器處理。這里的/*表示所有請求,/表示根路徑,*(星號)代表所有請求,加在一起就變成了根路徑下的所有請求。這樣,所有的請求都會先被EncodingFilter攔截,并在請求里設(shè)置上指定的gb2312編碼。

          ================================
          用filter控制用戶訪問權(quán)限

          我們要保護(hù)的頁面是admin/index.jsp,為此我們在web.xml進(jìn)行如下配置。
          <filter>
          ??? <filter-name>SecurityFilter</filter-name>
          ??? <filter-class>anni.SecurityFilter</filter-class>
          </filter>
          <filter-mapping>
          ??? <filter-name>SecurityFilter</filter-name>
          ??? <url-pattern>/admin/*</url-pattern>
          </filter-mapping>

          SecurityFilter過濾器:
          public void doFilter(ServletRequest request,
          ??????? ServletResponse response,
          ??????? FilterChain chain)
          ??????? throws IOException, ServletException {
          ??? HttpServletRequest req = (HttpServletRequest) request;
          ??? HttpServletResponse res = (HttpServletResponse) response;
          ?? HttpSession session = req.getSession();
          ??? if (session.getAttribute("username") != null) {
          ??????? chain.doFilter(request, response);
          ??? } else {
          ??????? res.sendRedirect("../failure.jsp");
          ??? }
          }

          首先要將ServletRequest和ServletResponse轉(zhuǎn)換成HttpServletRequest和HttpServletResponse,因為Filter本來設(shè)計成為多種協(xié)議服務(wù),http協(xié)議僅僅是其中一部分。不過我們接觸到的也只有http,而且也只有轉(zhuǎn)換成對應(yīng)HttpServletRequest和HttpServletResponse才能進(jìn)行下面的session操作和頁面重定向。
          得到了http請求之后,可以獲得請求對應(yīng)的session,判斷session中的username變量是否為null,如果不為null,說明用戶已經(jīng)登錄,就可以調(diào)用doFilter繼續(xù)請求訪問的資源。如果為null,說明用戶還沒有登錄,禁止用戶訪問,并使用頁面重定向跳轉(zhuǎn)到failure.jsp頁面顯示提示信息。

          ==================================
          filter所謂的特性

          請求映射
          filter-mapping和servlet-mapping都是將對應(yīng)的filter或servlet映射到某個url-pattern上,當(dāng)客戶發(fā)起某一請求時,服務(wù)器先將此請求與web.xml中定義的所有url-pattern進(jìn)行匹配,然后執(zhí)行匹配通過的filter和servlet。

          你可以使用三種方式定義url-pattern。
          1.直接映射一個請求。
          <servlet-mapping>
          ??? <servlet-name>ContactServlet</servlet-name>
          ??? <url-pattern>/contact.do</url-pattern>
          </servlet-mapping>
          ???????????????????
          2.映射一個路徑下的所有請求。
          <servlet-mapping>
          ??? <servlet-name>EncodingFilter</servlet-name>
          ??? <url-pattern>/*</url-pattern>
          </servlet-mapping>

          3.映射結(jié)尾相同的一類請求。
          <servlet-mapping>
          ??? <servlet-name>ControllerServlet</servlet-name>
          ??? <url-pattern>*.do</url-pattern>
          </servlet-mapping>

          想要獲得所有以user開頭.do結(jié)尾的請求嗎?user*.do在url-pattern是無法識別的,只能配置成*.do,再去servlet中對請求進(jìn)行篩選。
          想要讓一個servlet負(fù)責(zé)多個請求嗎?/user/*,/admin/*,*.do寫在一起url-pattern也不認(rèn)識,只能配成多個servlet-mapping。
          <servlet-mapping>
          ??? <servlet-name>ControllerServlet</servlet-name>
          ??? <url-pattern>/user/*</url-pattern>
          </servlet-mapping>
          <servlet-mapping>
          ??? <servlet-name>ControllerServlet</servlet-name>
          ??? <url-pattern>/admin/*</url-pattern>
          </servlet-mapping>
          <servlet-mapping>
          ??? <servlet-name>ControllerServlet</servlet-name>
          ??? <url-pattern>*.do</url-pattern>
          </servlet-mapping>

          過濾鏈

          服務(wù)器會按照web.xml中過濾器定義的先后循序組裝成一條鏈,然后一次執(zhí)行其中的doFilter()方法。執(zhí)行的順序就如上圖所示,執(zhí)行第一個過濾器的chain.doFilter()之前的代碼,第二個過濾器的chain.doFilter()之前的代碼,請求的資源,第二個過濾器的chain.doFilter()之后的代碼,第一個過濾器的chain.doFilter()之后的代碼,最后返回響應(yīng)。
          過濾鏈的好處是,執(zhí)行過程中任何時候都可以打斷,只要不執(zhí)行chain.doFilter()就不會再執(zhí)行后面的過濾器和請求的內(nèi)容。而在實際使用時,就要特別注意過濾鏈的執(zhí)行順序問題,像EncodingFilter就一定要放在所有Filter之前,這樣才能確保在使用請求中的數(shù)據(jù)前設(shè)置正確的編碼。

          filter的詳細(xì)配置

          在servlet-2.3中,F(xiàn)ilter會過濾一切請求,包括服務(wù)器內(nèi)部使用forward轉(zhuǎn)發(fā)請求和<%@ include file="/index.jsp"%>的情況。
          到了servlet-2.4中Filter默認(rèn)下只攔截外部提交的請求,forward和include這些內(nèi)部轉(zhuǎn)發(fā)都不會被過濾,但是有時候我們需要forward的時候也用到Filter,這樣就需要如下配置。
          <filter>
          ??? <filter-name>TestFilter</filtername>
          ??? <filter-class>anni.TestFilter</filter-class>
          </filter>
          <filter-mapping>
          ??? <filter-name>TestFilter</filtername>
          ??? <url-pattern>/*</url-pattern>
          ??? <dispatcher>REQUEST</dispatcher>
          ??? <dispatcher>FORWARD</dispatcher>
          ??? <dispatcher>INCLUDE</dispatcher>
          ??? <dispatcher>EXCEPTION</dispatcher>
          </filter-mapping>
          ???????
          這樣TestFilter就會過濾所有狀態(tài)下的請求。如果我們沒有進(jìn)行設(shè)置,默認(rèn)使用的就是REQUEST。而EXCEPTION是在isErrorPage="true"的情況下出現(xiàn)的,這個用處不多,看一下即可。
          這里FORWARD是解決request.getDispatcher("index.jsp").forward(request, response);無法觸發(fā)Filter的關(guān)鍵,配置上這個以后再進(jìn)行forward的時候就可以觸發(fā)過濾器了。

          Filter還有一個有趣的用法,在filter-mapping中我們可以直接指定servlet-mapping,讓過濾器只處理一個定義在web.xml中的servlet。
          <filter-mapping>
          ??? <filter-name>TestFilter</filter-name>
          ??? <servlet-name>TestServlet</servlet-name>
          </filter-mapping>
          <servlet>
          ??? <servlet-name>TestServlet</servlet-name>
          ??? <servlet-class>anni.TestServlet</servlet-class>
          </servlet>
          <servlet-mapping>
          ??? <servlet-name>TestServlet</servlet-name>
          ??? <url-pattern>/TestServlet</url-pattern>
          </servlet-mapping>
          ??????
          直接指定servlet-name,TestFilter便會引用TestServlet配置的url-pattern,在某些filter與servlet綁定的情況下不失為一個好辦法。

          posted on 2008-07-29 16:26 李云澤 閱讀(2052) 評論(0)  編輯  收藏 所屬分類: J2EE

          主站蜘蛛池模板: 从江县| 旺苍县| 奉化市| 浦县| 宁武县| 昭通市| 龙井市| 边坝县| 松桃| 白山市| 磐石市| 荆门市| 聂荣县| 罗甸县| 武山县| 和政县| 荆州市| 五台县| 马尔康县| 平果县| 天柱县| 辉县市| 阿尔山市| 新巴尔虎左旗| 潜山县| 祥云县| 五河县| 宣威市| 阿尔山市| 安顺市| 青铜峡市| 瑞昌市| 宾阳县| 贡嘎县| 尖扎县| 陵川县| 抚宁县| 常山县| 内乡县| 绩溪县| 泰顺县|