1. 程式人生 > >SpringMVC_第五章(攔截器和過濾器)

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:過濾器的銷燬方法

*/