利用redis生成订单号

目录

  1. 订单号生成
  2. redis单机与集群

 

单据号生成器:

  • 使用redis操作自增序列号:yyyyMMdd{4位随机数}{bizCode}{6位流水号:6位的自增序列号}
  • key=包名:业务类型+yyyymmdd,设置key后需要设置过期时间
  • key2:radom值为4位随机数

这里设置随机数是为了防止宕机后,生成重复的订单号。为了方便遍历使用以及保证订单号整体自增,把随机数改为redis服务器时间(HHmmss)。

​
package com.test.util;

import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;

/**
 * 
 * @ClassName: SerialNumberUtil
 * @Description: 订单号生成工具类
 * @author
 * @date 2018年7月30日 上午10:56:56
 *
 */
public class SerialNumberUtil {

	/**
	 * 根据两位业务类型码字符串,生成一个流水号,格式按照:
	 * yyyyMMdd{Redis服务器6位时间}{bizCode}{6位流水号:6位的自增序列号}
	 * 
	 * @param bizCode两位业务类型码字符串,00-99
	 * @return 22位的序列号
	 * @throws Exception
	 */
	public static String createNo(String bizCode) {

		// JedisClientSingle jedis = new JedisClientSingle();
		Jedis jedis = new Jedis("localhost");

		Logger log = Logger.getLogger(SerialNumberUtil.class);

		String pacName = StringUtil.getPacName();// 获取当前类所在的包名
		log.info("pacName:" + pacName);

		String date = StringUtil.getToday(); // 时间yyMMdd
		log.info("Time(yyMMdd):" + date);

		String key = pacName + bizCode + date;// 构建订单号key
		log.info("key:" + key);

		String key2 = pacName + "time";
		String redisTime = StringUtil.getRedisTime();// 获取redis服务器的时间HHmmss

		log.info("redis服务器当前时间:" + redisTime);

		if (StringUtil.isLegal(bizCode)) {
			jedis.incr(key);
			jedis.expire(key, 60 * 60 * 48);// 过期时间48小时
			log.info("key(expire:)" + jedis.ttl(key) + "s");
		}
		if (jedis.get(key2) == null) {
			jedis.set(key2, redisTime);
		}

		String v = "";
		v = jedis.get(key);
		v = StringUtil.autoCOS(v);
		v = bizCode + date + jedis.get(key2) + v;
		log.info("value:" + v);
		return v;
	}

}

​

    上面所用到的方法:

​
package com.test.util;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import org.apache.commons.lang3.RandomStringUtils;

import redis.clients.jedis.Jedis;

/**
 * 
 * @ClassName: StringUtil
 * @Description: 自增序列工具类
 * @author
 * @date 2018年7月20日 下午2:04:34
 *
 */
public class StringUtil {
	static final int DEFAULT_LENGTH = 6;

	private static Jedis jedis = new Jedis("localhost");

