自学内容网 自学内容网

java结合reids 实现并发去重,优雅地处理重复请求!

业务参数去重

目前的主流,我们的参数通常是一个JSON。那么针对这种场景,我们怎么去重呢?

如下面的例子,请求的其他参数是一样的,除了请求时间相差了一秒

//两个请求一样,但是请求时间差一秒
String req = "{\n" +
        "\"requestTime\" :\"20190101120001\",\n" +
        "\"requestValue\" :\"1000\",\n" +
        "\"requestKey\" :\"key\"\n" +
        "}";

String req2 = "{\n" +
        "\"requestTime\" :\"20190101120002\",\n" +
        "\"requestValue\" :\"1000\",\n" +
        "\"requestKey\" :\"key\"\n" +
        "}";

所以可以根据业务参数摘要,需要剔除这类时间字段,或者不唯一的字段参数,通过md5加密的方式作为唯一key如图:

@Slf4j
public class BootEncryptUtils {

    private static String MD5 = "MD5";

    /**
     * @param reqJSON     请求的参数,这里通常是JSON
     * @param excludeKeys 请求参数里面要去除哪些字段再求摘要
     * @return 去除参数的MD5摘要
     */
    public static String deduplicationParamMD5(String reqJSON, Collection<String> excludeKeys) {
        TreeMap paramTreeMap = JSON.parseObject(reqJSON, TreeMap.class);
        if (CollectionUtil.isNotEmpty(excludeKeys)) {
            for (String dedupExcludeKey : excludeKeys) {
                paramTreeMap.remove(dedupExcludeKey);
            }
        }
        String paramTreeMapJSON = JSON.toJSONString(paramTreeMap);
        return jdkMD5(paramTreeMapJSON);
    }

    /**
     * @param plainString 明文
     * @return cipherString 密文
     */
    public static String jdkMD5(String plainString) {
        String cipherString = null;
        try {
            // 获取实例
            MessageDigest messageDigest = MessageDigest.getInstance(MD5);
            // 计算摘要
            byte[] cipherBytes = messageDigest.digest(plainString.getBytes());
            // 输出为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : cipherBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            log.info("jdkMD5加密报错,{}", e.toString());
        }
        return cipherString;
    }

}

 通过reids的工具方法如图:

/**
     * 一定时间内相同请求参数去重
     *
     * @param key        锁的key
     * @param value      锁的value
     * @param expireTime 锁的过期时间/毫秒
     * @return 是否获取到锁
     */
    public boolean distinctRequest(String key, String value, long expireTime) {
        return Boolean.TRUE.equals(redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.set(key.getBytes(), value.getBytes(), Expiration.milliseconds(expireTime), RedisStringCommands.SetOption.SET_IF_ABSENT)));
    }

运行代码可以得到如下结果,相同的参数,在10秒内重复请求,只有第一次得到正确锁:


原文地址:https://blog.csdn.net/wcj_java/article/details/144305225

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!