1、如果每次都从Redis获取token,会有很多冗余代码
2、使用面向切面编程的思想
在不改变源代码或者很少改变源代码的情况下,增强类的某些方法。
在业务代码之前设置 切入点
创建切面类,也就是比如登录校验的某些公共方法
切面类从切入点切入流程,形成切面
2.1、创建注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLogin {
}
2.2、创建切面类
进行token校验
/**
* 切面类
* @Author 伊人秋采唐
* @Date 2024/8/10
*/
@Component //交给spring管理
@Aspect //切面类 标识这是一个切面类
public class MyLoginAspect {
@Autowired
private RedisTemplate redisTemplate;
//环绕通知,登录判断 Around
//切入点表达式:指定对哪些规则的方法进行增强
@Around("execution(* com.example.*.controller.*.*(..)) && @annotation(MyLogin)")
public Object login(ProceedingJoinPoint proceedingJoinPoint, MyLogin myLogin) throws Throwable {
//1 获取request对象
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();//Spring提供的工具类
ServletRequestAttributes sra = (ServletRequestAttributes)attributes;
assert sra != null;
HttpServletRequest request = sra.getRequest();
//2 从请求头获取token
String token = request.getHeader("token");
//3 判断token是否为空,如果为空,返回登录提示
if(!StringUtils.hasText(token)) {
throw new MyException("");
}
//4 token不为空,查询redis
String customerId = (String)redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX+token);
//5 查询redis对应用户id,把用户id放到ThreadLocal里面
if(StringUtils.hasText(customerId)) {
AuthContextHolder.setUserId(Long.parseLong(customerId));
}
//6 执行业务方法
return proceedingJoinPoint.proceed();
}
}
2.3、使用注解标识
表示这是一个切入点,在执行此方法之前,先执行切面方法
@MyLogin
@GetMapping("/getCustomerLoginInfo")
public Result getCustomerLoginInfo() {