SpringBoot拦截器的使用介绍

目录
  • 定义拦截器
    • 实现HandleInterceptor接口
    • 继承HandleInterceptorAdapter类
    • 实现WebRequestInterceptor接口
    • 实现RequestInterceptor接口
    • 小插曲 @Configuration和@Component区别
  • 注册拦截器
    • 继承WebMvcConfigurerAdapter类
    • 继承WebMvcConfigurationSupport类
    • 实现WebMvcConfigurer接口
    • 应用场景
  • 拦截器执行流程
    • 单个拦截器
    • 多个拦截器
  • 总结

定义拦截器

拦截器:所谓拦截器,就是能够在进行某个操作之前拦截请求,如果请求符合条件就允许在往下执行。比如说,海关就是一个拦截器,他拦截进出口的货物,如果货物满足进出口条件,则放行,否则就拦截,退回处理。

定义拦截器的几种方式:

实现HandleInterceptor接口

自定义拦截器类实现HandleInterceptor接口,并使用@Component注解标注为一个组件。

public class MySelfInterceptor implements HandlerInterceptor {
	@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	System.out.println("在业务处理器处理请求之前被调用");
    	return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
		System.out.println("在业务处理器处理请求执行完成后,生成视图之前执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		System.out.println("在DispatcherServlet完全处理完请求后被调用");
    }
}

根据三种情况,可以在不同的方法针对请求进行额外的处理。
在preHandle中,可以进行权限校验,安全控制。
在postHandle中,可以对返回来的ModelAndView进行处理,这个时候还未渲染视图。
在afterCompletion中,请求已经完成,页面已经渲染,数据已经返回。这个时候可以做一些资源清理,或者记录请求调用时间,做性能监控

继承HandleInterceptorAdapter类

自定义拦截器类继承HandleInterceptor接口的实现类HandleInterceptorAdapter来定义,并使用@Component注解标注为一个组件。建议使用此方式可以根据需要覆盖一些方法

@Component
public class MyInterceptor extends HandlerInterceptorAdapter {

    public SingleLoginInterceptor() {
        super();
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        super.afterConcurrentHandlingStarted(request, response, handler);
    }
}

可以看到HandlerInterceptorAdapter类底层是实现了HandlerInterceptor接口,多了两个方法,要比
实现HandlerInterceptor接口的方式功能强大。
这两个方法都是HandlerInterceptorAdapter类实现的org.springframework.web.servlet.AsyncHandlerInterceptor接口提供的,而AsyncHandlerInterceptor接口又继承了HandlerInterceptor接口,所以HandlerInterceptorAdapter底层是实现类HandlerInterceptor接口。

实现WebRequestInterceptor接口

自定义拦截器类实现WebRequestInterceptor接口,并使用@Component注解标注为一个组件。

@Component
public class MyInterceptor implements WebRequestInterceptor {

    @Override
    public void preHandle(WebRequest webRequest) throws Exception {

    }

    @Override
    public void postHandle(WebRequest webRequest, ModelMap modelMap) throws Exception {

    }

    @Override
    public void afterCompletion(WebRequest webRequest, Exception e) throws Exception {

    }
}

两个实现接口方式的异同点 相同点 都可以实现controller层的拦截请求 不同点
1.WebRequestInterceptor的入参WebRequest是包装了HttpServletRequest 和HttpServletResponse的,通过WebRequest获取Request中的信息更简便。
2.WebRequestInterceptor的preHandle是没有返回值的,说明该方法中的逻辑并不影响后续的方法执行,所以这个接口实现就是为了获取Request中的信息,或者预设一些参数供后续流程使用。
3.HandlerInterceptor的功能更强大也更基础,可以在preHandle方法中就直接拒绝请求进入controller方法。
4.使用场景:这个在上条已经说了,如果想更方便获取HttpServletRequest的信息就使用WebRequestInterceptor,当然这些HandlerInterceptor都能做,只不过要多写点代码

实现RequestInterceptor接口

