SpringMVC_第五章(攔截器和過濾器)
1:什麼是過濾器(Filter)
過濾器Filter:過濾器通過實現Filter介面,實現了過濾器的三個方法,分別是初始化方法,dofilter方法和銷燬方法,隨著容器的啟動和銷燬而初始化和銷燬,依賴於servlet容器,過濾器攔截的是位址列請求,過濾器實在進入容器後執行的servlet之前後執行,針對的在處理業務之前的操作。
chain.doFilter(request, response);這個方法的呼叫作為分水嶺。事實上呼叫Servlet的doService()方法是在這個方法中進行的。
1.1程式碼實現
過濾器程式碼:
public class Filter1 implements Filter { public void destroy() { // TODO Auto-generated method stub System.out.println("過濾器1銷燬方法"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("過濾器1,客戶端向Servlet傳送的請求被我攔截到了"); chain.doFilter(request, response); System.out.println("過濾器1,Servlet向客戶端傳送的響應被我攔截到了"); } public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub System.out.println("過濾器1初始化方法"); } }
xml配置:
<filter> <filter-name>filterDemo1</filter-name> <filter-class>com.thit.filters.Filter1</filter-class> </filter> <filter-mapping> <filter-name>filterDemo1</filter-name> <url-pattern>/*</url-pattern> <!-- /*是對所有的檔案進行攔截 --> </filter-mapping>
2:什麼是攔截器
攔截器是基於Javaf反射實現的,不依賴於servlet容器,過濾器針對於contraller方法,並且能獲取到所有的類,對類裡面所有的方法實現攔截,粒度更小,攔截器中可以注入service,也可以呼叫業務邏輯
2.1程式碼實現
攔截器1:
//攔截器1 public class LoginInterceptor implements HandlerInterceptor{ //預處理1.程式先執行preHandle()方法,如果該方法的返回值為true,則程式會繼續向下執行處理器中的方法,否則將不再向下執行。 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("1:攔截器1,程式進入preHandle方法"); User u=(User) request.getSession().getAttribute("user"); if(u==null) { System.out.println("在進入方法之前判斷session的使用者是否為空!"); System.out.println("地址:"+request.getContextPath()); //http://localhost:8080/login response.sendRedirect(request.getContextPath()+"/login"); return false; } return true; } //後處理 2.在業務處理器(即控制器Controller類)處理完請求後,會執行postHandle()方法,然後會通過DispatcherServlet向客戶端返回響應。 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub System.out.println("2:攔截器1,程式進入postHandle方法"); } //完工之後 3.在DispatcherServlet處理完請求後,才會執行afterCompletion()方法。 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub System.out.println("3:攔截器1,程式進入afterCompletion方法"); } }
攔截器2:
//攔截器2
public class Interceptor2 implements HandlerInterceptor{
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
System.out.println("1:攔截器2,進入到preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("2:攔截器2,進入到postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("3:攔截器2,進入到afterCompletion");
}
}
springxml配置:
<!--攔截器註冊 -->
<mvc:interceptors>
<!--攔截器1 -->
<mvc:interceptor>
<!--攔截不同的controller方法 -->
<!-- <mvc:mapping path="/users/search"/>
<mvc:mapping path="/users/updatepwd"/>
<mvc:mapping path="/users/search"/> -->
<!--萬用字元 攔截子節點和孫節點 -->
<mvc:mapping path="/users/**"/>
<!--在使用萬用字元的過程中 排除指定攔截 -->
<mvc:exclude-mapping path="/users/search"/>
<bean class="com.thit.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<!--攔截器2 -->
<mvc:interceptor>
<!--攔截不同的controller方法 -->
<!-- <mvc:mapping path="/users/search"/>
<mvc:mapping path="/users/updatepwd"/>
<mvc:mapping path="/users/search"/> -->
<!--萬用字元配置 -->
<mvc:mapping path="/users/**"/>
<bean class="com.thit.interceptor.Interceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
xml配置:
<!-- 方法一:這種方式預設讀取WEB-INF下的(servlet-name)+(-servlet.xml) springmvc-servlet.xml並且名字是固定的 -->
<!-- <servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> -->
<!-- 方法二:初始化引數名稱空間 namespace 必須配置檔案在放入在web-inf目錄下 -->
<!-- <servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>namespace</param-name>
<param-value>springmvc-servlet2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> -->
<!-- 方法三:初始化contextConfigLocation,將配置檔案放到任意目錄下 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- <param-value>WEB-INF/classes/springmvc/springmvc.xml</param-value> -->
<param-value>classpath*:springmvc/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3:攔截器於過濾器對比
兩者都是AOP程式設計思想的實現,都能夠實現許可權控制和日誌記錄等問題的處理,但是兩者粒度不同攔截物件不一樣
適用範圍不同:Filter是servlet的規範,只能用於web程式,但是攔截器可以用於application等程式。
規範不同:Filter是servlet的規範。但是Interceptor是spring容器支撐,有spring框架支援。
使用資源不一樣:spring的攔截器由於依賴spring,也是spring的一個元件,因此能夠在攔截器中使用spring的任何資源和物件。例如service物件,資料來源,事務管理等,通過ioc注入攔截器即可,而filter不能
粒度不同:Filter只能在servlet的前後起作用,而攔截器能在方法前後異常前後執行,更加靈活,粒度更小,spring框架程式優先使用攔截器。
4:案例執行圖
執行結果如下:
/*
0:過濾器1的初始化方法
1:過濾器1,客戶端向Servlet傳送的請求被我攔截到了
2:攔截器1的前置方法 preHandle
3:攔截器2的前置方法 preHandle
4: controller主方法
5:攔截器2的後置方法postHandle(在controller主方法執行之後執行)
6:攔截器1的後置方法postHandle(在controller主方法執行之後執行)
7:攔截器2的完成後方法afterCompletion(在DispatcherServlet處理完請求後,才會執行)
8:攔截器1的完成後方法afterCompletion(在DispatcherServlet處理完請求後,才會執行)
9:過濾器1,Servlet向客戶端傳送的響應被我攔截到了
10:過濾器的銷燬方法
*/