SpringBoot集成uid-generator

uid-generator

uid-generator是百度開源的,基於雪花算法的一款唯一主鍵生成器(數據庫表的主鍵要求全局唯一是相當重要的)。要求java8及以上版本。

官方介紹傳送門:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

引入uid-generator

方式一:下載源碼,本地引入

下載鏈接:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

下載後用maven導入,作爲本地子項目引入主項目。

a、導入下載的項目

b、引入

<dependency>
    <groupId>com.baidu.fsg</groupId>
	<artifactId>uid-generator</artifactId>
	<version>1.0.0-SNAPSHOT</version>
</dependency>

方式二:互聯網jar包引入(本文用的是此方式)

在maven倉庫只找到了一個jar包。

<dependency>
    <groupId>com.xfvape.uid</groupId>
    <artifactId>uid-generator</artifactId>
    <version>0.0.4-RELEASE</version>
</dependency>

配置

1、排除衝突的依賴

uid-generator中依賴了logback和mybatis。一般在項目搭建過程中,springboot中已經有了logback依賴,mybatis會作爲單獨的依賴引入。如果版本和uid-generator中的依賴不一致的話,就會導致衝突。爲了防止出現這些問題,直接排除一勞永逸。(我這裏用的是mybatis-plus,mybatis-plus官方要求的是,如果要使用mybatis-plus,就不能再單獨引入mybatis了,所以我這裏也是必須排除mybatis的)。排除jar包衝突問題參考另外一篇博文:https://blog.csdn.net/weixin_41381863/article/details/90042220

mybatis-plus和mybatis衝突的兩個常見錯誤:

a、java.lang.NoClassDefFoundError: org/mybatis/logging/LoggerFactory

b、如下圖

排除衝突的依賴如下:(使用本地項目引入的方式也需要排除以下依賴)

<dependency>
    <groupId>com.xfvape.uid</groupId>
    <artifactId>uid-generator</artifactId>
    <version>0.0.4-RELEASE</version>
    <exclusions>
		    	<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>log4j-over-slf4j</artifactId>
				</exclusion>
				<exclusion>
					<groupId>ch.qos.logback</groupId>
					<artifactId>logback-classic</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-api</artifactId>
				</exclusion>
				 <exclusion>
					<groupId>org.mybatis</groupId>
					<artifactId>mybatis-spring</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.mybatis</groupId>
					<artifactId>mybatis</artifactId>
				</exclusion>
    </exclusions>
</dependency>

2、配置項目。配置步驟全部參考官方介紹:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

a、配置數據庫的連接和mybatis-plus。參考:https://blog.csdn.net/weixin_41381863/article/details/106533572

b、在使用的數據庫中創建表WORKER_NODE。(如果數據庫版本較低,需要將TIMESTAMP類型換成datetime(3),一勞永逸的做法就是直接將TIMESTAMP換成datetime(3))

DROP TABLE IF EXISTS WORKER_NODE;
CREATE TABLE WORKER_NODE
(
ID BIGINT NOT NULL AUTO_INCREMENT COMMENT 'auto increment id',
HOST_NAME VARCHAR(64) NOT NULL COMMENT 'host name',
PORT VARCHAR(64) NOT NULL COMMENT 'port',
TYPE INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER',
LAUNCH_DATE DATE NOT NULL COMMENT 'launch date',
MODIFIED TIMESTAMP NOT NULL COMMENT 'modified time',
CREATED TIMESTAMP NOT NULL COMMENT 'created time',
PRIMARY KEY(ID)
)
 COMMENT='DB WorkerID Assigner for UID Generator',ENGINE = INNODB;

c、將uid-generator核心對象裝配爲spring的bean。

uid-generator提供了兩種生成器: DefaultUidGeneratorCachedUidGenerator。如對UID生成性能有要求, 請使用CachedUidGenerator。這裏裝配CachedUidGeneratorDefaultUidGenerator裝配方式是一樣的。

/**
 * <p> 百度  Uid-Generator配置
 * @author zepal
 * */
@Configuration
public class UidGeneratorConfig {

	@Bean("disposableWorkerIdAssigner")
	public DisposableWorkerIdAssigner initDisposableWorkerIdAssigner() {
		DisposableWorkerIdAssigner disposableWorkerIdAssigner = new DisposableWorkerIdAssigner();
		return disposableWorkerIdAssigner;
	}
	
