Browse Source

租户管理和日志管理修改
增加工具类Snowflake

wangli 4 năm trước cách đây
mục cha
commit
f5ec9a7cc4

+ 196 - 0
common/src/main/java/com/huaxu/util/Snowflake.java

@@ -0,0 +1,196 @@
+package com.huaxu.util;
+
+import org.apache.commons.lang3.RandomUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.SystemUtils;
+
+import java.net.Inet4Address;
+import java.net.UnknownHostException;
+
+/**
+ * Twitter_Snowflake
+ * SnowFlake的结构如下(每部分用-分开):
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
+ * 加起来刚好64位,为一个Long型。
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ */
+
+public class Snowflake {
+
+    // ==============================Fields===========================================
+    /** 开始时间截 (2015-01-01) */
+    private final long twepoch = 1489111610226L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 5L;
+
+    /** 数据标识id所占的位数 */
+    private final long dataCenterIdBits = 5L;
+
+    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 支持的最大数据标识id,结果是31 */
+    private final long maxDataCenterId = -1L ^ (-1L << dataCenterIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 数据标识id向左移17位(12+5) */
+    private final long dataCenterIdShift = sequenceBits + workerIdBits;
+
+    /** 时间截向左移22位(5+5+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~31) */
+    private long workerId;
+
+    /** 数据中心ID(0~31) */
+    private long dataCenterId;
+
+    /** 毫秒内序列(0~4095) */
+    private long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private long lastTimestamp = -1L;
+
+    private static Snowflake idWorker;
+
+    static {
+        idWorker = new Snowflake(getWorkId(),getDataCenterId());
+    }
+
+    //==============================Constructors=====================================
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~31)
+     * @param dataCenterId 数据中心ID (0~31)
+     */
+    public Snowflake(long workerId, long dataCenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (dataCenterId > maxDataCenterId || dataCenterId < 0) {
+            throw new IllegalArgumentException(String.format("dataCenterId can't be greater than %d or less than 0", maxDataCenterId));
+        }
+        this.workerId = workerId;
+        this.dataCenterId = dataCenterId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift)
+                | (dataCenterId << dataCenterIdShift)
+                | (workerId << workerIdShift)
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    private static Long getWorkId(){
+        try {
+            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
+            int[] ints = StringUtils.toCodePoints(hostAddress);
+            int sums = 0;
+            for(int b : ints){
+                sums += b;
+            }
+            return (long)(sums % 32);
+        } catch (UnknownHostException e) {
+            // 如果获取失败,则使用随机数备用
+            return RandomUtils.nextLong(0,31);
+        }
+    }
+
+    private static Long getDataCenterId(){
+        int[] ints = StringUtils.toCodePoints(SystemUtils.getHostName());
+        int sums = 0;
+        for (int i: ints) {
+            sums += i;
+        }
+        return (long)(sums % 32);
+    }
+
+
+    /**
+     * 静态工具类
+     *
+     * @return
+     */
+    public static Long generateId(){
+        long id = idWorker.nextId();
+        return id;
+    }
+
+    //==============================Test=============================================
+    /** 测试 */
+    public static void main(String[] args) {
+        System.out.println(System.currentTimeMillis());
+        long startTime = System.nanoTime();
+        for (int i = 0; i < 50000; i++) {
+            long id = Snowflake.generateId();
+            System.out.println(id);
+        }
+        System.out.println((System.nanoTime()-startTime)/1000000+"ms");
+    }
+}

+ 1 - 1
user_auth/src/main/java/com/huaxu/service/impl/UserServiceImpl.java

