您的位置:首页 > 编程语言 > Java开发

基于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注解即可。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: