小言_互联网的博客

java使用redis生成唯一编号工具类

413人阅读  评论(0)

       在项目中,我们经常遇到需要生成订单编号、字典编号等唯一值场景,大部分的服务器环境都是负载均衡,多台机器,那么此时我们必须考虑多并发的问题,所以需要借助redis来实现编号生成的功能。

       我的实现思路是redis锁限制为单线程模式,防并发,再获取redis编号key,进而分配到最新的编号。

GenerateCaseNumberUtil.java代码如下:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @FileName: GenerateCaseNumber
 * @Description: 生成案件编号,生成规则:LD/XZ/MS/SS/XS (2位)+年(4位)+自增序列号(5位)共11位
 * @author: v-guoxingliang.ea
 * @create: 2018-07-09 17:26
 * @Copyright: (c) 2018年 ****公司
 */
@Slf4j
@Component
public class GenerateCaseNumber {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RedissonClient client;

    /**
     * <p>Description: [
     * 生成案件编号,生成规则:
     * LD/XZ/MS/SS/XS (2位)+年(4位)+自增序列号(5位)共11位
     * 劳动争议案件类型:LD
     * 行政诉讼案件类型:XZ
     * 民事诉讼案件类型:MS
     * 商事诉讼案件类型:SS
     * 刑事诉讼案件类型:XS]</p>
     * Created on: 2018/9/3  16:49
     * @author v-guoxingliang.ea
     * @param caseType LD/XZ/MS/SS/XS
     * @return java.lang.String
     */
    public String getCaseNumber(String caseType) throws VerifyException {
        RLock lock = client.getLock(RedisConstantUtil.REDIS_CASE_NUMBER_GENERATE_LOCK);
        try {
            lock.lock(10, TimeUnit.SECONDS);
            String date = new SimpleDateFormat("yyyy").format(new Date());
            String seq = seqGenerator(new SimpleDateFormat("yyyy").format(new Date()), 5, 1, RedisConstantUtil.REDIS_CASE_NUMBER_GENERATE);
            return caseType + date + seq;
        } catch (Exception e) {
            log.warn("caseType=[{}]", caseType, e);
            throw new VerifyException(LanguageUtil.get(ConstantsUtils.GENERATE_CASE_NUMBER_ERROR_MSG));
        } finally {
            lock.unlock();
        }
    }

    /**
     * <p>Description: [自增序列号]</p>
     * Created on: 2018/7/31  14:51
     * @author v-guoxingliang.ea
     * @param prefix 前缀
     * @param numLength 要生成多少位的数字
     * @param startNum 起始数字
     * @return java.lang.String
     */
    public String seqGenerator(String prefix, int numLength, int startNum, String key) {
        String upperCode = "";
        //查找以prefix作为key值的数据长度
        Long size = redisTemplate.opsForList().size(key);
        //有数据
        if (size > 0) {
            //获取该key下面的所有值 (-1所有值;1下一个值)
            List all = redisTemplate.opsForList().range(key, 0, -1);
            //返回最后一个值
            upperCode = all.get(all.size() - 1).toString();
        }
        String returnCode = "";
        //后缀数字
        int suffix;
        if (!StringUtils.isEmpty(upperCode)) {//有数据
            //截取前缀开始的后面数字
            suffix = Integer.parseInt(upperCode);
            //最后的序号加一
            suffix++;
        } else {//没有数据
            suffix = startNum;
        }
        //后缀不够numLength长,前面补充0
        String str = "%0" + numLength + "d";
        returnCode = String.format(str, suffix);
        //存入Redis
        redisTemplate.opsForList().rightPush(key, returnCode);
        return returnCode;
    }
}

常量类RedisConstantUtil.java代码如下:

public class RedisConstantUtil {
    private RedisConstantUtil() {}

    /*生成案件编码key */
    public static final String REDIS_CASE_NUMBER_GENERATE = "case:generate:caseNumber:";
    public static final String REDIS_CASE_NUMBER_GENERATE_LOCK = "case:generate:caseNumber:lock";
}

上述用到的redis的jar包:

<!-- 集成了redis这个jar就不要重复引入了 -->
<dependency>
	 <groupId>org.springframework.data</groupId>
	 <artifactId>spring-data-redis</artifactId>
	 <version>1.8.13.RELEASE</version>
</dependency>

<!-- redisson -->
<dependency>
     <groupId>org.redisson</groupId>
     <artifactId>redisson</artifactId>
     <version>3.9.1</version>
</dependency>

其中VerifyException是自定义异常。


转载:https://blog.csdn.net/qq_16207635/article/details/101205695
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场