springboot拦截器总结
Springboot 拦截器总结
拦截器大体分为两类 : handlerInterceptor 和 methodInterceptor
而methodInterceptor 又有XML 配置方法 和AspectJ配置方法
1. handlerInterceptor用法
handlerInterceptor 主要用于拦截有url映射的方法(即controller中与url有关联的方法)
[1] 先创建一个拦截器
package com.grady.interceptordemo.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 自定义拦截器 - 给予 springmvc
 * @ClassName: CustomInterceptor
 * @Description: springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。
 *                  该拦截器只能过滤action请求(即有url映射的函数,其他的不行),
 *                  spring允许有多个拦截器存在,由拦截器链管理
 *                  当preHandle return true时,执行下一个拦截器,直到所有拦截器执行完,再运行 被拦截的请求
 *                  当preHandle return false时, 不再执行 后续的拦截器链 及 被拦截的请求。
 */
@Slf4j
public class CustomInterceptor implements HandlerInterceptor {
    /**
     * 我未实现一个方法却没有报错,因为使用了Java8的语法,默认函数
     */
    /**
     * 进入对应的controller前
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("CustomInterceptor : preHandle");
        // 这里如果return false,不会执行后面的拦截器,也不会执行请求的方法了
        //return false;
        return true;
    }
    /**
     * 执行完controller方法后,但在返回对应视图前(返回json就没有返回视图的过程了)
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("CustomInterceptor : postHandle");
    }
    /**
     * 整个请求调用结束后,视图返回后,做资源清理工作
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("CustomInterceptor : afterCompletion");
    }
}
[2] 将拦截器添加到InterceptorRegistry配置中
package com.grady.interceptordemo.config;
import com.grady.interceptordemo.interceptor.CustomInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
 * WebMvcConfigurerAdapter 实际被 Deprecated 所以就不用纠结去不去继承他了,直接实现WebMvcConfigurer
 */
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
      	//这里配置了customInterceptor这个拦截器拦截所有url
        registry.addInterceptor(customInterceptor()).addPathPatterns("/**");
    }
    @Bean
    public CustomInterceptor customInterceptor() {
        CustomInterceptor customInterceptor = new CustomInterceptor();
        return customInterceptor;
    }
}
之后访问url接口,可以看到以下日志
c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : preHandle
c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : postHandle
c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : afterCompletion
2. 使用 methodInterceptor
[1] 使用XML配置方法
 XML 配置 先要创建自己的xxMethodInterceptor (实现MethodInterceptor)
@Slf4j
public class CustomMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        log.info("CustomMethodInterceptor ==> invoke method: process method name is {}", methodInvocation.getMethod().getName());
        log.info("CustomMethodInterceptor ==> invoke method: process class name is {}", methodInvocation.getMethod().getDeclaringClass());
        // 这里做自定义操作
        return methodInvocation.proceed();
    }
}
然后再xml中进行配置
spring-aop.xml (注释部分是打开对注解的支持,暂时未开)
<?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:aop = "http://www.springframework.org/schema/aop"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
  <bean id="customMethodInterceptor" class="com.grady.interceptordemo.interceptor.CustomMethodInterceptor"/>
  <aop:config proxy-target-class="false">
  <!-- 方法拦截器,基于spring aop 实现配置 -->
  <!-- 扫描使用了注解的方法进行拦截 -->
<!--  <aop:advisor pointcut="@annotation(com.grady.interceptordemo.annotation.CustomAnnotation)" advice-ref="customMethodInterceptor" />-->
  <!-- 指定包路径下的方法 -->
  <aop:advisor pointcut="execution(* com.grady.interceptordemo.controller.*.*(..))" advice-ref="customMethodInterceptor" />
  </aop:config>
</beans>
在xxxApplication.java导入XML @ImportResource("classpath:spring-aop.xml")
日志
 c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : preHandle
 c.g.i.i.CustomMethodInterceptor          : CustomMethodInterceptor ==> invoke method: process method name is hello
 c.g.i.i.CustomMethodInterceptor          : CustomMethodInterceptor ==> invoke method: process class name is class com.grady.interceptordemo.controller.HelloController
 c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : postHandle
 c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : afterCompletion
