Parcourir la source

feat : 用户token策略提交

bilingfeng il y a 2 ans
Parent
commit
182d5ed028

+ 10 - 3
game-module/game-common-redis/pom.xml

@@ -10,12 +10,14 @@
     <modelVersion>4.0.0</modelVersion>
     <artifactId>game-common-redis</artifactId>
     <description>redis相关</description>
+    <packaging>pom</packaging>
 
     <dependencies>
-        <!-- SpringBoot Boot AOP -->
+        <!-- SpringBoot Boot aspectj -->
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>1.9.6</version>
         </dependency>
         <!-- SpringBoot Boot Redis -->
         <dependency>
@@ -33,6 +35,11 @@
             <artifactId>redisson</artifactId>
             <version>3.13.6</version>
         </dependency>
+        <!-- Apache Commons Pool2 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
         <!-- 工具包 -->
         <dependency>
             <groupId>com.zanxiang.game</groupId>

+ 94 - 0
game-module/game-common-redis/src/main/java/com/zanxiang/common/redis/utils/RedisUtils.java

@@ -0,0 +1,94 @@
+package com.zanxiang.common.redis.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author : lingfeng
+ * @time : 2021-11-23
+ * @description : redis缓存通用前缀
+ */
+@Component
+@Slf4j
+public class RedisUtils<T> {
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 设置缓存
+     *
+     * @param key  : 缓存key
+     * @param t    : 缓存对象
+     * @param time : 过期时间
+     * @return : 返回是否设置成功
+     */
+    public boolean setCache(String key, T t, long time) {
+        try {
+            ValueOperations<String, T> operations = redisTemplate.opsForValue();
+            operations.set(key, t, time, TimeUnit.SECONDS);
+            return true;
+        } catch (Exception e) {
+            log.error("缓存添加异常, key : {}, value : {}, e : {}", key, t, e.getMessage());
+        }
+        return false;
+    }
+
+    /**
+     * 获取缓存方法
+     *
+     * @param key : 缓存key
+     * @return : 返回缓存对象
+     */
+    public T getCache(String key) {
+        try {
+            if (redisTemplate.hasKey(key)) {
+                ValueOperations<String, T> operations = redisTemplate.opsForValue();
+                return operations.get(key);
+            }
+        } catch (Exception e) {
+            log.error("获取缓存异常, key : {}, e : {}", key, e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * redis 事物锁设置方法
+     *
+     * @param key  : 缓存key
+     * @param t    : 缓存对象
+     * @param time : 过期时间
+     * @return : 返回是否设置成功
+     */
+    public boolean setIfAbsent(String key, T t, long time) {
+        try {
+            ValueOperations<String, T> operations = redisTemplate.opsForValue();
+            return operations.setIfAbsent(key, t, time, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            log.error("缓存添加异常, key : {}, value : {}, e : {}", key, t, e.getMessage());
+        }
+        return false;
+    }
+
+    /**
+     * 删除缓存的方法
+     *
+     * @param key : 缓存key
+     * @return : 返回缓存对象
+     */
+    public boolean deleteCache(String key) {
+        try {
+            if (redisTemplate.hasKey(key)) {
+                return redisTemplate.delete(key);
+            }
+        } catch (Exception e) {
+            log.error("删除缓存异常, key : {}, e : {}", key, e.getMessage());
+        }
+        return false;
+    }
+}

+ 206 - 0
game-module/game-common/src/main/java/com/zanxiang/common/constant/Constants.java

@@ -0,0 +1,206 @@
+package com.zanxiang.common.constant;
+
+import java.math.BigDecimal;
+
+/**
+ * 通用常量信息
+ *
+ * @author ruoyi
+ */
+public class Constants {
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * http请求
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https请求
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 登录成功
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 注销
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 注册
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 登录失败
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 当前记录起始索引
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 每页显示记录数
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 排序列
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 排序的方向 "desc" 或者 "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 验证码 redis key
+     */
+    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final long CAPTCHA_EXPIRATION = 5;
+
+    /**
+     * 最大令牌有效期(秒)
+     */
+    public final static long TOKEN_EXPIRE = 24 * 60 * 60;
+
+    /**
+     * 参数管理 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 微信信息存储的前缀(所有 WxJava存储的信息都已这个开头)
+     */
+    public static final String WX_PREFIX = "wx:";
+
+    /**
+     * 微信预授权码前缀(存储用户 id)
+     */
+    public static final String WX_PRE_AUTH_PREFIX = "wx-auth:";
+
+    /**
+     * 微信延时消息列表的前缀:yyyy-MM-dd_HH:mm
+     */
+    public static final String WX_SEND_MSG = "wx-send-msg:";
+
+    /**
+     * 读取微信延时消息列表的锁
+     */
+    public static final String WX_SEND_MSG_LOCK = "wx-send-msg_lock:";
+
+    /**
+     * 刷新 access_token时的锁
+     */
+    public static final String AUTH_ACCESS_TOKEN_LOCK = "auth_access_token_lock:";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    public static final String SINGLE_USER = "single_user_";
+
+    public static final String ROCKET_MQ_ORDER_MSG_KEY_KEFU = "sharding_key_kefu:";
+
+    /**
+     * 异步同步粉丝 Redis锁
+     */
+    public static final String ROCK_ASYNC_MP_FANS = "ROCK_ASYNC_MP_FANS_";
+
+public static final BigDecimal NUM_100 = new BigDecimal(100);
+
+    public static final boolean ENABLE_NO = false;
+    public static final boolean ENABLE_YES = true;
+
+    /**
+     * 异步消费时间的锁
+     */
+    public static final String ASYNC_SAVE_LOG_LAST_TIME = "ASYNC_SAVE_LOG_LAST_TIME";
+
+    /**
+     * 临时缓存 mpFansLog日志
+     */
+    public static final String MP_FANS_LOG_BUFFER = "MP_FANS_LOG_BUFFER";
+    /**
+     * 临时缓存的 mp_kefu_msg_exection_log日志
+     */
+    public static final String KEFU_MSG_EXECUTION_DETAIL_BUFFER = "KEFU_MSG_EXECUTION_DETAIL_BUFFER";
+
+    /**
+     * 客服消息执行日志的统计信息
+     */
+    public static final String KEFU_MSG_EXECUTION_LOG_STAT = "KEFU_MSG_EXECUTION_LOG_STAT";
+
+    public static final String KEFU_STRATEGY_MQ_STAT = "KEFU_STRATEGY_MQ_STAT:";
+
+    public static final String TEMPLATE_STRATEGY_MQ_STAT = "TEMPLATE_STRATEGY_MQ_STAT:";
+
+    public static final String GROUP_STRATEGY_MQ_STAT = "GROUP_STRATEGY_MQ_STAT:";
+
+    /**
+     * 模板消息执行统计
+     */
+    public static final String TEMPLATE_SEND_DETAIL_STAT = "TEMPLATE_SEND_DETAIL_STAT:";
+
+    /**
+     * 模板消息回调执行统计
+     */
+    public static final String TEMPLATE_SEND_CALL_BACK_SUCCESS_STAT = "TEMPLATE_SEND_CALL_BACK_SUCCESS_STAT:";
+
+    /**
+     * 模板消息回调执行统计
+     */
+    public static final String TEMPLATE_SEND_CALL_BACK_FAILED_STAT = "TEMPLATE_SEND_CALL_BACK_FAILED_STAT:";
+
+    /**
+     * 模板消息发送日志,冒号后面加公众号 appid
+     */
+    public static final String TEMPLATE_SEND_LOG = "TEMPLATE_SEND_LOG:";
+
+    public static final String REDIS_CACHE_PREFIX = "SpringCache:";
+
+    /**
+     * 网关账号信息缓存
+     */
+    public static final String REDIS_GATEWAY_ACCOUNT_INFO = "Gateway:AccountInfo";
+
+    /**
+     * 网关服务信息
+     */
+    public static final String REDIS_GATEWAY_SERVER_INFO = "Gateway:ServerInfo:";
+
+    /**
+     * 网关白名单列表
+     */
+    public static final String REDIS_GATEWAY_WHITE_URL = "Gateway:WhiteUrl:";
+
+    /**
+     * 已登录用户列表
+     */
+    public static final String REDIS_LOGIN_USER_LIST = "Gateway:LoginUserList:";
+}

+ 60 - 0
game-module/game-common/src/main/java/com/zanxiang/common/enums/ExpireTimeEnum.java

@@ -0,0 +1,60 @@
+package com.zanxiang.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2021-11-16
+ * @description : 时间常量
+ */
+@Getter
+@AllArgsConstructor
+public enum ExpireTimeEnum {
+
+    /**
+     * 无固定期限
+     */
+    NONE(0, "无固定期限"),
+
+    /**
+     * 1分钟
+     */
+    ONE_MIN(60, "1分钟"),
+
+    /**
+     * 1小时
+     */
+    ONE_HOUR(60 * 60, "1小时"),
+
+    /**
+     * 1天
+     */
+    ONE_DAY(24 * 60 * 60, "1天"),
+
+    /**
+     * 一周
+     */
+    ONE_WEEK(24 * 60 * 60 * 7, "一周"),
+
+    /**
+     * 1个月
+     */
+    ONE_MON(30 * 24 * 60 * 60, "1个月"),
+
+    /**
+     * 1年
+     */
+    ONE_YEAR(365 * 24 * 60 * 60, "1年");
+
+    /**
+     * 时间
+     */
+    private final long time;
+
+    /**
+     * 描述
+     */
+    private final String desc;
+
+}  

+ 5 - 0
game-module/game-sdk/pom.xml

@@ -16,6 +16,11 @@
             <artifactId>game-common</artifactId>
             <version>${game-common.vertion}</version>
         </dependency>
+        <dependency>
+            <groupId>com.zanxiang.game</groupId>
+            <artifactId>game-common-redis</artifactId>
+            <version>${game-common-redis.vertion}</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>

+ 24 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/constant/RedisKeyConstant.java

@@ -0,0 +1,24 @@
+package com.zanxiang.sdk.constant;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-08
+ * @description : 缓存key前缀
+ */
+public class RedisKeyConstant {
+
+    /**
+     * 同步服务缓存统一前缀
+     */
+    private static final String REDIS_PREFIX = "game_sdk_";
+
+    /**
+     * 用户token缓存key
+     */
+    public static final String USER_TOKEN_KEY = RedisKeyConstant.REDIS_PREFIX + "user_token";
+
+    /**
+     * token缓存key
+     */
+    public static final String TOKEN_INFO_KEY = RedisKeyConstant.REDIS_PREFIX + "token_info";
+}

+ 46 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/dto/UserTokenDTO.java

@@ -0,0 +1,46 @@
+package com.zanxiang.sdk.domain.dto;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-08
+ * @description : 用户token信息
+ */
+public class UserTokenDTO {
+
+    /**
+     * 主键id
+     */
+    private Long id;
+
+    /**
+     * 玩家id
+     */
+    private Long userId;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * token
+     */
+    private String token;
+
+    /**
+     * 设备类型;mobile,android,iphone,ipad,web,pc,mac,wxapp
+     */
+    private String deviceType;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+}

+ 33 - 1
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/entity/UserToken.java

@@ -3,11 +3,14 @@ package com.zanxiang.sdk.domain.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.zanxiang.common.enums.ExpireTimeEnum;
+import com.zanxiang.common.utils.DateUtils;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.ToString;
 
+import java.io.Serializable;
 import java.time.LocalDateTime;
 
 /**
@@ -20,7 +23,9 @@ import java.time.LocalDateTime;
 @AllArgsConstructor
 @ToString
 @TableName("h_user_token")
-public class UserToken {
+public class UserToken implements Serializable {
+
+    private static final long serialVersionUID = -6515396685604515968L;
 
     /**
      * id
@@ -57,4 +62,31 @@ public class UserToken {
      * 更新时间
      */
     private LocalDateTime updateTime;
+
+    /**
+     * 构造方法
+     *
+     * @param userId     : 用户id
+     * @param token      : token签名
+     * @param deviceType : 设备类型
+     */
+    public UserToken(Long userId, String token, String deviceType) {
+        this.userId = userId;
+        this.token = token;
+        this.deviceType = deviceType;
+        this.createTime = LocalDateTime.now();
+        this.updateTime = this.createTime;
+        this.expireTime = DateUtils.localDateTimeToSecond(this.createTime) + ExpireTimeEnum.ONE_WEEK.getTime();
+    }
+
+    /**
+     * 更新用户token
+     *
+     * @param token : 新的token
+     */
+    public void updateToken(String token) {
+        this.token = token;
+        this.updateTime = LocalDateTime.now();
+        this.expireTime = DateUtils.localDateTimeToSecond(this.updateTime) + ExpireTimeEnum.ONE_WEEK.getTime();
+    }
 }

+ 10 - 6
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/CommonParam.java

@@ -8,27 +8,31 @@ import lombok.Data;
 public class CommonParam {
     //==============必须携带相关参数===========
     @ApiModelProperty("token")
-    String token;
+    private String token;
 
     @ApiModelProperty("游戏id")
-    String game_id;
+    private String gameId;
 
     //==============device 相关===============
     @ApiModelProperty("设备id")
     @JsonAlias("device-device_id")
-    String device_id;
+    private String deviceId;
 
     @ApiModelProperty("mac设备")
     @JsonAlias("device-mac")
-    String device_mac;
+    private String deviceMac;
 
     @ApiModelProperty("设备品牌")
     @JsonAlias("device-brand")
-    String device_brand;
+    private String deviceBrand;
 
     @ApiModelProperty("设备型号代码")
     @JsonAlias("device-model")
-    String device_model;
+    private String deviceModel;
+
+    @ApiModelProperty("设备类型")
+    @JsonAlias("device-type")
+    private String deviceType;
 
 //            "device-os":"",
 //            "device-os_version":"",

+ 12 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserService.java

@@ -0,0 +1,12 @@
+package com.zanxiang.sdk.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.sdk.domain.entity.User;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-08
+ * @description : 用户信息
+ */
+public interface IUserService extends IService<User> {
+}

+ 38 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserTokenService.java

@@ -0,0 +1,38 @@
+package com.zanxiang.sdk.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.sdk.domain.dto.UserTokenDTO;
+import com.zanxiang.sdk.domain.entity.UserToken;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-08
+ * @description : 用户token管理
+ */
+public interface IUserTokenService extends IService<UserToken> {
+
+    /**
+     * 通过用户设备获取token详情
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    UserTokenDTO getTokenInfoByUserDevice(Long userId, String deviceType);
+
+    /**
+     * 获取用户token
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    String getUserToken(Long userId, String deviceType);
+
+    /**
+     * 删除用户token
+     *
+     * @param userId : 用户id
+     */
+    void deleteUserToken(Long userId);
+}

+ 0 - 14
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/TokenServiceImpl.java

@@ -1,14 +0,0 @@
-package com.zanxiang.sdk.service.Impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-/**
- * @author : lingfeng
- * @time : 2022-06-07
- * @description : 用户token管理
- */
-@Slf4j
-@Service
-public class TokenServiceImpl {
-}

+ 5 - 1
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserServiceImpl.java

@@ -1,7 +1,11 @@
 package com.zanxiang.sdk.service.Impl;
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.sdk.domain.entity.User;
 import com.zanxiang.sdk.domain.params.LoginPasswordParam;
 import com.zanxiang.sdk.domain.vo.UserLoginVO;
+import com.zanxiang.sdk.mapper.UserMapper;
+import com.zanxiang.sdk.service.IUserService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
@@ -12,7 +16,7 @@ import org.springframework.stereotype.Service;
  */
 @Slf4j
 @Service
-public class UserServiceImpl {
+public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
 
     /**
      * 用户名密码登录

+ 158 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserTokenServiceImpl.java

@@ -0,0 +1,158 @@
+package com.zanxiang.sdk.service.Impl;
+
+import com.alibaba.nacos.common.utils.CollectionUtils;
+import com.alibaba.nacos.common.utils.MD5Utils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.common.enums.ExpireTimeEnum;
+import com.zanxiang.common.exception.BaseException;
+import com.zanxiang.common.redis.utils.RedisUtils;
+import com.zanxiang.common.text.UUID;
+import com.zanxiang.common.utils.bean.BeanUtils;
+import com.zanxiang.sdk.constant.RedisKeyConstant;
+import com.zanxiang.sdk.domain.dto.UserTokenDTO;
+import com.zanxiang.sdk.domain.entity.UserToken;
+import com.zanxiang.sdk.mapper.UserTokenMapper;
+import com.zanxiang.sdk.service.IUserTokenService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-07
+ * @description : 用户token管理
+ */
+@Slf4j
+@Service
+public class UserTokenServiceImpl extends ServiceImpl<UserTokenMapper, UserToken> implements IUserTokenService {
+
+    @Autowired
+    private RedisUtils<UserToken> redisUtils;
+
+    /**
+     * 通过用户设备获取token详情
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    @Override
+    public UserTokenDTO getTokenInfoByUserDevice(Long userId, String deviceType) {
+        //查询缓存信息
+        String key = this.getUserTokenKey(userId, deviceType);
+        UserToken userToken = redisUtils.getCache(key);
+        if (userToken != null) {
+            return BeanUtils.copy(userToken, UserTokenDTO.class);
+        }
+        //缓存不存在, 查询数据库
+        userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getUserId, userId)
+                .eq(UserToken::getDeviceType, deviceType));
+        if (userToken == null) {
+            return null;
+        }
+        return BeanUtils.copy(userToken, UserTokenDTO.class);
+    }
+
+    /**
+     * 获取用户token
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    @Override
+    public String getUserToken(Long userId, String deviceType) {
+        //获取token
+        String token = this.createToken(userId, deviceType);
+        //查询数据库token信息
+        UserToken userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getUserId, userId)
+                .eq(UserToken::getDeviceType, deviceType));
+        //不存在token数据, 直接创建
+        if (userToken == null) {
+            userToken = new UserToken(userId, token, deviceType);
+            super.save(userToken);
+        } else {
+            //梗系数据库
+            userToken.updateToken(token);
+            super.updateById(userToken);
+        }
+        //设置用户缓存
+        String userTokenKey = this.getUserTokenKey(userId, deviceType);
+        redisUtils.setCache(userTokenKey, userToken, ExpireTimeEnum.ONE_WEEK.getTime());
+        //设置token详情缓存
+        String tokenInfoKey = this.getTokenInfoKey(token, deviceType);
+        redisUtils.setCache(tokenInfoKey, userToken, ExpireTimeEnum.ONE_WEEK.getTime());
+        //返回token
+        return token;
+    }
+
+    /**
+     * 删除用户token
+     *
+     * @param userId : 用户id
+     */
+    @Override
+    public void deleteUserToken(Long userId) {
+        List<UserToken> userTokenList = super.list(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getUserId, userId));
+        if (CollectionUtils.isEmpty(userTokenList)) {
+            return;
+        }
+        userTokenList.forEach(userToken -> {
+            //根据主键删除数据库
+            super.removeById(userToken.getId());
+            //删除缓存
+            String userTokenKey = this.getUserTokenKey(userId, userToken.getDeviceType());
+            redisUtils.deleteCache(userTokenKey);
+            String tokenInfoKey = this.getTokenInfoKey(userToken.getToken(), userToken.getDeviceType());
+            redisUtils.deleteCache(tokenInfoKey);
+        });
+    }
+
+    /**
+     * 创建token
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    private String createToken(Long userId, String deviceType) {
+        //生成随机数
+        String random = userId + deviceType + UUID.randomUUID().toString() + System.currentTimeMillis();
+        //创建token
+        try {
+            return MD5Utils.md5Hex(MD5Utils.md5Hex(random.getBytes()).getBytes());
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            throw new BaseException("生成token异常");
+        }
+    }
+
+    /**
+     * 拼接用户token缓存key
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回用户token的缓存key
+     */
+    private String getUserTokenKey(Long userId, String deviceType) {
+        return RedisKeyConstant.USER_TOKEN_KEY + "_" + userId + "_" + deviceType;
+    }
+
+    /**
+     * 拼接用户token缓存key
+     *
+     * @param token      : 用户token
+     * @param deviceType : 设备类型
+     * @return : 返回用户token的缓存key
+     */
+    private String getTokenInfoKey(String token, String deviceType) {
+        return RedisKeyConstant.TOKEN_INFO_KEY + "_" + token + "_" + deviceType;
+    }
+}

+ 1 - 0
pom.xml

@@ -23,6 +23,7 @@
         <swagger2.ui.version>2.9.2</swagger2.ui.version>
         <mybatis-plus.version>3.4.0</mybatis-plus.version>
         <game-common.vertion>0.0.1-SNAPSHOT</game-common.vertion>
+        <game-common-redis.vertion>0.0.1-SNAPSHOT</game-common-redis.vertion>
     </properties>
 
 </project>