自定义类实现RequestInterceptor接口,此方式为微服务Feign调用的自定义拦截器,实现各个微服务之间的参数传递。

@Configuration
public class CenterinsRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {

    }
}

小插曲 @Configuration和@Component区别

这里使用了@Configuration注解而不是@Component,其实@Configuration本质上也是一个@Component,只不过前者描述的类中所有用@Bean标记的方法都会由CGLIB动态代理执行,在首次调用的时候会执行,然后把执行结果放到Spring上下文,之后对该方法的调用都是从Spring上下文上取的结果,所以都是指同一个实例。而使用了@Component,所有用@Bean标记的方法都是纯Java调用,每次都是生成不同的实例对象。如果要让使用了@Compnent注解的类中其@Bean标记的方法生成都是同一个实例,只需要使用@AutoWired标记属性,自动注入即可。

@Configuration
public class MyBeanConfig {

    @Bean
    public Country country(){
        return new Country();
    }

    @Bean
    public UserInfo userInfo(){
        return new UserInfo(country());
    }

}

 // 以上代码 等同于以下代码
 // 以下代码去掉Autowired注入,则country方法是不同的实例对象。

@Component
public class MyBeanConfig {

    @Autowired
    private Country country;

    @Bean
    public Country country(){
        return new Country();
    }

    @Bean
    public UserInfo userInfo(){
        return new UserInfo(country);
    }

}

注册拦截器

注册拦截器在springboot中直接使用注解便可实现。

继承WebMvcConfigurerAdapter类

 1.创建一个自定义类,继承WebMvcConfigurerAdapter类重写addInterceptors方法。

@Configuration
public class WebCofiguration extends WebMvcConfigurerAdapter {
    public void addInterceptors(InterceptorRegistry registry) {
    		// 将自己定义的拦截器注入进来进行拦截操作
        registry.addInterceptor(new MySelfInterceptor ())
                .addPathPatterns("/**")
                .excludePathPatterns("/logout");
                //过滤器可以添加多个,这里的addPathPatterns的/**是对所有的请求都做拦截。
                //excludePathPatterns代表排除url的拦截路径,即不拦截
    }
}

此类在SpringBoot2.0以后已经废除,但仍可使用。推荐使用以下两种方式来代替此方式。

继承WebMvcConfigurationSupport类

 2.创建一个自定义类继承WebMvcConfigurationSupport类,实现addInterceptors。

@Configuration
public class MyInterceptorConfig extends WebMvcConfigurationSupport {

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}

此方式会导致默认的静态资源被拦截,这就需要我们手动将静态资源放开。
除了重写方法外还需要重写addResourceHandlers方法来释放静态资源

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    super.addResourceHandlers(registry);
}

实现WebMvcConfigurer接口

 3.创建一个自定义类实现WebMvcConfigurer接口,重写addInterceptors方法。

@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 实现WebMvcConfigurer不会导致静态资源被拦截
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }
}

此方式不会拦截静态资源

应用场景

由于这两种方式的不同:
继承 WebMvcConfigurationSupport类的方式推荐用在前后端分离的项目中,后台不需要访问静态资源(就不需要放开静态资源了),当然也可以在前后端不分离中,如果需要访问静态资源使用上面的方式重写addResourceHandlers方法即可;
实现 WebMvcConfigure接口的方式推荐用在非前后端分离的项目中,因为需要读取一些图片、css、js文件等等,当然也可以使用在前后端分离项目。

拦截器执行流程

单个拦截器

对单个拦截器执行流程解释如下:
程序首先会执行拦截器类中的preHandle()方法,如果该方法返回true,则程序会继续向下执行处理器中的方法,否则程序将不再往下继续执行。在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应,在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。
因此单个拦截器的执行流程:
prehandle()——Handle(也就是控制器里的方法)——postHandle()——afterCompletion()。

多个拦截器

在大型的企业级项目中,通常会配置多个拦截器来实现不同的功能。例如我们自定义了三个拦截器A、B、C。并将它们都注册到同一个拦截器配置类中,如下图

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AInterceptor())
                .addPathPatterns("/**");

        registry.addInterceptor(new BInterceptor())
                .addPathPatterns("/**");

        registry.addInterceptor(new CInterceptor())
                .addPathPatterns("/**");
    }
}

