Spring MVC中各個filter的用法

來源:互聯網
上載者:User

標籤:頁面   coding   commons   title   glob   app   定義   image   oid   

http://liuluo129.iteye.com/blog/1965268
springspring mvcfilter 過濾器相關類的結構

spring mvc的org.springframework.web.filter包下的Java檔案如下:


類的結構如下:

AbstractRequestLoggingFilter及其子類 

  AbstractRequestLoggingFilter類定義了兩個方法beforeRequest和afterRequest分別用於設定過濾前後執行的操作,它有三個子類,分別是CommonsRequestLoggingFilter、ServletContextRequestLoggingFilter和Log4jNestedDiagnosticContextFilter,這三個子類分別實現了各自的beforeRequest和afterRequest。其中,CommonsRequestLoggingFilter在過濾前後分別列印出一段debug的資訊;ServletContextRequestLoggingFilter在過濾前後分別向記錄檔中寫入一段日誌資訊,記錄檔可由log4j.properties等指定;Log4jNestedDiagnosticContextFilter則將日誌資訊儲存到NDC中,NDC採用了一個類似棧的機制來push和pot上下文資訊,每一個線程都獨立地儲存上下文資訊,比如說一個servlet就可以針對 每一個request建立對應的NDC,儲存用戶端地址等資訊。

CharacterEncodingFilter

該過濾器是配置編碼格式的,在web.xml中設定如下:

Xml代碼  收藏代碼<filter>    <filter-name>springCharacterEncodingFilter</filter-name>    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>    <init-param>       <param-name>forceEncoding</param-name>       <param-value>true</param-value>    </init-param>    <init-param>       <param-name>encoding</param-name>       <param-value>UTF-8</param-value>    </init-param>  </filter>  <filter-mapping>     <filter-name>springCharacterEncodingFilter</filter-name>     <url-pattern>/*</url-pattern>  </filter-mapping>  
HiddenHttpMethodFilter

html中form表單只支援GET與POST請求,而DELETE、PUT等method並不支援,spring3添加了一個過濾器,可以將這些請求轉換為標準的http方法,使得支援GET、POST、PUT與DELETE請求。可以配置如下:

Xml代碼  
<filter>      <filter-name>HiddenHttpMethodFilter</filter-name>      <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>      <init-param>          <param-name>methodParam</param-name>          <param-value>_method_</param-value>      </init-param>  </filter>  <filter-mapping>      <filter-name>HiddenHttpMethodFilter</filter-name>      <url-pattern>/*</url-pattern>  </filter-mapping>  

 

在頁面的form表單中設定method為Post,並添加一個如下的隱藏欄位:

  <input type="hidden" name="_method" value="put" />

查看HiddenHttpMethodFilter源碼

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {          String paramValue = request.getParameter(methodParam);          if("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {              String method = paramValue.toUpperCase(Locale.ENGLISH);              HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);              filterChain.doFilter(wrapper, response);          } else          {              filterChain.doFilter(request, response);          }  }  

由源碼可以看出,filter只對Post方法進行過濾,且需要添加參數名為_method的隱藏欄位,也可以設定其他參數名,比如想設定為_method_,可以在HiddenHttpMethodFilter配置類中設定初始化參數: 

Xml代碼  
<filter>       <filter-name>HiddenHttpMethodFilter</filter-name>       <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>       <init-param>          <param-name>methodParam</param-name>          <param-value>_method_</param-value>       </init-param>  </filter>   
HttpPutFormContentFilter

由HiddenHttpMethodFilter可知,html中的form的method值只能為post或get,我們可以通過HiddenHttpMethodFilter擷取put表單中的參數索引值對,而在Spring3中擷取put表單的參數索引值對還有另一種方法,即使用HttpPutFormContentFilter過濾器。

HttpPutFormContentFilter過濾器的作為就是擷取put表單的值,並將之傳遞到Controller中標註了method為RequestMethod.put的方法中。

與HiddenHttpMethodFilter不同,在form中不用添加參數名為_method的隱藏欄位,且method不必是post,直接寫成put,但該過濾器只能接受enctype值為application/x-www-form-urlencoded的表單,也就是說,在使用該過濾器時,form表單的代碼必須如下:

<form action="" method="put" enctype="application/x-www-form-urlencoded">  

......  

</form>  

配置如下:

<filter>     <filter-name>httpPutFormcontentFilter</filter-name>     <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>  </filter>  <filter-mapping>     <filter-name>httpPutFormContentFilter</filter-name>     <url-pattern>/*</url-pattern>  </filter-mapping>  
ShallowEtagHeaderFilter

ShallowEtagHeaderFilter是spring提供的支援ETag的一個過濾器,所謂ETag是指被請求變數的實體值,是一個可以與Web資源關聯的記號,而Web資源可以是一個Web頁,也可以是JSON或XML文檔,伺服器單獨負責判斷記號是什麼及其含義,並在HTTP回應標頭中將其傳送到用戶端,以下是伺服器端返回的格式:

ETag:"50b1c1d4f775c61:df3"  

用戶端的查詢更新格式是這樣的:

If-None-Match : W / "50b1c1d4f775c61:df3"  

   如果ETag沒改變,則返回狀態304然後不返回,這也和Last-Modified一樣。

   ShallowEtagHeaderFilter會將JSP等的內容緩衝,產生MD5的key,然後在response中作為Etage的header返回給用戶端。下次用戶端對相同的資源(或者說相同的url)發出請求時,用戶端會將之前產生的key作為If-None-Match的值發送到server端。 Filter會用戶端傳來的值和伺服器上的做比較,如果相同,則返回304;否則,將發送新的內容到用戶端。

查看ShallowEtagHeaderFilter的源碼如下:

 

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException{    ShallowEtagResponseWrapper responseWrapper = new ShallowEtagResponseWrapper(response, null);    filterChain.doFilter(request, responseWrapper);    // 由此可知,伺服器仍會處理請求    byte[] body = responseWrapper.toByteArray();    int statusCode = responseWrapper.getStatusCode();       if (isEligibleForEtag(request, responseWrapper, statusCode, body)) {      String responseETag = generateETagHeaderValue(body);      response.setHeader(HEADER_ETAG, responseETag);         String requestETag = request.getHeader(HEADER_IF_NONE_MATCH);      if (responseETag.equals(requestETag)) {        if (this.logger.isTraceEnabled()) {          this.logger.trace("ETag [" + responseETag + "] equal to If-None-Match, sending 304");        }        response.setStatus(304);      }      else {        if (this.logger.isTraceEnabled()) {          this.logger.trace("ETag [" + responseETag + "] not equal to If-None-Match [" + requestETag + "], sending normal response");        }        copyBodyToResponse(body, response);      }    }    else {      if (this.logger.isTraceEnabled()) {        this.logger.trace("Response with status code [" + statusCode + "] not eligible for ETag");      }      copyBodyToResponse(body, response);    }  }  

由源碼可知,ShallowEtagHeaderFilter只能根據結果判斷是否重新向用戶端發送資料,並不會不處理請求,因此節省頻寬,而不能提高伺服器效能。

配置ShallowEtagHeaderFilter的代碼如下:

 

<filter>       <filter-name>shallowEtagHeaderFilter</filter-name>       <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</fliter-class>    </filter>    <filter-mapping>       <filter-name>shallowEtagHeaderFilter</filter-name>       <servlet-name>spring</servlet-name>    </filter-mapping>  
RequestContextFilter

這是在Spring2.0時添加的類,通過LocaleContextHolder和RequestContextHolder把Http request對象基於LocalThread綁定到請求提供服務的線程上。現在一般使用DispatcherServlet這個中央分發器。現在RequestContextFilter過濾器主要用於第三方的Servlet,如JSF的FacesServlet。在Spring2.5之前都是使用該過濾器配置。配置如下:

 

<filter>        <filter-name>RequestContextFilter</filter-name>        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>RequestContextFilter</filter-name>        <servlet-name>Faces Servlet</servlet-name>    </filter-mapping>  
DelegatingFilterProxy

該類其實並不能說是一個過濾器,它的原型是FilterToBeanProxy,即將Filter作為spring的bean,由spring來管理。該類提供了在web.xml和application context之間的聯絡。

Proxy for a standard Servlet 2.3 Filter, delegating to a Spring-managed bean that implements the Filter interface. 

有以下幾個參數可以設定:

(1) contextAttribute,使用委派Bean的範圍,其值必須從org.springframework.context.ApplicationContext.WebApplicationContext中取得,預設值是session;其他可選的有request、globalSession和application

(2) targetFilterLifecycle,是否調用Filter的init和destroy方法,預設為false。

(3)targetBeanName,被代理的過濾器的bean的名字,該bean的類必須實現Filter介面。

在web.xml中配置如下:

<filter>     <filter-name>testFilter</filter-name>     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>     <init-param>        <param-name>targetBeanName</param-name>        <param-value>spring-bean-name</param-value>     </init-param>     <init-param>        <param-name>contextAttribute</param-name>       <param-value>session</param-value>     </init-param>     <init-param>        <param-name>targetFilterLifecycle</param-name>        <param-value>false</param-value>     </init-param>  </filter>          <filter-mapping>     <filter-name>testFilter</filter-name>     <url-pattern>/*</url-pattern>  </filter-mapping>  

 testBean是被spring容器管理的對象,對象的類實現了Filter介面。或者可以不用配置這個參數,這樣spring容器中所有實現了Filter介面的類都被代理,實際就是把Servlet容器中的filters同spring容器中的bean關聯起來,方便spring進行管理。

如果不配置DelegatingFilterProxy,則由於filter比bean先載入,也就是spring會先載入filter指定的類到container中,這樣filter中注入的spring bean就為null了。如果將filter中加入DelegatingFilterProxy類,"targetFilterLifecycle"指明作用於filter的所有生命週期。原理是,DelegatingFilterProxy類是一個代理類,所有的請求都會首先發到這個filter代理,然後再按照"filter-name"委派到spring中的這個bean。

此外,spring bean實現了Filter介面,但預設情況下,是由spring容器來管理其生命週期的(不是由tomcat這種伺服器容器來管理)。如果設定"targetFilterLifecycle"為True,則spring來管理Filter.init()和Filter.destroy();若為false,則這兩個方法失效。

在Spring Security中就是使用該類進行設定。即在web.xml中配置該過濾器,然後在spring security相關的配置中設定相應的過濾器bean。但是該類是spring-web包下的類,不屬於Spring Security類。

 

 

Spring MVC中各個filter的用法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.