赞
踩
注解代码:
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface RepeatSubmit {
-
- /**
- * 过期时间,单位毫秒
- */
- long expireTime() default 500L;
-
- }
注解工具类:
- package com.psbchn.config;
-
- import com.psbchn.handler.annotation.RepeatSubmit;
- import com.psbchn.handler.exception.base.BaseException;
- import lombok.extern.slf4j.Slf4j;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
-
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import java.lang.reflect.Method;
- import java.util.concurrent.TimeUnit;
-
- /**
- * 防止表单重复提交切面
- *
- * @Author lwz
- * @Date 2023/11/22 10:13
- */
- @Slf4j
- @Aspect
- @Component
- public class RepeatSubmitAspect {
- private static final String KEY_PREFIX = "repeat_submit:";
- @Resource
- private RedisTemplate redisTemplate;
-
- @Pointcut("@annotation(com.psbchn.handler.annotation.RepeatSubmit)")
- public void repeatSubmit() {}
-
- @Around("repeatSubmit()")
- public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
- //joinPoint获取方法对象
- Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
- //获取方法上的@RepeatSubmit注解
- RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
- //获取HttpServletRequest对象,以获取请求uri
- ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- HttpServletRequest request = requestAttributes.getRequest();
- String uri = request.getRequestURI();
- //拼接Redis的key,这里只是简单根据uri来判断是否重复提交。可以根据自己业务调整,比如根据用户id或者请求token等
- String cacheKey = KEY_PREFIX.concat(uri);
- Boolean flag = null;
- try {
- //借助setIfAbsent(),key不存在才能设值成功
- flag = redisTemplate.opsForValue().setIfAbsent(cacheKey, "", annotation.expireTime(), TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- //如果Redis不可用,则打印日志记录,但依然对请求放行
- log.error("", e);
- return joinPoint.proceed();
- }
- //Redis可用的情况,如果flag=true说明单位时间内这是第一次请求,放行
- if (flag) {
- return joinPoint.proceed();
- } else {
- //进入else说明单位时间内进行了多次请求,则拦截请求并提示稍后重试
- throw new BaseException("系统繁忙,请稍后重试");
- }
- }
- }
使用方法 :
- /**
- * 新增文件分类
- *
- * @param fileCategoryVo
- * @return true
- */
- @RepeatSubmit
- @ResponseBody
- @ApiOperation(value = "文件分类新增", notes = "", httpMethod = "POST")
- @RequestMapping(value = "/insert", produces = {MediaType.APPLICATION_JSON_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.POST)
- public RestResponse<Boolean> insertFileCategory(@RequestBody FileCategoryVo fileCategoryVo) {
-
- boolean flag = fileCategoryService.insertFileCategory(fileCategoryVo);
- if (flag) {
- return RestResponse.ok("增加成功");
- } else {
- return RestResponse.fail("增加失败");
- }
- }
2.通过幂等性控制
这个不懂啊~~谁知道怎么做,推荐一个链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。