From 130ba93754bec3a141be09d5d703f98e68b210bc Mon Sep 17 00:00:00 2001 From: sxu <602087911@qq.com> Date: Sat, 15 Feb 2025 21:47:38 +0800 Subject: [PATCH] bonus_houqin --- .../com/bonus/system/api/domain/SysDept.java | 15 +++ .../com/bonus/system/api/domain/SysUser.java | 1 + .../java/com/bonus/auth/form/LoginBody.java | 2 + bonus-common/bonus-common-core/pom.xml | 10 ++ .../com/bonus/common/core/utils/id/Id.java | 53 ++++++++ .../common/core/utils/id/IdProperties.java | 37 ++++++ .../core/utils/id/IdWorkConfiguration.java | 123 ++++++++++++++++++ .../system/config/CommonConfiguration.java | 10 ++ .../com/bonus/system/domain/SysRoleDept.java | 2 + .../service/impl/SysDeptServiceImpl.java | 2 + .../resources/mapper/system/SysDeptMapper.xml | 2 +- 11 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/Id.java create mode 100644 bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdProperties.java create mode 100644 bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdWorkConfiguration.java create mode 100644 bonus-modules/bonus-system/src/main/java/com/bonus/system/config/CommonConfiguration.java diff --git a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysDept.java b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysDept.java index a9eba92..dcd7165 100644 --- a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysDept.java +++ b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysDept.java @@ -1,6 +1,7 @@ package com.bonus.system.api.domain; import com.bonus.common.core.web.domain.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -19,9 +20,15 @@ import java.util.List; public class SysDept extends BaseEntity { private static final long serialVersionUID = 1L; + /** + * 主键ID + */ + private Long id; + /** * 部门ID */ + @JsonFormat(shape = JsonFormat.Shape.STRING) private Long deptId; /** @@ -274,6 +281,14 @@ public class SysDept extends BaseEntity { this.level = level; } + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Long getDeptId() { return deptId; } diff --git a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java index c33fbd5..8334740 100644 --- a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java +++ b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/domain/SysUser.java @@ -39,6 +39,7 @@ public class SysUser extends BaseEntity { * 部门ID */ @Excel(name = "部门编号", type = Type.IMPORT) + @JsonFormat(shape = JsonFormat.Shape.STRING) private Long deptId; /** diff --git a/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java b/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java index 8a8d8d3..0f9030c 100644 --- a/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java +++ b/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java @@ -2,6 +2,7 @@ package com.bonus.auth.form; import com.bonus.auth.config.LoginType; import com.bonus.auth.config.VerificationCodeType; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; /** @@ -50,5 +51,6 @@ public class LoginBody { /** * i皖送登录数据库中没有用心信息的时候给个默认公司 */ + @JsonFormat(shape = JsonFormat.Shape.STRING) private Long deptId; } diff --git a/bonus-common/bonus-common-core/pom.xml b/bonus-common/bonus-common-core/pom.xml index 26fe105..6e10994 100644 --- a/bonus-common/bonus-common-core/pom.xml +++ b/bonus-common/bonus-common-core/pom.xml @@ -164,6 +164,16 @@ 1.10.19 test + + org.springframework.data + spring-data-redis + + + com.google.guava + guava + 33.0.0-jre + compile + diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/Id.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/Id.java new file mode 100644 index 0000000..ab417ae --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/Id.java @@ -0,0 +1,53 @@ +package com.bonus.common.core.utils.id; + +import com.google.common.base.Preconditions; +import java.time.LocalDateTime; +import java.time.ZoneId; + +public class Id { + private static final long EPOCH = LocalDateTime.of(2021, 12, 29, 9, 2).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + private static final long SEQUENCE_BITS = 12L; + private static final long WORKER_ID_BITS = 10L; + static final long WORKER_ID_MAX_VALUE = 1024L; + private static final long SEQUENCE_MASK = 4095L; + private static final long WORKER_ID_LEFT_SHIFT_BITS = 12L; + private static final long TIMESTAMP_LEFT_SHIFT_BITS = 22L; + static Long WORKER_ID; + private static long SEQUENCE; + private static long LAST_TIME; + + public Id(Long workerId) { + WORKER_ID = workerId; + } + + public static long next() { + return nextKey(); + } + + public static String nextString() { + return String.valueOf(next()); + } + + private static synchronized long nextKey() { + long currentMillis = System.currentTimeMillis(); + Preconditions.checkState(LAST_TIME <= currentMillis, "Clock is moving backwards, last time is %d milliseconds, current time is %d milliseconds", LAST_TIME, currentMillis); + if (LAST_TIME == currentMillis) { + if (0L == (SEQUENCE = SEQUENCE + 1L & 4095L)) { + currentMillis = waitUntilNextTime(currentMillis); + } + } else { + SEQUENCE = 0L; + } + + LAST_TIME = currentMillis; + return currentMillis - EPOCH << 22 | WORKER_ID << 12 | SEQUENCE; + } + + private static long waitUntilNextTime(final long lastTime) { + long time; + for(time = System.currentTimeMillis(); time <= lastTime; time = System.currentTimeMillis()) { + } + + return time; + } +} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdProperties.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdProperties.java new file mode 100644 index 0000000..b1d2476 --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdProperties.java @@ -0,0 +1,37 @@ +package com.bonus.common.core.utils.id; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties( + prefix = "id" +) +public class IdProperties { + public static final String PREFIX = "id"; + private Boolean enabled = true; + private String key = "worker_id_sequence"; + private String workspace; + + public Boolean getEnabled() { + return this.enabled; + } + + public String getKey() { + return this.key; + } + + public String getWorkspace() { + return this.workspace; + } + + public void setEnabled(final Boolean enabled) { + this.enabled = enabled; + } + + public void setKey(final String key) { + this.key = key; + } + + public void setWorkspace(final String workspace) { + this.workspace = workspace; + } +} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdWorkConfiguration.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdWorkConfiguration.java new file mode 100644 index 0000000..aae1b11 --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/id/IdWorkConfiguration.java @@ -0,0 +1,123 @@ +package com.bonus.common.core.utils.id; + +import cn.hutool.core.text.CharSequenceUtil; +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.UUID; + +@Component +@ConditionalOnClass({StringRedisTemplate.class}) +@EnableConfigurationProperties({IdProperties.class}) +@ConditionalOnProperty( + prefix = "id", + name = {"enabled"}, + havingValue = "true", + matchIfMissing = true +) +public class IdWorkConfiguration { + private static final Logger log = LoggerFactory.getLogger(IdWorkConfiguration.class); + private final IdProperties idProperties; + + public IdWorkConfiguration(StringRedisTemplate redisTemplate, IdProperties idProperties) throws IOException { + this.idProperties = idProperties; + Long workerId = this.getLocalWorkId(); + + try { + while(workerId == null) { + Long newWorkId = redisTemplate.opsForValue().increment(idProperties.getKey(), 1L); + this.saveLocalWorkId(String.valueOf(newWorkId)); + workerId = this.getLocalWorkId(); + } + } catch (Throwable var5) { + log.error("获取workID失败", var5); + throw var5; + } + + if (workerId > 1024L) { + throw new RuntimeException("超过最大启动实例"); + } else { + Id.WORKER_ID = workerId; + } + } + + private void saveLocalWorkId(String workId) throws IOException { + File workIdHome = this.getWorkIdHome(); + String var10002 = String.valueOf(workIdHome.getAbsoluteFile()); + FileUtils.writeStringToFile(new File(var10002 + "/" + String.valueOf(UUID.randomUUID()) + ".lock"), workId, StandardCharsets.UTF_8); + } + + private File getWorkIdHome() { + String workHome = this.idProperties.getWorkspace(); + if (CharSequenceUtil.isBlank(workHome)) { + workHome = FileUtils.getUserDirectoryPath() + "/.workId/"; + } + + String var10002 = CharSequenceUtil.removeSuffix(workHome, "/"); + return new File(var10002 + "/" + this.idProperties.getKey()); + } + + private Long getLocalWorkId() throws IOException { + File workIdHome = this.getWorkIdHome(); + if (!workIdHome.exists()) { + return null; + } + + Collection files = FileUtils.listFiles(workIdHome, new String[]{"lock"}, false); + if (CollectionUtils.isEmpty(files)) { + return null; + } + + for (File file : files) { + FileChannel channel = null; + FileLock fileLock = null; + + try { + RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); + channel = randomAccessFile.getChannel(); + fileLock = channel.tryLock(); + + if (fileLock != null) { // 成功获取文件锁 + Long workId = Long.valueOf(randomAccessFile.readLine()); + releaseResourcesOnShutdown(channel); + return workId; + } + } catch (IOException e) { + log.error("Error accessing workId file", e); + } finally { + if (fileLock == null && channel != null) { + try { + channel.close(); + } catch (IOException e) { + log.error("Failed to close file channel", e); + } + } + } + } + return null; + } + + private void releaseResourcesOnShutdown(FileChannel channel) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + channel.close(); + } catch (IOException e) { + log.error("Release WorkId file lock error", e); + } + })); + } +} diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/config/CommonConfiguration.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/config/CommonConfiguration.java new file mode 100644 index 0000000..9c36405 --- /dev/null +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/config/CommonConfiguration.java @@ -0,0 +1,10 @@ +package com.bonus.system.config; + +import com.bonus.common.core.utils.id.IdWorkConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({IdWorkConfiguration.class}) +public class CommonConfiguration { +} diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/domain/SysRoleDept.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/domain/SysRoleDept.java index fae0f2c..6ccad6d 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/domain/SysRoleDept.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/domain/SysRoleDept.java @@ -1,5 +1,6 @@ package com.bonus.system.domain; +import com.fasterxml.jackson.annotation.JsonFormat; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -14,6 +15,7 @@ public class SysRoleDept private Long roleId; /** 部门ID */ + @JsonFormat(shape = JsonFormat.Shape.STRING) private Long deptId; public Long getRoleId() diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysDeptServiceImpl.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysDeptServiceImpl.java index 8d557fc..f3bd96b 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysDeptServiceImpl.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysDeptServiceImpl.java @@ -4,6 +4,7 @@ import java.util.*; import java.util.stream.Collectors; import com.bonus.common.core.utils.DateUtils; +import com.bonus.common.core.utils.id.Id; import com.bonus.common.core.web.domain.BaseEntity; import com.bonus.config.SystemConfig; import com.bonus.system.api.domain.*; @@ -306,6 +307,7 @@ public class SysDeptServiceImpl implements ISysDeptService @Transactional(rollbackFor = Exception.class) public int insertDept(SysDept dept) { + dept.setDeptId(Id.next()); //增加根公司的处理 if (dept.getParentId() == null){ dept.setParentId(0L); diff --git a/bonus-modules/bonus-system/src/main/resources/mapper/system/SysDeptMapper.xml b/bonus-modules/bonus-system/src/main/resources/mapper/system/SysDeptMapper.xml index bf43191..9f4ef5f 100644 --- a/bonus-modules/bonus-system/src/main/resources/mapper/system/SysDeptMapper.xml +++ b/bonus-modules/bonus-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -187,7 +187,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0' limit 1 - + insert into sys_dept( dept_id, parent_id,