@@ -210,7 +210,7 @@ public class UserServiceImpl implements UserService {
         loginUser.setPhoneNumber(user.getPhone());
         loginUser.setAuthorities(grantedAuthorities);
         loginUser.setPermissonType(permission.getPermissionType());
-        loginUser.setRoleId(permission.getRoleId());
+//        loginUser.setRoleId(permission.getRoleId());
         MobileLoginAuthenticationToken authenticationTokenReslut = new MobileLoginAuthenticationToken(loginUser,oAuth2Authentication.getCredentials(),loginUser.getAuthorities());
         authenticationTokenReslut.setDetails(oAuth2Authentication.getDetails());
         OAuth2Authentication oAuth2AuthenticationNew = new OAuth2Authentication(oAuth2Authentication.getOAuth2Request(), authenticationTokenReslut);

+ 1 - 1
user_center/src/main/java/com/huaxu/controller/TenantController.java

@@ -149,7 +149,7 @@ public class TenantController {
     @RequestMapping(value = "selectPage", method = RequestMethod.POST)
     @ApiOperation(value = "查询租户信息列表")
     public AjaxMessage<Pagination<TenantDto>> selectPage(
-            @ApiParam(value = "租户名称")  TenantDto tenantDto,
+            @ApiParam(value = "租户名称")  @RequestBody TenantDto tenantDto,
             @ApiParam(value = "页数,非必传,默认第一页",  defaultValue = "1") @RequestParam(required = false, defaultValue = "1") Integer pageNum,
             @ApiParam(value = "条数,非必传,默认30条",  defaultValue = "30") @RequestParam(required = false, defaultValue = "30") Integer pageSize
 

+ 4 - 4
user_center/src/main/java/com/huaxu/dto/LoginLogDto.java

@@ -30,12 +30,12 @@ public class LoginLogDto extends LoginLogEntity {
     private String condition;
 
     @ExcelIgnore
-    @ApiModelProperty(value = "查询条件(起始时间)" )
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "查询条件(起始时间)yyyy-MM-dd" )
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date beginTime;
 
     @ExcelIgnore
-    @ApiModelProperty(value = "查询条件(终止时间)")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "查询条件(终止时间)yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date endTime;
 }

+ 4 - 4
user_center/src/main/java/com/huaxu/dto/OperateLogDto.java

@@ -28,11 +28,11 @@ public class OperateLogDto extends OperateLogEntity {
     @ApiModelProperty(value = "查询条件(用户名/手机号)")
     private String condition;
     @ExcelIgnore
-    @ApiModelProperty(value = "查询条件(起始时间)" )
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "查询条件(起始时间)yyyy-MM-dd" )
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date beginTime;
     @ExcelIgnore
-    @ApiModelProperty(value = "查询条件(终止时间)" )
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty(value = "查询条件(终止时间)yyyy-MM-dd" )
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private Date endTime;
 }

+ 3 - 1
user_center/src/main/java/com/huaxu/entity/TenantEntity.java

@@ -26,8 +26,10 @@ public class TenantEntity implements Serializable {
     private Integer id;
     @ApiModelProperty(value = "租户名称")
     private String tenantName;
-    @ApiModelProperty(value = "租户标识")
+    @ApiModelProperty(value = "租户标识:系统后台自动生成")
     private String code;
+    @ApiModelProperty(value = "租户类型")
+    private String tenantType;
     @ApiModelProperty(value = "租户Logo")
     private String logo;
     @ApiModelProperty(value = "租户域名")

+ 8 - 10
user_center/src/main/java/com/huaxu/service/impl/TenantServiceImpl.java

@@ -2,19 +2,14 @@ package com.huaxu.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.huaxu.dao.TenantMapper;
-import com.huaxu.dao.UserMapper;
 import com.huaxu.dto.TenantDto;
-import com.huaxu.entity.TenantEntity;
 import com.huaxu.entity.UserEntity;
-import com.huaxu.model.LoginUser;
 import com.huaxu.service.TenantService;
 import com.huaxu.service.UserService;
-import com.huaxu.util.UserUtil;
-import io.swagger.annotations.ApiModelProperty;
+import com.huaxu.util.Snowflake;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -85,11 +80,12 @@ public class TenantServiceImpl implements TenantService {
 //        tenantDto.setDateCreate(new Date());
 //        tenantDto.setUpdateBy(loginUser.getUsername());
 //        tenantDto.setDateUpdate(new Date());
+        tenantDto.setCode(Snowflake.generateId().toString());
         tenantDto.setStatus(0);
         tenantMapper.insert(tenantDto);
         //创建管理员信息
         UserEntity userEntity =new UserEntity();
-        userEntity.setTenantId(tenantDto.getCode());//此字段到底取标识还是id
+        userEntity.setTenantId(tenantDto.getCode());
         userEntity.setCreateBy(tenantDto.getCreateBy());
         userEntity.setDateCreate(new Date());
         userEntity.setUpdateBy(tenantDto.getUpdateBy());
@@ -121,15 +117,17 @@ public class TenantServiceImpl implements TenantService {
         //修改租户信息
 //        tenantDto.setUpdateBy(loginUser.getUsername());
 //        tenantDto.setDateUpdate(new Date());
+
         tenantMapper.update(tenantDto);
         //修改管理员信息
         UserEntity userEntity =new UserEntity();
         userEntity.setId(tenantDto.getUserId());
-        userEntity.setTenantId(tenantDto.getCode());//此字段到底取标识还是id
+        userEntity.setTenantId(tenantDto.getCode());
         userEntity.setUpdateBy(tenantDto.getUpdateBy());
         userEntity.setDateUpdate(new Date());
         userEntity.setPhone(tenantDto.getPhone());
         userEntity.setUsername(tenantDto.getUserName());
+        userEntity.setUserType("系统管理员");
         userService.updateUserById(userEntity);
         //修改租户菜单信息
         //界面传回的租户菜单id
@@ -138,13 +136,13 @@ public class TenantServiceImpl implements TenantService {
         List<Integer > oldTenantMenuIds = tenantMapper.selectTenantMenuIds(tenantDto.getId());
         //相同的暂时不改动
 
-        //新增的id(需要新增的)
+        //新增的菜单id(需要新增的)
         List<Integer> addTenantMenuIds = newTenantMenuIds.stream().filter(item -> !oldTenantMenuIds.contains(item)).collect(Collectors.toList());
         //创建租户菜单信息
         if(addTenantMenuIds.size()>0){
             tenantMapper.createTenantMenu(tenantDto.getUpdateBy(),tenantDto.getId(),addTenantMenuIds);
         }
-        //去掉的id(需要删除的)
+        //去掉的菜单id(需要删除的)
         List<Integer> deleteTenantMenuIds = oldTenantMenuIds.stream().filter(item -> !newTenantMenuIds.contains(item)).collect(Collectors.toList());
         if(deleteTenantMenuIds.size()>0){
             tenantMapper.deleteTenantMenuIds(tenantDto.getId(),deleteTenantMenuIds);

+ 7 - 20
user_center/src/main/resources/mapper/TenantMapper.xml

@@ -2,36 +2,20 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.huaxu.dao.TenantMapper">
 
-    <resultMap id="TenantMap" type="com.huaxu.entity.TenantEntity" >
-        <result property="id" column="ID" jdbcType="INTEGER"/>
-        <result property="tenantName" column="TENANT_NAME" jdbcType="VARCHAR"/>
-        <result property="code" column="CODE" jdbcType="VARCHAR"/>
-        <result property="logo" column="LOGO" jdbcType="VARCHAR"/>
-        <result property="webUrl" column="WEB_URL" jdbcType="VARCHAR"/>
-        <result property="startDate" column="START_DATE" jdbcType="TIMESTAMP"/>
-        <result property="endDate" column="END_DATE" jdbcType="TIMESTAMP"/>
-        <result property="tenantState" column="TENANT_STATE" jdbcType="INTEGER"/>
-        <result property="remark" column="REMARK" jdbcType="VARCHAR"/>
-        <result property="status" column="STATUS" jdbcType="INTEGER"/>
-        <result property="dateCreate" column="DATE_CREATE" jdbcType="TIMESTAMP"/>
-        <result property="createBy" column="CREATE_BY" jdbcType="VARCHAR"/>
-        <result property="dateUpdate" column="DATE_UPDATE" jdbcType="TIMESTAMP"/>
-        <result property="updateBy" column="UPDATE_BY" jdbcType="VARCHAR"/>
-    </resultMap>
-
     <sql id="Base_Column_List">
         t.TENANT_NAME as "tenantName"
         ,u.id as "userId"
         ,u.USERNAME as "userName"
         ,u.PHONE as "phone"
         ,t.`CODE` as "code"
+        ,t.`tenant_type` as "tenantType"
         ,t.LOGO as "logo"
         ,t.WEB_URL as "webUrl"
         ,t.DATE_CREATE as "dateCreate"
     </sql>
 
     <sql id="tenantJoins">
-        left join uims_user u on t.ID=u.TENANT_ID and u.USER_TYPE=2
+        left join uims_user u on t.ID=u.TENANT_ID and u.USER_TYPE='系统管理员'
     </sql>
     <select id="selectById" resultType="com.huaxu.dto.TenantDto">
         select
@@ -64,8 +48,8 @@
 
     <!-- 新增所有列 -->
     <insert id="insert" keyProperty="id" useGeneratedKeys="true">
-        insert into uims_tenant(ID ,TENANT_NAME ,CODE ,LOGO ,WEB_URL ,START_DATE ,END_DATE ,TENANT_STATE ,REMARK ,STATUS ,DATE_CREATE ,CREATE_BY ,DATE_UPDATE ,UPDATE_BY)
-        values ( #{id}, #{tenantName}, #{code}, #{logo}, #{webUrl}, #{startDate}, #{endDate}, #{tenantState}, #{remark}, #{status},#{dateCreate},#{createBy},#{dateUpdate},#{updateBy})
+        insert into uims_tenant(TENANT_NAME,tenant_type ,CODE ,LOGO ,WEB_URL ,START_DATE ,END_DATE ,TENANT_STATE ,REMARK ,STATUS ,DATE_CREATE ,CREATE_BY ,DATE_UPDATE ,UPDATE_BY)
+        values ( #{tenantName},#{tenantType}, #{code}, #{logo}, #{webUrl}, #{startDate}, #{endDate}, #{tenantState}, #{remark}, #{status},#{dateCreate},#{createBy},#{dateUpdate},#{updateBy})
     </insert>
 
     <!-- 批量新增 -->
@@ -86,6 +70,9 @@
             <if test="tenantName != null and tenantName != ''">
                 TENANT_NAME = #{tenantName},
             </if>
+            <if test="tenantType != null and tenantType != ''">
+                tenant_type = #{tenantType},
+            </if>
             <if test="code != null and code != ''">
                 CODE = #{code},
             </if>