天天看點

SpringBoot2.X學習之Intercepter攔截器

本節課對SpringBoot2.0以及之前版本的攔截器進行講解

在SpringBoot1.x的版本中實作攔截器,首先寫一個自定義攔截器實作addInterceptors接口,實作其三個方法:

package com.qzsun.springbootdemo.intecpter;

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

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

public class LoginIntercepter implements HandlerInterceptor{

	/**
	 * 進入controller方法之前
	 */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("LoginIntercepter------->preHandle");

//		String token = request.getParameter("access_token");
//
//		response.getWriter().print("fail");

		return HandlerInterceptor.super.preHandle(request, response, handler);
	}

	/**
	 * 調用完controller之後,視圖渲染之前
	 */
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {

		System.out.println("LoginIntercepter------->postHandle");

		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}

	/**
	 * 整個完成之後,通常用于資源清理
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("LoginIntercepter------->afterCompletion");

		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}



}
           

然後寫一個配置類繼承WebMvcConfigurerAdapter,然後重寫其addInterceptors()方法,并将剛剛寫的攔截器注冊進去,并加上攔截規則:

package com.qzsun.springbootdemo.intecpter;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author sunqizheng
 * @Title: CustomOldWebMvcConfigurer
 * @ProjectName springbootdemo
 * @Description: 2.0版本之前攔截器,方法過時了
 * @date 2019/1/3113:34
 */
//@Configuration
public class CustomOldWebMvcConfigurer extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/");
        super.addInterceptors(registry);
    }
}
           

但是該寫法在2.0版本中已經過時了,我們點進源碼檢視發現其已被@Deprecated掉了,原因在源碼的注釋上已經寫清楚了:

@deprecated從Spring5.0開始{@link WebMvcConfigurer}具有預設方法(由Java 8基線實作),可以直接實作而無需此擴充卡

SpringBoot2.X學習之Intercepter攔截器
SpringBoot2.X學習之Intercepter攔截器

下面我們進行新版本攔截器的實作,第一步也是寫一個自定義攔截器,就沿用剛剛寫的攔截器,然後寫一個配置類實作WebMvcConfigurer接口,重寫addInterceptors()方法,注意加上注解@Configuration納入容器管理,然後在裡面注冊之前寫好的LoginIntercepter,然後加上攔截路徑,注意:如果是攔截所有的話就是":

/**
 * @author sunqizheng
 * @Title: CustomWebMvcConfigurer
 * @ProjectName springbootdemo
 * @Description: 攔截器配置,類似于以前mvc項目的Spring配置檔案中配置攔截器
 * @date 2019/1/3113:57
 */
@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //攔截器最後路徑一定要 “/**”, 如果是目錄的話則是 /*/
        //如果是攔截所有的話就是"/**"
        registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/*/**");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}
           

然後在controller中加一個接口供測試使用:

@RequestMapping("/api/test/intercepter")
    public String intercepter(){
        System.out.println("--------測試攔截器-----");
        return "index";
    }
           

啟動并通路http://localhost:8081/api/test/intercepter

SpringBoot2.X學習之Intercepter攔截器

攔截器起作用了, preHandle()在進入controller方法之前調用,postHandle()在調用完controller之後,視圖渲染之前調用

,afterCompletion()在整個請求完成之後,通常用于資源清理

如果是兩個攔截器,他們的順序是先定義的先攔截,下面我們再自定義一個攔截器,并注冊到配置類中:

package com.qzsun.springbootdemo.intecpter;

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

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

public class TwoIntercepter implements HandlerInterceptor{

	/**
	 * 進入對應的controller方法之前
	 */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {

		System.out.println("TwoIntercepter------>preHandle");
		return HandlerInterceptor.super.preHandle(request, response, handler);
	}

	/**
	 * controller處理之後,傳回對應的視圖之前
	 */
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("TwoIntercepter------>postHandle");
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}

	/**
	 * 整個請求結束後調用,視圖渲染後,主要用于資源的清理
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("TwoIntercepter------>afterCompletion");
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}

	
}
           
@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //攔截器最後路徑一定要 “/**”, 如果是目錄的話則是 /*/
        //如果是攔截所有的話就是"/**"
        registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/*/**");
        registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api/*/**");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}
           

 啟動運作,我們發現果真是先定義的先執行,但是在執行完handle方法之後就是先定義的後執行了,就像兩個同心圓,handle方法在最裡面,外面一層是攔截器2,最外面一層是攔截器1。

SpringBoot2.X學習之Intercepter攔截器

 補充:我們可以使用.excludePathPatterns()方法排除掉不需要攔截的路徑:

SpringBoot2.X學習之Intercepter攔截器

Filter與Intercepter的差別:

Filter

        是基于函數回調 doFilter(),而Interceptor則是基于AOP思想

        Filter在隻在Servlet前後起作用,而Interceptor夠深入到方法前後、異常抛出前後等

        依賴于Servlet容器即web應用中,而Interceptor不依賴于Servlet容器是以可以運作在多種環境。

        在接口調用的生命周期裡,Interceptor可以被多次調用,而Filter隻能在容器初始化時調用一次。

        Filter和Interceptor的執行順序

        過濾前->攔截前->action執行->攔截後->過濾後

源碼位址:https://gitee.com/xuxinsunqizheng/SpringBoot2.0.git  

繼續閱讀