Spring 攔截器(附代碼鏈接)

最後附有網盤鏈接(程序打包+數據庫)

Spring 攔截器

1、定義與應用場景

攔截器是spring中的一個重要概念(類似於Filter過濾器)。他被註冊到spring,攔截指定規則的請求,基於回調機制執行。一般來說,攔截器只會攔截action請求,這一點與過濾器不同。

應用場景:
權限檢查:如是否已經登錄,或則對某些數據具有增刪改查等權限;

日誌記錄:可以記錄請求信息的日誌,以便進行信息監控,信息統計等;

性能監控:慢日誌等。

2、攔截器接口

1.處理器攔截器(HandlerIntercepto):

public interface HandlerInterceptor {

   /**
     * 預處理回調方法,實現處理器的預處理(如檢查登陸),第三個參數爲響應的處理器,自定義Controller
     * 返回值:true表示繼續流程(如調用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

   /**
     * 後處理回調方法,實現處理器的後處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能爲null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

   /**
    * 整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間並輸出消耗時間,還可以進行一些資源清理,類似於try-catch-finally中的finally,但僅調用處理器執行鏈中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

3、攔截流程

攔截器執行順序按照Spring配置文件中定義的順序執行;

首先按照執行順序執行所有攔截器的preHandle()方法【用於預處理等】,如果遇到返回值是false,則不會執行還未執行的攔截器,而是直接倒序執行afterCompletion()方法,如果爲true,則依次執行剩下的攔截器;

如果所有攔截器的preHandle()方法返回值都爲true,則執行相應的控制層接口(controller),如果在該接口中有異常拋出,則和preHandle()方法返回false一樣,不會執行postHandle(),而是直接倒序執行afterCompletion()方法;

如果接口(controller)中業務邏輯執行完成(頁面還未渲染數據),會倒序執行postHandle()方法,渲染完數據後,然後倒序執行afterCompletton()方法。

4、來個流程圖解釋

本次以兩個攔截器更深度地解釋
在這裏插入圖片描述
運行結果

01:04:46.196 [http-nio-8080-exec-2] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 1301 ms
01:04:46.205 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/springmvc/fileUploadPage", parameters={}
01:04:46.210 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to init.wuji.springboot.mvc.fileupload.action.FileUploadAction#fileUploadPage()
=======MyHandlerInterceptor==========>preHandle
-------------MySecondInterceptor==========preHandle
-------------MySecondInterceptor==========postHandle
=======MyHandlerInterceptor==========>postHandle
01:04:46.233 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.view.JstlView - View name 'success', model {}
01:04:46.239 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.view.JstlView - Forwarding to [/views/success.jsp]
-------------MySecondInterceptor==========afterCompletion
=======MyHandlerInterceptor==========>afterCompletion
01:04:46.245 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

注意順序

上代碼

首先兩個攔截器代碼
第一個文件名:/springmvc/src/main/java/init/wuji/springboot/mvc/interceptor/MyHandlerInterceptor.java
代碼:

package init.wuji.springboot.mvc.interceptor;

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

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

public class MyHandlerInterceptor implements HandlerInterceptor{

	/**
	 * preHandle方法在handler方法執行之前攔截用戶的請求,如果返回false,表示中斷後續操作,如果返回true,表示向下繼續執行。
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("=======MyHandlerInterceptor==========>preHandle");
		return true;
	}

	/**
	 * postHandle 該方法在handler方法調用之後,解析視圖之前執行;我們可以通過此方法對請求域中的modle和view進行修改
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		//request.getParameter();
		if(modelAndView != null) {
			modelAndView.setViewName("success");
		}
		
		System.out.println("=======MyHandlerInterceptor==========>postHandle");
	}

	/**
	 * afterCompletion 此方法在handler方法執行完畢之後(視圖渲染結束),我們可以通過此方法釋放資源,記錄日誌等操作,及異常處理
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("=======MyHandlerInterceptor==========>afterCompletion");
	}

	
	
}

第二個攔截器
文件名:/springmvc/src/main/java/init/wuji/springboot/mvc/interceptor/MySecondInterceptor.java
代碼:

package init.wuji.springboot.mvc.interceptor;

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

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

public class MySecondInterceptor implements HandlerInterceptor{

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("-------------MySecondInterceptor==========preHandle");
		return true;
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("-------------MySecondInterceptor==========postHandle");
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("-------------MySecondInterceptor==========afterCompletion");
	}

}

然後是上下文的配置
文件名:/springmvc/src/main/resources/config/applicationContext-mvc.xml
代碼:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        ">
    <context:component-scan base-package="init.wuji.springboot.mvc.*.action"></context:component-scan>    
	
	<!-- 
	配置視圖解析器
	 -->
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>	
		
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 上傳文件的最大值, 單位爲:字節  50*1024*1024 
		
		-->
		<property name="maxUploadSize" value="#{50*1024*1024}" />
	</bean>

	<mvc:annotation-driven>
		 <mvc:message-converters>
		 	<!-- register-defaults="true"表示使用默認的消息轉換器 -->
            <!-- FastJson(Spring4.2x以上版本設置) -->
            <!-- 使用@responsebody註解並且返回值類型爲String時,返回的string字符串帶有雙引號"{'user':'songfs'}",其原因是直接將string類型轉成了json字符串,應該在json解析器之前添加字符串解析器-->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <!-- FastJsonHttpMessageConverter4 使@ResponseBody支持返回Map<String,Object>等類型,它會自動轉換爲json-->
            <!-- 需要返回json時需要配置 produces = "application/json"。不需要再指定utf-8-->
            <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <!-- 加入支持的媒體類型 -->
                <property name="supportedMediaTypes">
                    <list>
                        <!-- 這裏順序不能反,一定先寫text/html,不然IE執行AJAX時,返回JSON會出現下載文件 -->
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>application/xml;charset=UTF-8</value>
                    </list>
                </property>
                <property name="fastJsonConfig">
                    <bean class="com.alibaba.fastjson.support.config.FastJsonConfig">
                        <property name="features">
                            <list>
                                <value>AllowArbitraryCommas</value>
                                <value>AllowUnQuotedFieldNames</value>
                                <value>DisableCircularReferenceDetect</value>
                            </list>
                        </property>
                        <property name="dateFormat" value="yyyy-MM-dd HH:mm:ss"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
	</mvc:annotation-driven>
	
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- mvc:mapping 中配置需要攔截的路徑 -->
			<mvc:mapping path="/**"/>
			
			<!--exclude-mapping 中配置需要剔除攔截的路徑 -->
			<mvc:exclude-mapping path="/ws/userWsList"/>
			<bean class="init.wuji.springboot.mvc.interceptor.MyHandlerInterceptor"></bean>
		</mvc:interceptor>
		
		<mvc:interceptor>
			<!-- mvc:mapping 中配置需要攔截的路徑 -->
			<mvc:mapping path="/userInfoRest/**"/>
			<bean class="init.wuji.springboot.mvc.interceptor.MySecondInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>
	<!-- 
	SSM:spirng springmvc  mybatis
	
	spirngboot 
	儘量不要將業務代碼 與 框架配置信息放到一起
	<mvc:view-controller path="/userInfo/userAddInit" view-name="user/add"/>
	 -->
</beans>

下課

鏈接

鏈接:https://pan.baidu.com/s/1_8Hs6V06GdX7ia5fYV4MlQ
提取碼:7s8u

發佈了21 篇原創文章 · 獲贊 29 · 訪問量 6288
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章