1.优化登录挤下线的逻辑

This commit is contained in:
乾乾
2025-05-13 16:33:12 +08:00
parent 7ad2c12b2c
commit 31b17c00ad
5 changed files with 60 additions and 11 deletions

View File

@@ -1,13 +1,13 @@
package com.hula.utils;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -274,6 +274,50 @@ public class RedisUtils {
return list.stream().map(o -> toBeanOrNull(o, tClass)).collect(Collectors.toList());
}
/**
* 查询key下面的所有key值
* @param keyPattern
* @return
*/
public static List<String> multiGet(String keyPattern) {
Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
Set<String> result = new HashSet<>();
Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(keyPattern).count(100).build());
while (cursor.hasNext()) {
result.add(new String(cursor.next()));
}
return result;
});
return stringRedisTemplate.opsForValue().multiGet(keys);
}
/**
* 匹配所有key并删除
* @param keyPattern
*/
public static void multiDelete(String keyPattern) {
// 1. 使用SCAN获取所有匹配的键
Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
Set<String> result = new HashSet<>();
Cursor<byte[]> cursor = connection.scan(
ScanOptions.scanOptions()
.match(keyPattern)
.count(100)
.build()
);
while (cursor.hasNext()) {
result.add(new String(cursor.next()));
}
return result;
});
// 2. 批量删除所有键
if (keys != null && !keys.isEmpty()) {
stringRedisTemplate.delete(keys);
}
}
static <T> T toBeanOrNull(String json, Class<T> tClass) {
return json == null ? null : JsonUtils.toObj(json, tClass);
}
@@ -285,9 +329,7 @@ public class RedisUtils {
public static <T> void multiSet(Map<String, T> map, long time) {
Map<String, String> collect = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, (e) -> objToStr(e.getValue())));
stringRedisTemplate.opsForValue().multiSet(collect);
map.forEach((key, value) -> {
expire(key, time);
});
map.forEach((key, value) -> expire(key, time));
}

View File

@@ -108,6 +108,7 @@ public class ChatServiceImpl extends ServiceImpl<ChatMapper, Chat> implements IC
chat.setUid(command.getUid());
chat.setCreatedBy(command.getUid());
chat.setCreatedTime(LocalDateTime.now());
chat.setId(null);
chatMapper.insert(chat);
return ChatVO.builder().chatNumber(chat.getChatNumber()).prompt(command.getPrompt()).build();
}

View File

@@ -71,6 +71,11 @@ public class RedisKey {
*/
public static final String GROUP_ANNOUNCEMENTS_FORMAT = "groupInfo:announcements_%d";
/**
* 用户token存放 格式:终端:uid
*/
public static final String USER_TOKEN_UID_FORMAT = "userToken:%s:uid_%d";
/**
* 用户token存放 格式:终端:uid:uuid
*/

View File

@@ -24,5 +24,5 @@ public class UploadUrlReq extends BaseEntity {
private String fileName;
@ApiModelProperty(value = "上传场景chat.聊天室,emoji.表情包,avatar.头像")
@NotNull
private Integer scene;
private String scene;
}

View File

@@ -1,5 +1,6 @@
package com.hula.core.user.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.interfaces.Claim;
@@ -55,17 +56,17 @@ public class TokenServiceImpl implements TokenService {
String uuid = UUID.randomUUID().toString(true);
String tokenKey = RedisKey.getKey(RedisKey.USER_TOKEN_FORMAT, loginType, uid, uuid);
String refreshTokenKey = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_FORMAT, loginType, uid, uuid);
String token = RedisUtils.getStr(tokenKey), refreshToken;
String key = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_UID_FORMAT, loginType, uid);
RedisUtils.del(tokenKey, key);
String key = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_UID_FORMAT, loginType, uid) + "*";
RedisUtils.multiDelete(RedisKey.getKey(RedisKey.USER_TOKEN_UID_FORMAT, loginType, uid) + "*");
// 1.2 token存在 旧设备下线
if (StrUtil.isNotBlank(token)) {
if (CollUtil.isNotEmpty(RedisUtils.multiGet(key))) {
RedisUtils.multiDelete(key);
applicationEventPublisher.publishEvent(new TokenExpireEvent(this, new OffLineResp(uid, loginType, RequestHolder.get().getIp(), uuid)));
}
// 2. 创建用户token
token = JwtUtils.createToken(uid, loginType, uuid, TOKEN_EXPIRE_DAYS);
String token = JwtUtils.createToken(uid, loginType, uuid, TOKEN_EXPIRE_DAYS), refreshToken;
refreshToken = JwtUtils.createToken(uid, loginType, uuid, TOKEN_RENEWAL_DAYS);
// 3. 刷新存放时间