天天看点

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  

继续阅读