java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > redis 接口防重复提交

Java结合redis实现接口防重复提交

作者:帆非凡

本文主要介绍了Java结合redis实现接口防重复提交,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

redis 接口防重

技术点:redis/aop

说明:

简易版本实现防止重复提交,适用范围为所有接口适用,采用注解方式,在需要防重的接口上使用注解,可以设置防重时效。

场景:

在系统中,经常会有一些接口会莫名其妙的被调用两次,可能在幂等接口中不会存在太大的问题,但是非幂等接口的处理就会导致出现脏数据,甚至影响系统的正确性。

选型参考:

在常见的防重处理分为多种,粗分为前端处理,后端处理

前端处理分为:

后端处理分为:

选型原因

以上内容都是瞎BB的,其实我也是个菜鸟,欢迎各位大佬提建议或者意见,大家共同进步,共同完善,让java圈充满激情四射的爱。

代码样例

@PostMapping("/user/update")
@ApiOperation(value = "修改用户信息", notes = "修改用户信息", tags = "user module")
@AvoidReSubmit(expireTime = 1000 * 3)
public void update(@RequestBody User user){
 userMapper.updateById(user);
}

具体代码实现

// 定义自定义注解,设置注解参数默认值
package top.withu.gaof.freehope.annotate;

import java.lang.annotation.*;


/**
 * @author Gaofan
 * @date 2019年10月12日 下午2:54:45
 * @describe 防止重复提交
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AvoidReSubmit {

    /**
     * 失效时间,即可以第二次提交间隔时长
     * @return
     */
    long expireTime() default 30 * 1000L;
}

// 定义切面进行处理
package top.withu.gaof.freehope.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import top.withu.gaof.freehope.annotate.AvoidReSubmit;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO
 * @Author: gaofan
 * @Date: 2019/10/12 16:10
 * @Copyright: 2019 www.blog.freehope.top Inc. All rights reserved.
 **/
@Aspect
@Component
public class AvoidResumitAspect {

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 定义匹配规则,以便于后续拦截直接拦截submit方法,不用重复表达式
     */
    @Pointcut(value = "@annotation(top.withu.gaof.freehope.annotate.AvoidReSubmit)")
    public void submit() {
    }

    @Before("submit()&&@annotation(avoidReSubmit)")
    public void doBefore(JoinPoint joinPoint, AvoidReSubmit avoidReSubmit) {

        // 拼装参数
        StringBuffer sb = new StringBuffer();
        for(Object object : joinPoint.getArgs()){
            sb.append(object);
        }

        String key = md5(sb.toString());
        long expireTime = avoidReSubmit.expireTime();
        ValueOperations valueOperations = redisTemplate.opsForValue();
        Object object = valueOperations.get(key);
        if(null != object){
            throw new RuntimeException("您已经提交了请求,请不要重复提交哦!");
        }
        valueOperations.set(key, 1, expireTime, TimeUnit.MILLISECONDS);
    }

    @Around("submit()&&@annotation(avoidReSubmit)")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint, AvoidReSubmit avoidReSubmit) throws Throwable {
        System.out.println("环绕通知:");
        Object result = null;
        result = proceedingJoinPoint.proceed();
        return result;
    }

    @After("submit()")
    public void doAfter() {
        System.out.println("******拦截后的逻辑******");
    }

    private String md5(String str){
        if (str == null || str.length() == 0) {
            throw new IllegalArgumentException("String to encript cannot be null or zero length");
        }
        StringBuffer hexString = new StringBuffer();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte[] hash = md.digest();
            for (int i = 0; i < hash.length; i++) {
                if ((0xff & hash[i]) < 0x10) {
                    hexString.append("0" + Integer.toHexString((0xFF & hash[i])));
                } else {
                    hexString.append(Integer.toHexString(0xFF & hash[i]));
                }
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return hexString.toString();
    }
}

思路:

简单的通过redis实现,估计版本在网上非常多了。这里的一个思路还是mark一下,现在我这代码只有我和上帝知道什么意思,我怕一个月以后就只有上帝知道了。

到此这篇关于Java结合redis实现接口防重复提交的文章就介绍到这了,更多相关redis 接口防重复提交内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

您可能感兴趣的文章:
阅读全文