詳述SpringMVC中Interceptor攔截器

目錄

一、自定義攔截器類

二、配置攔截器

三、執行順序

1.preHandle

2.postHandle

3.afterCompletion 


一、自定義攔截器類

首先創建如下項目:

在web.xml中配置DispatchServlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>springsun</display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:application.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
</web-app>

在Controller容器中創建攔截/userinfo/toView.do請求的Handler方法:

package club.affengkuang.userinfo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserInfoController {
	
	@RequestMapping("/userinfo/toView.do")
	public String toView() {
		System.out.println("toView......");
		return "to";
	}
}

接下來自定義攔截器:

創建AccessInterceptor類,實現HandlerInterceptor接口,並重寫接口中的三個抽象方法preHandle、postHandle、afterCompletion,攔截器便自定義完成:

package club.affengkuang.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

//創建一個HandlerInterceptor接口實現類
public class AccessInterceptor implements HandlerInterceptor {
	
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("preHandle......");
		return true;
	}
		
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("postHandle......");
	}

	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("afterCompletion......");
	}
}

二、配置攔截器

在application中配置15到17行mvc:interceptors標籤內配置剛纔自定義好的AccessInterceptor類:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<context:component-scan base-package="club.affengkuang"></context:component-scan>
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/view/" p:suffix=".jsp"></bean>
	
	<mvc:interceptors>
		<bean class="club.affengkuang.interceptor.AccessInterceptor"></bean>
	</mvc:interceptors>
</beans>

測試:

三、執行順序

在請求處理過程中,攔截器中三個方法的執行順序如下:

1.preHandle

preHandle方法在目標方法(Handler方法)執行前執行,一般用於校驗,以下是底層代碼分析:

請求處理執行過程見博客:SpringMVC中servlet請求處理過程

當使用debug方式,執行到DispatchServlet類中doDispatch方法時:

第962行:進入applyPreHandle方法

進入applyPreHandle後:

第129行:創建一個上轉型對象數組,將所有攔截器對象賦值到父類接口的數組變量中,其中[1]中便是我們自定義的Accessinterceptor類對象

第131行:遍歷interceptors中每個元素

第133行:此處使用多態,表層調用的是接口中preHandle方法,實則調用的是上轉型對象重寫的preHandle方法,也就是我們實現的preHandle方法; 

注意:在preHandle方法中返回值爲Boolean類型

①假設該方法返回false時,該行if語句爲true,執行if代碼塊

第135行:applyPreHandle方法返回false

上面的doDispatch方法中也直接結束執行,所以執行結果中只有preHandle方法被執行了:

②假設該方法返回true時,該行if語句爲true,執行第140行語句,返回true:

回到doDispatch方法:

第967行:handle方法處理servlet中請求

2.postHandle

接着上面的源碼分析:

進入第974行代碼中的applyPostHandle方法:執行原理與preHandle方法相同,只不過在第151行執行的是在AccessInterceptor類中實現的postHandle方法:

3.afterCompletion 

隨後執行到第984行,進入processDispatchResult方法:

然後執行到processDispatchResult方法中:

第1027行:如果此時沒發生異常,exception爲null,則不執行此代碼;

第1059行:執行triggerAfterCompletion方法; 

執行原理與前面兩個方法原理相同,此處169行執行的是在AccessInterceptor類中實現的afterCompletion方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章