自定义注解+拦截器

Posted benniaoxianfei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义注解+拦截器相关的知识,希望对你有一定的参考价值。

应用场景:限制接口访问次数;登录限制。

1.控制层入口增加自定义注解进行限制:@AccessLimit(seconds=5, maxCount=5, needLogin=true)

 //5秒内最多登陆五次

 1     @AccessLimit(seconds=5, maxCount=5, needLogin=true)
 2     @RequestMapping(value="/path", method=RequestMethod.GET)
 3     @ResponseBody
 4     public Result<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user,
 5                                          @RequestParam("goodsId")long goodsId,
 6                                          @RequestParam(value="verifyCode", defaultValue="0")int verifyCode) {
 7 
 8         if(user == null) {
 9             return Result.error(CodeMsg.SESSION_ERROR);
10         }
11 
12         boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
13         if(!check) {
14             return Result.error(CodeMsg.REQUEST_ILLEGAL);
15         }
16         String path = miaoshaService.createMiaoshaPath(user, goodsId);
17         return Result.success(path);
18     }

 

2.自定义注解AccessLimit()类及其参数

 1 import java.lang.annotation.Retention;
 2 import java.lang.annotation.Target;
 3 
 4 import static java.lang.annotation.ElementType.METHOD;
 5 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 6 
 7 /**
 8  *自定义注解
 9  */
10 @Retention(RUNTIME)
11 @Target(METHOD)
12 public @interface AccessLimit {
13 
14     int seconds();
15     int maxCount();
16     boolean needLogin() default true;
17 
18 
19 
20 }

 

3.自定义拦截器类 + 重写方法preHandle(); //实现业务逻辑

  class AccessInterceptor extends HandlerInterceptorAdapter;

  

 1 /**
 2  * SpringBoot实现拦截器
 3  * HandlerInterceptorAdapter:拦截器基类
 4  * @Date 2020-04-26 16:01
 5  */
 6 @Service
 7 public class AccessInterceptor extends HandlerInterceptorAdapter {
 8 
 9     @Autowired
10     MiaoshaUserService miaoshaUserService;
11 
12     @Autowired
13     RedisService redisService;
14 
15 
16     @Override
17     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
18                              Object handler) throws Exception {
19 
20         if(handler instanceof HandlerMethod){
21 
22             //1.根据参数获取用户信息
23             MiaoshaUser miaoshaUser = getUser(request,response);
24 
25             //2.把用户保存在ThreadLocal里
26             //收到请求---响应完成:是同一个线程
27             UserContext.setMiaoshaUser(miaoshaUser);
28 
29             //3.获取使用该注解的方法传入的参数
30             HandlerMethod handlerMethod = (HandlerMethod)handler;
31             AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
32 
33             if(accessLimit == null){
34                 //没有访问限制
35                 return true;
36             }
37             int seconds = accessLimit.seconds();
38             int maxCount = accessLimit.maxCount();
39             boolean needLogin = accessLimit.needLogin();
40 
41             String uri = request.getRequestURI();
42 
43             if(needLogin){
44                 if(null == miaoshaUser){
45                     //有访问限制,返回错误信息
46                     render(response, CodeMsg.SESSION_ERROR);
47                     return false;
48                 }else{
49                     uri = uri + "_" + miaoshaUser.getId();
50                 }
51             }else{
52                 //do nothing
53             }
54 
55             //《重构-改善既有代码的设计》martine flower
56             //校验访问次数是否超过限制
57             AccessKey accessKey = AccessKey.withExpire(seconds);
58             Integer count = redisService.getRedis(accessKey, uri, Integer.class);
59             if(null == count) {
60                 redisService.setRedis(accessKey, uri, 1);
61             }else if(count < maxCount) {
62                 redisService.incr(accessKey, uri);
63             }else {
64                 render(response, CodeMsg.ACCESS_LIMIT_REACHED);
65                 //达到访问限制,返回错误信息
66                 return false;
67             }
68         }
69         return true;
70     }

 

 

 

4.注册拦截器

  重写方法addInterceptors(InterceptorRegistry registry);

 1 /**
 2  * @Date 2020-04-09 10:49
 3  */
 4 @Configuration
 5 public class WebConfig extends WebMvcConfigurerAdapter {
 6 
 7     @Autowired
 8     UserArgumentResolver userArgumentResolver;
 9 
10     @Autowired
11     AccessInterceptor accessInterceptor;
12 
13     @Override
14     public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
15         argumentResolvers.add(userArgumentResolver);
16     }
17 
18     /**
19      * 注册拦截器
20      * @param registry
21      */
22     @Override
23     public void addInterceptors(InterceptorRegistry registry) {
24         //registry.addInterceptor(accessInterceptor);
25     }
26 }

 

 

以上是关于自定义注解+拦截器的主要内容,如果未能解决你的问题,请参考以下文章

在Spring中怎么拦截自定义的注解

SSH开发 | 配合自定义注解 和 Stratus拦截器,实现 方法级粒度 用户鉴权

自定义注解+拦截器

Springboot中使用自定义参数注解获取 token 中用户数据

[Java]利用拦截器和自定义注解做登录以及权限验证

SpringBoot+拦截器+自定义异常+自定义注解+全局异常处理简单实现接口权限管理...