	@Bean("cachedUidGenerator")
	public CachedUidGenerator initCachedUidGenerator(WorkerIdAssigner workerIdAssigner) {
		CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
		cachedUidGenerator.setWorkerIdAssigner(workerIdAssigner);
		// 屬性參考鏈接  https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md
        // 以下爲可選配置, 如未指定將採用默認值
		// cachedUidGenerator.setTimeBits(28);
		// cachedUidGenerator.setWorkerBits(22);
		// cachedUidGenerator.setSeqBits(13);
		// cachedUidGenerator.setEpochStr("2016-09-20");
		cachedUidGenerator.setBoostPower(3);
		cachedUidGenerator.setPaddingFactor(50);
		cachedUidGenerator.setScheduleInterval(60L);
//		// 拒絕策略: 當環已滿, 無法繼續填充時
		// 默認無需指定, 將丟棄Put操作, 僅日誌記錄. 如有特殊需求, 請實現RejectedPutBufferHandler接口(支持Lambda表達式)
		// 拒絕策略: 當環已空, 無法繼續獲取時
		// 默認無需指定, 將記錄日誌, 並拋出UidGenerateException異常. 如有特殊需求, 請實現RejectedTakeBufferHandler接口(支持Lambda表達式)
		return cachedUidGenerator;
	}
}

 說明:默認的屬性,是百度對雪花算法的組成部分作出的調整(所有位加起來要爲64,標識位始終爲1,即非標識位一共爲63)。

d、配置uid-generator依賴的mybatis配置

mapper文件:(注意:<mapper>中namespace屬性要修改爲引入的uid-generator,WorkerNodeDAO的絕對路徑。<resultMap>的type屬性和<insert>中的parameterType屬性,要修改爲引入的uid-generator,WorkerNodeEntity的絕對路徑。不然mybatis怎麼取映射路徑

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xfvape.uid.worker.dao.WorkerNodeDAO">
	<resultMap id="workerNodeRes"
			   type="com.xfvape.uid.worker.entity.WorkerNodeEntity">
		<id column="ID" jdbcType="BIGINT" property="id" />
		<result column="HOST_NAME" jdbcType="VARCHAR" property="hostName" />
		<result column="PORT" jdbcType="VARCHAR" property="port" />
		<result column="TYPE" jdbcType="INTEGER" property="type" />
		<result column="LAUNCH_DATE" jdbcType="DATE" property="launchDate" />
		<result column="MODIFIED" jdbcType="TIMESTAMP" property="modified" />
		<result column="CREATED" jdbcType="TIMESTAMP" property="created" />
	</resultMap>

	<insert id="addWorkerNode" useGeneratedKeys="true" keyProperty="id"
		parameterType="com.xfvape.uid.worker.entity.WorkerNodeEntity">
		INSERT INTO WORKER_NODE
		(HOST_NAME,
		PORT,
		TYPE,
		LAUNCH_DATE,
		MODIFIED,
		CREATED)
		VALUES (
		#{hostName},
		#{port},
		#{type},
		#{launchDate},
		NOW(),
		NOW())
	</insert>

	<select id="getWorkerNodeByHostPort" resultMap="workerNodeRes">
		SELECT
		ID,
		HOST_NAME,
		PORT,
		TYPE,
		LAUNCH_DATE,
		MODIFIED,
		CREATED
		FROM
		WORKER_NODE
		WHERE
		HOST_NAME = #{host} AND PORT = #{port}
	</select>
</mapper>

@MapperScan的dao層接口掃描:

@MapperScan({"com.zgn.mp.dao", "com.xfvape.uid.worker.dao"})

說明:com.xfvape.uid.worker.dao是引入的uid-generator,WorkerNodeDAO所在的包。(前面的路徑請忽略,是我本地demo的dao層接口路徑)

application.properties配置:

mybatis-plus.mapper-locations=classpath:mapper/*.xml,classpath:mapper/uid/WORKER_NODE.xml

說明:classpath:mapper/uid/WORKER_NODE.xml是創建上述mapper文件所在的路徑。(classpath:mapper/*.xml是我本地demo的mapper文件路徑,忽略或改成自己項目中的路徑)

測試

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class UidGeneratorTest {

	@Autowired
	private UidGenerator uidGenerator;
	
	@Test
	public void testSerialGenerate() {
		
		long uid = uidGenerator.getUID();
		System.out.println("生成的id = " + uid);
		
		// 生成當前唯一id所用的元素
		System.out.println(uidGenerator.parseUID(uid));
	}
}

輸出結果:

擴展

1、如果是通過本地項目引入,參考上述步驟配置進主項目即可(注意各個類的路徑)。

2、如果是分佈式項目,將官方開源的項目下載下來後,參考它的配置修改,放進tomcat運行。也可以重新創建springboot項目,參考上述步驟配置運行即可(注意各個類的路徑)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章