从这里也可以看出,handlerInterceptor 的prehandle方法先于methodInterceptor 的invoke方法执行,其他的方法再invoke 方法之后执行
再在spring-aop.xml中打开注解,看是否支持注解版本(这里注释掉了包扫描的拦截方式)
<?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:aop = "http://www.springframework.org/schema/aop"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
  <bean id="customMethodInterceptor" class="com.grady.interceptordemo.interceptor.CustomMethodInterceptor"/>
  <aop:config proxy-target-class="false">
  <!-- 方法拦截器,基于spring aop 实现配置 -->
  <!-- 扫描使用了注解的方法进行拦截 -->
  <aop:advisor pointcut="@annotation(com.grady.interceptordemo.annotation.CustomAnnotation)" advice-ref="customMethodInterceptor" />
  <!-- 指定包路径下的方法 -->
<!--  <aop:advisor pointcut="execution(* com.grady.interceptordemo.controller.*.*(..))" advice-ref="customMethodInterceptor" />-->
  </aop:config>
</beans>
日志一致,说明是生效的
c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : preHandle
c.g.i.i.CustomMethodInterceptor          : CustomMethodInterceptor ==> invoke method: process method name is hello
c.g.i.i.CustomMethodInterceptor          : CustomMethodInterceptor ==> invoke method: process class name is class com.grady.interceptordemo.manager.impl.HelloManagerImpl
c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : postHandle
c.g.i.interceptor.CustomInterceptor      : CustomInterceptor : afterCompletion
[2] 再看AspectJ版本(推荐方式)
SpectJ 不需要XML 配置,比较方便
 直接声明切面切点就搞定问题了
@Component
@Slf4j
public class AspectJInterceptor {
    // 声明一个切点,表示从哪里切入增强,这里是切controller目录下的所有public 方法
    @Pointcut("execution (* com.grady.interceptordemo.controller.*.*(..))")
    public void logPoint() {
    }
  	//声明切面的执行方式,这里是环绕切面,环绕切是有返回值的Object
    @Around("logPoint()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        log.info("AspectJInterceptor around的函数为:" + point.getSignature());
        log.info("AspectJInterceptor around 方法开始时间 : " + startTime);
        Object obj = point.proceed();// ob 为方法的返回值
        log.info("AspectJInterceptor  around 耗时 : " + (System.currentTimeMillis() - startTime));
        return obj;
    }
}
这样就可以了
查看日志
AspectJInterceptor around的函数为:String com.grady.interceptordemo.controller.HelloController.hello()
c.g.i.interceptor.AspectJInterceptor     : AspectJInterceptor around 方法开始时间 : 1567261903109
c.g.i.interceptor.AspectJInterceptor     : AspectJInterceptor  around 耗时 : 9
说明生效了
上面是根据表达式寻找函数切的;现在换基于注解切
修改代码
@Aspect
@Component
@Slf4j
public class AspectJInterceptor {
    // 声明一个切点 基于注解
    @Pointcut("@annotation(com.grady.interceptordemo.annotation.CustomAnnotation)")
    public void logPoint2() {
    }
    @Around("logPoint2()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        log.info("AspectJInterceptor around的函数为:" + point.getSignature());
        log.info("AspectJInterceptor around 方法开始时间 : " + startTime);
        Object obj = point.proceed();// ob 为方法的返回值
        log.info("AspectJInterceptor  around 耗时 : " + (System.currentTimeMillis() - startTime));
        return obj;
    }
}
日志:
2019-08-31 22:45:52.275  INFO 4516 --- [nio-8080-exec-1] c.g.i.interceptor.AspectJInterceptor     : AspectJInterceptor around的函数为:String com.grady.interceptordemo.manager.impl.HelloManagerImpl.hello()
2019-08-31 22:45:52.276  INFO 4516 --- [nio-8080-exec-1] c.g.i.interceptor.AspectJInterceptor     : AspectJInterceptor around 方法开始时间 : 1567262752274
可以看的是HelloManagerImpl.hello 方法上有注解,所以切面方法中打印的是这个方法;而之前的版本切的位置是controller包中的方法,所以打印的是HelloController.hello
PS:
可以在application.properties 中打开这个开关,开启CGlib ,(这个实验中不开是可以的,原因是当spring aop 无效时(比如没有实现接口的类controller),会自动使用CGLib尝试)
# 启用CGLib 来实现aop
# spring.aop.proxy-target-class=true
springboot拦截器总结的更多相关文章
- Java结合SpringBoot拦截器实现简单的登录认证模块
		Java结合SpringBoot拦截器实现简单的登录认证模块 之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章 ... 
- SpringBoot拦截器中Bean无法注入(转)
		问题 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于其他bean在service,controller层注入一点问题也没有,开始根本没意识到Be ... 