	public static String getSequence(long seq) {
		String str = String.valueOf(seq);
		int length = str.length();
		if (length >= DEFAULT_LENGTH) {// 每天超过6位
			return str;
		}
		int rest = DEFAULT_LENGTH - length;
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < rest; i++) {
			sb.append('0');
		}
		sb.append(str);
		return sb.toString();
	}

	/**
	 * 
	 * @Title: autoCOS 
	 * @Description: 补全6位字符串(Auto completion of string) 
	 * @return 参数
	 * @return String 返回类型 
	 * @throws
	 */
	public static String autoCOS(String value) {

		int length = value.length();
		if (length >= DEFAULT_LENGTH) {
			return value;
		}
		int rest = DEFAULT_LENGTH - length;
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < rest; i++) {
			sb.append('0');
		}
		sb.append(value);
		return sb.toString();
	}

	/**
	 * 
	 * @Title: isLegal
	 * @Description: 对bizCode进行白名单验证,以免恶意伪造
	 * @param
	 * @return 参数
	 * @return boolean 返回类型
	 * @throws BizCodeException
	 */
	public static boolean isLegal(String bizCode) {
		if (bizCode == null || bizCode.length() != 2) {
			throw new BizCodeException(bizCode);
		}
		if (Character.isDigit(bizCode.charAt(0)) && Character.isDigit(bizCode.charAt(1)))
			return true;
		return false;
	}

	/**
	 * 
	 * @Title: getPacName
	 * @Description: 获取包名
	 * @param @return 参数
	 * @return String 返回类型
	 */
	public static String getPacName() {
		String clzName = Thread.currentThread().getStackTrace()[1].getClassName();
		int index = clzName.lastIndexOf(".");
		String pacName = clzName.substring(0, index) + ":";
		return pacName;
	}

	/**
	 * 
	 * @Title: getRandom
	 * @Description: 获取四位随机数
	 * @param @return 参数
	 * @return String 返回类型
	 */
	public static Set<String> m = new HashSet<String>();

	public static String getRandom() {
		String randomDigit;
		do {
			randomDigit = RandomStringUtils.random(4, false, true);
		} while (m.contains(randomDigit));
		m.add(randomDigit);
		return randomDigit;
	}

	/**
	 * 
	 * @Title: getToday
	 * @Description: 获取今天的日期:yyyyMMdd
	 * @param @return 参数
	 * @return String 返回类型
	 */
	public static String getToday() {
		return new SimpleDateFormat("yyyMMdd").format(new Date());
	}

	/**
	 * 
	 * @Title: getRedisTime 
	 * @Description:获取Redis服务器的时间HHssmm 
	 * @param @return参数 
	 * @return String 返回类型 
	 * @throws
	 */
	public static String getRedisTime() {
		List<String> time = jedis.time();
		Long timestamp = Long.parseLong(time.get(0)) * 1000;
		String redisTime = new SimpleDateFormat("HHmmss", Locale.CHINA).format(new Date(timestamp));
		return redisTime;

	}
}

​

    maven+spring+redis配置

    pom.xml

	<!-- Redis客户端 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>${jedis.version}</version>
		</dependency>

    applicationContext-jedis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    <!-- 加载配置文件 -->
    <context:property-placeholder ignore-unresolvable="true" 
              location="classpath:redis.properties" />
	<!-- 连接池配置 -->
	 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大连接数 -->
		<property name="maxTotal"><value>${redis.maxTotal}</value>
		</property>
		<!-- 最大空闲连接数 -->
		<property name="maxIdle"><value>${redis.maxIdle}</value></property>
		<!-- 每次释放连接的最大数目 -->
		<property name="numTestsPerEvictionRun">
		<value>${redis.numTestsPerEvictionRun}</value></property>
		<!-- 释放连接的扫描间隔(毫秒) -->
		<property name="timeBetweenEvictionRunsMillis">
		<value>${redis.timeBetweenEvictionRunsMillis}</value></property>
		
		<!-- 连接最小空闲时间 -->
		<property name="minEvictableIdleTimeMillis">
		<value>${redis.minEvictableIdleTimeMillis}</value></property>
		
	    <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
		<property name="softMinEvictableIdleTimeMillis">
	    <value>${redis.softMinEvictableIdleTimeMillis}</value></property>
		
		<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
		<property name="maxWaitMillis"><value>${redis.maxWaitMillis}</value></property>
		<!-- 在获取连接的时候检查有效性, 默认false -->
		<property name="testOnBorrow"><value>${redis.testOnBorrow}</value></property>
		<!-- 在空闲时检查有效性, 默认false -->
		<property name="testWhileIdle"><value>${redis.testWhileIdle}</value></property>
		<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
		<property name="blockWhenExhausted"><value>${redis.blockWhenExhausted}</value></property>
	</bean>	 
	 
	<!-- jedis客户端单机版 -->
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="${redis.host}"></constructor-arg>
		<constructor-arg name="port" value="${redis.port}" type="int"></constructor-arg>
		<constructor-arg name="timeout" value="${redis.timeout}" type="int"></constructor-arg>
		<constructor-arg name="password" value="${redis.password}"></constructor-arg>
		<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
	</bean>
	<bean id="jedisClient" class="com.test.dao.impl.JedisClientSingle"/>
		
	<!-- jedis集群版配置 -->
	<!-- <bean id="redisClient" class="redis.clients.jedis.JedisCluster">
		<constructor-arg name="nodes">
			<set>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="${redis.host1}"></constructor-arg>
					<constructor-arg name="port" value="${redis.post1}" type="int"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="${redis.host2}"></constructor-arg>
					<constructor-arg name="port" value="${redis.post2}" type="int"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="${redis.host3}"></constructor-arg>
					<constructor-arg name="port" value="${redis.post3}" type="int"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="${redis.host4}"></constructor-arg>
					<constructor-arg name="port" value="${redis.post4}" type="int"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="${redis.host5}"></constructor-arg>
					<constructor-arg name="port" value="${redis.post5}" type="int"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="${redis.host6}"></constructor-arg>
					<constructor-arg name="port" value="${redis.post6}" type="int"></constructor-arg>
				</bean>
			</set>
		</constructor-arg>
		<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
	</bean>
	<bean id="jedisClientCluster" class="com.taotao.rest.dao.impl.JedisClientCluster"></bean> -->
