基于SpringAOP思想的拦截器,摒弃了InterceptorAdapter
2020-07-13 06:11
666 查看
每次当涉及到权限验证的时候,大家最先想到的就是基于SpringMVC的InterceptorAdapter拦截器来进行基础的权限验证,但是这个拦截器有这样一个问题,就是默认会拦截所有的请求,那么这个时候我们就可以基于AOP的思想,那些地方需要被拦截,只要关注这些地方就行了。下面直接上代码
基础技术 SpringBoot+JWT
pom文件如下:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> <!-- SpringBoot 拦截器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.5</version> </dependency>
下面开始代码
1.AnnotationUtils工具类
import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * 获取注解工具类 * * @author wuhx 2020-05-15 09:23 */ public class AnnotationUtils { private static final Log log = LogFactory.get(); /** * 获取方法上的注解 * * @param method 执行方法 * @param annotation 注解的class * @return 返回注解实现对象, 如果没有, 则返回null */ public static <T extends Annotation> T getAnnotation(Method method, Class<T> annotation) { if (method != null) { try { return method.getAnnotation(annotation); } catch (Exception e) { log.error(("获取方法上注解异常"), e); return null; } } return null; } /** * 获取类上的注解 * * @param aClass 执行方法 * @param annotation 注解的class * @return 返回注解实现对象, 如果没有, 则返回null */ @SuppressWarnings("unchecked") public static <A extends Annotation> A getClassAnnotation(Class aClass, Class<A> annotation) { if (aClass != null) { try { return (A) aClass.getAnnotation(annotation); } catch (Exception e) { log.error(("获取类上注解异常"), e); return null; } } return null; } /** * 获取属性上的注解 * * @author wuhx 2020-05-15 09:25 */ public static <T extends Annotation> T getFieldAnnotation(Class aClass, Class<T> annotation, String name) { try { return aClass.getDeclaredField(name).getAnnotation(annotation); } catch (NoSuchFieldException e) { return null; } } }
2.AspectUtils工具类
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.MethodSignature; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * @author wuhx 22020-05-15 09:23 */ public class AspectUtils { /** * 获取织入点所在的方法 * * @param point 织入点 * @return 方法 */ public static Method getMethod(ProceedingJoinPoint point) { Signature signature = point.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; return methodSignature.getMethod(); } /** * 获取织入点所在的类 * * @param point 织入点 * @return 类 */ public static Class getClass(ProceedingJoinPoint point) { return getMethod(point).getDeclaringClass(); } /** * 获取执行织入点上的注解 * * @param point 执行织入点 * @param annotation 注解的class * @return 返回注解实现对象, 如果没有, 则返回null */ public static <T extends Annotation> T getAnnotation(ProceedingJoinPoint point, Class<T> annotation) { return AnnotationUtils.getAnnotation(getMethod(point), annotation); } /** * 获取执行方法的类上的注解,如果方法上拥有相同注解,则以方法上的为准, * * @param point 执行织入点 * @param annotation 注解的class * @return 返回注解实现对象, 优先返回方法上的, 如果没有, 返回类上的 ,如果没有 则返回null */ public static <T extends Annotation> T getClassAnnotation(ProceedingJoinPoint point, Class<T> annotation) { Method method = getMethod(point); Class aClass = method.getDeclaringClass(); T t = AnnotationUtils.getAnnotation(method, annotation); // 如果方法上没有相同注解,则返回类上的注解 if (t == null) { return AnnotationUtils.getClassAnnotation(aClass, annotation); } return t; } }
3.自定义注解
/** * @author wuhx 2020-05-12 14:12:19 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface TokenApp { // 是否校验token 默认true 进行token校验 boolean value() default true; }
4.定义拦截
/** * @author wuhx 2020-05-12 15:04:42 */ @Aspect @Order @ControllerAdvice public class TokenAppAspect { private final Audience audience; private final HttpServletRequest request; public TokenAppAspect(Audience audience,HttpServletRequest request) { this.audience = audience; this.request = request; } @Pointcut("@annotation(zhiyan.applets.base.annotation.TokenApp) || @within(zhiyan.applets.base.annotation.TokenApp)") public void pointcut(){} @Around("pointcut()") public Object filter(ProceedingJoinPoint point) throws Throwable{ return check(point, AspectUtils.getClassAnnotation(point, TokenApp.class)); } private Object check(ProceedingJoinPoint point, TokenApp tokenApp) throws Throwable{ if (tokenApp != null && tokenApp.value()){ String token = request.getHeader("token"); //token为空 if (StrUtil.isEmpty(token) || "null".equals(token)){ return HttpResult.error("token为空"); } if (JwtTokenUtil.isExpiration(token,audience.getBase64Secret())){ return HttpResult.error("token过期"); } } return point.proceed(); } }
下面,来看我们的Controller
只要在方法上加上@TokenAPP注解,那么这个方法就会进行校验。如果整个controller里面的方法都需要进行token校验,那么只要在类上 加上@TokenAPP注解即可。
相关文章推荐
- 利用方法拦截器优化Ibatis更新策略 —— 基于POJO、CGLIB、SPRING AOP
- 基于AOP设计思想的拦截器(Interceptor)与传统拦截器(Filter)的区别
- 在Struts中基于Spring的AOP MethodInterceptor(拦截器)的权限验证
- 在Struts中基于Spring的AOP MethodInterceptor(拦截器)的权限验证
- Spring的基于Aspectj的注解配置的AOP开发
- 基于spring security及spring aop的权限控制
- Spring3.0 入门进阶(3):基于XML方式的AOP使用
- 基于AspectJ的Spring-AOP
- spring aop aspectj 基于注解
- Spring Aop 日志拦截器
- spring aop的使用(注解方式以及基于xml配置方式)
- spring AOP拦截器的配置使用
- 基于AspectJ的SpringAOP开发
- Spring基于XML配置AOP
- Spring基于XML配置AOP
- Spring Aop原理分析(二) - Aop的拦截器和通知
- Spring AOP原理及拦截器
- Spring的AOP思想研究和实现
- Spring基于annotation的AOP(AspectJ)
- spring boot 拦截器 或 Spring AOP 方式记录请求日志