当前位置:   article > 正文

幂等性校验

幂等性校验

一、幂等校验思路:

前端:请求时先获取唯一标识,然后带着唯一标识去请求业务接口

后端:唯一标识生成接口:生成唯一标识,存储redis,返回前端。

            业务处理接口:在业务接口上添加自定义幂等校验注解,前端请求时,拦截器进行拦截判断该请求的方法上是否添加了幂等校验注解,如有进行校验,无放行。校验逻辑:判断redis是否存在,存在则删除该幂等标识(删除是为了防止并发问题)并放行,不存在说明是重复请求。

二、代码样例:

        1、幂等校验注解

  1. /*
  2. * 在需要保证 接口幂等性 的Controller的方法上使用此注解
  3. */
  4. @Target({ElementType.METHOD})
  5. @Retention(RetentionPolicy.RUNTIME)
  6. public @interface Idempotent {
  7. }

        2、拦截器

  1. @Component
  2. //幂等性拦截,方法上是否添加幂等性校验注解
  3. public class IdempotenceInterceptor implements HandlerInterceptor {
  4. @Autowired
  5. private IdempotentImpl idempotentImpl;
  6. @Override
  7. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  8. //判断是否是方法请求
  9. if (!(handler instanceof HandlerMethod)){
  10. return true;
  11. }
  12. HandlerMethod handlerMethod= (HandlerMethod)handler;
  13. Method method = handlerMethod.getMethod();
  14. Idempotent idempotent= method.getAnnotation(Idempotent.class);
  15. if (null !=idempotent){
  16. String idem= request.getHeader("idempotent");
  17. if (StringUtils.isEmpty(idem)){
  18. throw new GlobalException(ResponseCode.FAILUER_1.getCode(),"未携带幂等标识");
  19. }
  20. //幂等校验
  21. idempotentImpl.checkToken(idem);
  22. }
  23. return true;
  24. }
  25. }
  26. /*
  27. * @Description
  28. */
  29. @Configuration
  30. public class WebConfigurer implements WebMvcConfigurer {
  31. @Autowired
  32. private IdempotenceInterceptor idempotenceInterceptor;
  33. /*
  34. * 幂等性拦截器
  35. * */
  36. @Override
  37. public void addInterceptors(InterceptorRegistry registry) {
  38. registry.addInterceptor(idempotenceInterceptor);
  39. }
  40. }

        3、幂等标识生成校验

  1. @Component
  2. public class IdempotentImpl {
  3. private static final String IDEMPOTENT = "idempotent";
  4. @Resource
  5. private RedisSessionTemplate redisSessionTemplate;
  6. //创建一个唯一idempotent标识
  7. public String createToken() {
  8. String uuid = UUID.randomUUID().toString();
  9. //存储redis,保留固定时间,超过失效
  10. redisSessionTemplate.set(uuid, uuid, 60 * 30);
  11. return uuid;
  12. }
  13. public void checkToken(String idempotent) {
  14. //如果redis中不存在,说明该标识已请求处理
  15. if (!redisSessionTemplate.exists(idempotent)) {
  16. throw new GlobalException(ResponseCode.FAILUER_1.getCode(), "重复请求");
  17. }
  18. //防止并发问题,要判断删除是否成功,不成功说明已请求处理
  19. Long del = redisSessionTemplate.del(idempotent);
  20. if (del <= 0) {
  21. throw new GlobalException(ResponseCode.FAILUER_1.getCode(), "重复请求");
  22. }
  23. }
  24. }

        4、业务请求接口加幂等注解

  1. @RestController
  2. @RequestMapping("/test")
  3. public class TestController {
  4. @Autowired
  5. private TestService testService;
  6. @GetMapping("/selectTest")
  7. @Idempotent()
  8. public String selectTest(){
  9. try {
  10. return testService.SelectTest();
  11. }catch (Exception ex){
  12. throw new GlobalException(1001,"错误异常");
  13. }
  14. }
  15. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/416784
推荐阅读
相关标签
  

闽ICP备14008679号