它们的preHandle()方法会按照配置文件中拦截器的配置顺序执行,而它们的postHandle()和afterCompletion()方法则会按照配置顺序的反序执行。
因此当前我们的三个拦截器执行顺序如下:
preHandleA——preHandleB——preHandleC——Handle——postHandleC——postHandleB——postHandleA——afterCompletionC——afterCompletionB——afterCompletionA

总结

到此这篇关于SpringBoot拦截器的使用介绍的文章就介绍到这了,更多相关SpringBoot拦截器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解决SpringBoot自定义拦截器和跨域配置冲突的问题

    目录 SpringBoot自定义拦截器和跨域配置冲突 技术栈 问题引出 原代码 新代码 SpringBoot 拦截器和addCorsMappings冲突 SpringBoot自定义拦截器和跨域配置冲突 技术栈 vue-cli3,springboot 2.3.2.RELEASE 问题引出 在做毕业设计过程中用到了自定义拦截器验证登录.同时在springboot配置类中设置了跨域问题,出现跨域失败的情况. 原代码 @Configuration public class WebConfig exten

  • springboot 拦截器执行两次的解决方案

    springboot拦截器执行两次 原因是: org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error 也是一个controller路径为/error @Configuration public class MVCConfig extends WebMvcConfigurationSupport { //自定义的拦截器 @Bean public SecurityInterceptor g

  • 浅谈Springboot实现拦截器的两种方式

    目录 一.拦截器方式 1.配置HandlerInterceptor 2.注册拦截器 3.使用拦截器的坑 二.过滤器方式 1.实现Filter接口 2.使用过滤器需要注意的 实现过滤请求有两种方式: 一种就是用拦截器,一种就是过滤器 拦截器相对来说比较专业,而过滤器虽然不专业但是也能完成基本的拦截请求要求. 一.拦截器方式 1.配置HandlerInterceptor 下面这个也是我们公司项目拦截器的写法,总体来说感觉还不错,我就记录了下来. 利用了一个静态Pattern变量存储不走拦截器的路径,

  • springboot项目拦截器重定向循环问题的解决

    目录 springboot项目拦截器重定向循环 解决办法 springboot拦截器无限循环报错 springboot项目拦截器重定向循环 本菜鸟很久没写东西了,这回是解决了一个小问题,希望能帮助到你. 最近写了一个项目,项目中写了登录拦截器,session过期的用户请求会重定向到登录页面. 写完测试发现session过期后浏览器一直提示重定向次数过多. 打开浏览器F12看到一直都在访问/login/login/login之类的无限循环路径. 后来经过网上查询发现我之前设置重定向地址时直接设置的

  • SpringBoot拦截器的使用介绍

    目录 定义拦截器 实现HandleInterceptor接口 继承HandleInterceptorAdapter类 实现WebRequestInterceptor接口 实现RequestInterceptor接口 小插曲 @Configuration和@Component区别 注册拦截器 继承WebMvcConfigurerAdapter类 继承WebMvcConfigurationSupport类 实现WebMvcConfigurer接口 应用场景 拦截器执行流程 单个拦截器 多个拦截器 总

  • SpringBoot拦截器的配置使用介绍

    目录 1. 配置拦截器 2. 一个小 Demo 1. 自定义拦截器类—LoginInterceptor 2. 将拦截器注册到容器中 3. 原理分析 1. 配置拦截器 具体步骤: 编写一自定义拦截器类实现接口 HandlerInterceptor HandlerInterceptor 接口: 可在三处进行拦截——目标方法执行之前.目标方法执行完成.页面渲染以后拦截 public interface HandlerInterceptor { default boolean preHandle(Htt

  • SpringBoot拦截器的使用小结

    总结一下SpringBoot下拦截器的使用,步骤很简单: 1.自定义自己的拦截类,拦截类需要继承HandlerInterceptor接口并实现这个接口的方法. @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //方法调用前执行 return true;//返回

  • SpringBoot拦截器如何获取http请求参数

    1.1.获取http请求参数是一种刚需 我想有的小伙伴肯定有过获取http请求的需要,比如想 前置获取参数,统计请求数据 做服务的接口签名校验 敏感接口监控日志 敏感接口防重复提交 等等各式各样的场景,这时你就需要获取 HTTP 请求的参数或者请求body,一般思路有两种,一种就是自定义个AOP去拦截目标方法,第二种就是使用拦截器.整体比较来说,使用拦截器更灵活些,因为每个接口的请求参数定义不同,使用AOP很难细粒度的获取到变量参数,本文主线是采用拦截器来获取HTTP请求. 1.2.定义拦截器获

  • springboot拦截器无法注入redisTemplate的解决方法

    在工作中我们经常需要做登录拦截验证或者其他拦截认证功能,基于springboot项目下我们很容易想到结合redis做的分布式拦截,把用户登录或者需要验证的信息放到redis里面.但是在写拦截器的时候发现redisTemplate一直无法注入进来,最后查资料才发现springboot拦截器是在Bean实例化之前执行的,所以Bean实例无法注入. 先看下问题,新建一个拦截器,然后注入redisTemplate /** * @author: lockie * @Date: 2019/8/13 16:1

  • SpringBoot 拦截器妙用你真的了解吗

    HandlerInterceptor 详解 HandlerInterceptor 允许定制 handler 处理器执行链的工作流接口.我们可以自定义拦截器用于拦截 handlers 处理器(你可以理解为 controller 层的接口),从而可以添加一些共同的重复性的处理行为(例如接口鉴权,接口日志记录,性能监控等),而不用修改每一个 handler 的实现. 注意,此基于 SpringBoot 2.3.12.RELEASE 版本讲解. HandlerInterceptor 接口只有三个默认空实

  • SpringBoot拦截器以及源码详析

    目录 1.拦截器是什么 2.自定义拦截器 2.1 编写拦截器 2.2 注册和配置拦截器 3.拦截器原理 3.1 找到可以处理请求的handler以及handler的所有拦截器 3.2 执行拦截器的preHandle方法 3.3 执行目标方法 3.4 执行拦截器的postHandle方法 3.5 执行拦截器的afterCompletion方法 3.6 异常处理 4.总结 1.拦截器是什么 java里的拦截器(Interceptor)是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一

  • springboot拦截器Interceptor的使用,你都了解吗

    springmvc 中的拦截器可以对请求进行判别, 在请求到达控制器之前, 把非法的请求给拦截掉 下面来说一说, 它在springboot中的使用 拦截器是可以有多个的, 对不同的 url 进行拦截 我们这个例子设想的是, 如果用户登录过, 就会用户设置一个 session , 如果session中 有user 的信息,就说明用户是登录过的 1.我们先创建一个 User 的实例对象 domain public class User { private Integer id; private St

  • 关于SpringBoot拦截器中Bean无法注入的问题

    问题 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于其他bean在service,controller层注入一点问题也没有,开始根本没意识到Bean无法注入是在拦截器中无效的问题,一直在查找注解指定的包在哪里配置的,然而却找不到配置,Springboot是用java类的形式加载配置的.在网络的某个角落看到这样的说法: SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描! "Applicati

  • SpringBoot拦截器的使用

    目录 一.拦截器简介 二.拦截器配置使用方式 1.过滤器拦截器作用范围 2.拦截器的使用 三.知识点总结 1.拦截器的使用 2.拦截器和过滤器的相同与不同 一.拦截器简介 拦截器通常通过动态代理的方式来执行. 拦截器的生命周期由IoC容器管理,可以通过注入等方式来获取其他Bean的实例,使用更方便. 二.拦截器配置使用方式 1.过滤器拦截器作用范围 2.拦截器的使用 示例代码如下: package com.rongrong.wiki.interceptor; import org.slf4j.L

随机推荐