- 【SpringBoot】SpringBoot拦截器实战和 Servlet3.0自定义Filter、Listener
		=================6.SpringBoot拦截器实战和 Servlet3.0自定义Filter.Listener ============ 1.深入SpringBoot2.x过滤器Fi ... 
- SpringBoot拦截器中无法注入bean的解决方法
		SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ... 
- Springboot拦截器未起作用
		之前遇到要使用springboot拦截器却始终未生效的状况,查了网上的博客,大抵都是@Component,@Configuration注解未加,或是使用@ComponentScan增加包扫描,但是尝试 ... 
- SpringBoot拦截器中service或者redis注入为空的问题
		原文:https://my.oschina.net/u/1790105/blog/1490098 这两天遇到SpringBoot拦截器中Bean无法注入问题.下面介绍我的思考过程和解决过程: 1.由于 ... 
- springboot + 拦截器 + 注解 实现自定义权限验证
		springboot + 拦截器 + 注解 实现自定义权限验证最近用到一种前端模板技术:jtwig,在权限控制上没有用springSecurity.因此用拦截器和注解结合实现了权限控制. 1.1 定义 ... 
- Springboot 拦截器配置(登录拦截)
		Springboot 拦截器配置(登录拦截) 注意这里环境为springboot为2.1版本 1.编写拦截器实现类,实现接口 HandlerInterceptor, 重写里面需要的三个比较常用的方 ... 
- Springboot拦截器实现IP黑名单
		Springboot拦截器实现IP黑名单 一·业务场景和需要实现的功能 以redis作为IP存储地址实现. 业务场景:针对秒杀活动或者常规电商业务场景等,防止恶意脚本不停的刷接口. 实现功能:写一个拦 ... 
- SpringBoot 拦截器获取http请求参数
		SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 目录 SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 获取http请求参数是一种刚需 定义拦截器获取请求 为 ... 
随机推荐
- 使用C++的ORM框架QxORM
			QxORM中,我们用的最多的无非是这两点 官方表述是这样的: 持久性: 支持最常见的数据库,如 SQLite.MySQL.PostgreSQL.Oracle.MS SQL Server.MongoDB ... 
- UiPath Orchestrator安装步骤
			UiPath Orchestrator安装步骤 答案在这 https://rpazj.com/thread-219-1-1.html 
- 简单性能测试:springboot-2.x vs actix-web-4.x benchmark
			性能测试:springboot-2.x vs actix-web-4.x benchmark 转载请注明出处 https://www.cnblogs.com/funnyzpc/p/15956465.h ... 
- 测试右移:线上质量监控 ELK 实战
			目录 [测试右移]介绍 ELK Stack 介绍 ELK 监控体系搭建 ES & Kibana 搭建 Nginx 日志自动采集 Nginx Agent 安装 Nginx 服务器 数据分析 Lo ... 
- springboot中的任务处理
			springboot中的任务处理 一.异步任务 在开发中有时用户提交的数据,后台需要一定时间才能做出响应,此时用户在前台也不能在等待中,此时就应该先开启异步请求处理,利用多线程,先给前台反馈,后台另一 ... 
- 常用类-jdk8之前的日期和API
			一.System静态方法 点击查看代码 package com.Tang.StringDay01; import org.junit.Test; public class DateTimeTest { ... 
- 总结vue 需要掌握的知识点
			使用的开发工具是webstorm,它是默认就安装好了vuejs插件,idea要使用的话,需要安装一下该插件 一.快速搭建项目vue-cli 脚手架(Vue2.0) 1.Vue CLI使用前提 –Nod ... 
- 07 MySQL_SQL数据类型
			数据类型 整数类型: int(m) 对应java中的int bigint(m) 对应java中的long m代表显示长度,需要结合 zerofill使用 create table t_int(id i ... 
- 动手实践丨手把手教你用STM32做一个智能鱼缸
			摘要:本文基于STM32单片机设计了一款基于物联网的智能鱼缸. 本文分享自华为云社区<基于STM32+华为云IOT设计的物联网鱼缸[玩转华为云]>,作者: DS小龙哥 . 1. 前言 为了 ... 
- Hadoop-HA 搭建高可用集群Hadoop Zookeeper
			Hadoop Zookeeper 搭建(一) 一.准备工作 VMWARE虚拟机 CentOS 7 系统 虚拟机1:master 虚拟机2:node1 虚拟机3:node2 时间同步 ntpdate n ... 