</beans>

   redis.properties

#最大连接数
redis.maxTotal=30
#最大空闲连接数
redis.maxIdle=10
#每次释放连接的最大数目
redis.numTestsPerEvictionRun=1024
#释放连接的扫描间隔(毫秒)
redis.timeBetweenEvictionRunsMillis=30000
#连接最小空闲时间 
redis.minEvictableIdleTimeMillis=1800000
#连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放
redis.softMinEvictableIdleTimeMillis=10000
#获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1
redis.maxWaitMillis=1500
#在获取连接的时候检查有效性, 默认false
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true
#连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
redis.blockWhenExhausted=false

#redis://:[密码]@[服务器地址]:[端口]/[db index]
redis.url=redis://:[email protected]:6379/0

redis.host=192.168.168.223
redis.port=6379
redis.timeout=1000
redis.password=foobared
redis.database=0

     jedis接口

package com.test.dao;

public interface JedisClient {

	String get(String key);

	String set(String key, String value);

	String hget(String hkey, String key);

	long hset(String hkey, String key, String value);

	long incr(String key);

	long expire(String key, int second);

	long ttl(String key);

	long del(String key);

	long hdel(String hkey, String key);

}

   单机实现与集群实现。

package com.test.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.test.dao.JedisClient;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@Service
public class JedisClientSingle implements JedisClient {

	@Autowired
	private JedisPool jedisPool;

	@Override
	public String get(String key) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.get(key);
		jedis.close();
		return string;
	}

	@Override
	public String set(String key, String value) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.set(key, value);
		jedis.close();
		return string;
	}

	@Override
	public String hget(String hkey, String key) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.hget(hkey, key);
		jedis.close();
		return string;
	}

	@Override
	public long hset(String hkey, String key, String value) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hset(hkey, key, value);
		jedis.close();
		return result;
	}

	@Override
	public long incr(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.incr(key);
		jedis.close();
		return result;
	}

	@Override
	public long expire(String key, int second) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.expire(key, second);
		jedis.close();
		return result;
	}

	@Override
	public long ttl(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.ttl(key);
		jedis.close();
		return result;
	}

	@Override
	public long del(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.del(key);
		jedis.close();
		return result;
	}

	@Override
	public long hdel(String hkey, String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hdel(hkey, key);
		jedis.close();
		return result;
	}

}
扫描二维码关注公众号,回复: 2649832 查看本文章
package com.test.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;

import com.test.dao.JedisClient;

import redis.clients.jedis.JedisCluster;

public class JedisClientCluster implements JedisClient {

	@Autowired
	private JedisCluster jedisCluster;

	@Override
	public String get(String key) {
		return jedisCluster.get(key);
	}

	@Override
	public String set(String key, String value) {
		return jedisCluster.set(key, value);
	}

	@Override
	public String hget(String hkey, String key) {
		return jedisCluster.hget(hkey, key);
	}

	@Override
	public long hset(String hkey, String key, String value) {
		return jedisCluster.hset(hkey, key, value);
	}

	@Override
	public long incr(String key) {
		return jedisCluster.incr(key);
	}

	@Override
	public long expire(String key, int second) {
		return jedisCluster.expire(key, second);
	}

	@Override
	public long ttl(String key) {
		return jedisCluster.ttl(key);
	}

	@Override
	public long del(String key) {

		return jedisCluster.del(key);
	}

	@Override
	public long hdel(String hkey, String key) {

		return jedisCluster.hdel(hkey, key);
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_42171657/article/details/81455346
今日推荐