diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java index 25a551c..a6cd1e0 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -63,13 +63,13 @@ public class MessageMark implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java index 94dfcfc..32c04c1 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java @@ -7,6 +7,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.List; import java.util.Map; /** @@ -25,4 +26,6 @@ public class MessageExtra implements Serializable { private Map urlTitleMap; //消息撤回详情 private MsgRecall recall; + //艾特的uid + private List atUidList; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/RedisConfig.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/RedisConfig.java index 85518d5..ae52ae6 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/RedisConfig.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/RedisConfig.java @@ -15,7 +15,8 @@ import java.util.Objects; @Configuration public class RedisConfig { - @Bean + + @Bean("myRedisTemplate") public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { // 创建模板 RedisTemplate redisTemplate = new RedisTemplate<>(); @@ -30,10 +31,11 @@ public class RedisConfig { // value和 hashValue采用 JSON序列化 redisTemplate.setValueSerializer(jsonRedisSerializer); redisTemplate.setHashValueSerializer(jsonRedisSerializer); + redisTemplate.afterPropertiesSet(); return redisTemplate; } - public class MyRedisSerializerCustomized extends GenericJackson2JsonRedisSerializer { + private static class MyRedisSerializerCustomized extends GenericJackson2JsonRedisSerializer { @Override public byte[] serialize(Object source) throws SerializationException { if (Objects.nonNull(source)) { diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java index c0c5efc..faa6bd2 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java @@ -26,6 +26,16 @@ public class RedisKey { */ public static final String USER_TOKEN_STRING = "userToken:uid_%d"; + /** + * 用户的信息更新时间 + */ + public static final String USER_MODIFY_STRING = "userModify:uid_%d"; + + /** + * 用户的信息汇总 + */ + public static final String USER_SUMMARY_STRING = "userSummary:uid_%d"; + public static String getKey(String key, Object... objects) { return BASE_KEY + String.format(key, objects); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageMarkEvent.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageMarkEvent.java index 5cd7906..6107641 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageMarkEvent.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageMarkEvent.java @@ -6,10 +6,12 @@ import org.springframework.context.ApplicationEvent; @Getter public class MessageMarkEvent extends ApplicationEvent { - private ChatMessageMarkDTO dto; + + private final ChatMessageMarkDTO dto; public MessageMarkEvent(Object source, ChatMessageMarkDTO dto) { super(source); this.dto = dto; } + } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageRecallEvent.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageRecallEvent.java index c32f397..24d27fd 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageRecallEvent.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/MessageRecallEvent.java @@ -6,10 +6,12 @@ import org.springframework.context.ApplicationEvent; @Getter public class MessageRecallEvent extends ApplicationEvent { - private ChatMsgRecallDTO recallDTO; + + private final ChatMsgRecallDTO recallDTO; public MessageRecallEvent(Object source, ChatMsgRecallDTO recallDTO) { super(source); this.recallDTO = recallDTO; } + } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/exception/GlobalExceptionHandler.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/exception/GlobalExceptionHandler.java index 66e0b70..fad1667 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/exception/GlobalExceptionHandler.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/exception/GlobalExceptionHandler.java @@ -3,6 +3,7 @@ package com.abin.mallchat.common.common.exception; import com.abin.mallchat.common.common.domain.vo.response.ApiResult; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -62,4 +63,14 @@ public class GlobalExceptionHandler { log.info("business exception!The reason is:{}", e.getMessage(), e); return ApiResult.fail(e.getErrorCode(), e.getMessage()); } -} \ No newline at end of file + + /** + * http请求方式不支持 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ApiResult handleException(HttpRequestMethodNotSupportedException e) { + log.error(e.getMessage(), e); + return ApiResult.fail(-1, String.format("不支持'%s'请求", e.getMethod())); + } + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java new file mode 100644 index 0000000..16b0f16 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java @@ -0,0 +1,66 @@ +package com.abin.mallchat.common.common.service.cache; + +import cn.hutool.core.collection.CollectionUtil; +import com.abin.mallchat.common.common.utils.RedisUtils; +import org.springframework.data.util.Pair; + +import java.lang.reflect.ParameterizedType; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Description: redis string类型的批量缓存框架 + * Author: abin + * Date: 2023-06-10 + */ +public abstract class AbstractRedisStringCache implements BatchCache { + + private Class outClass; + + protected AbstractRedisStringCache() { + ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass(); + this.outClass = (Class) genericSuperclass.getActualTypeArguments()[1]; + } + + protected abstract String getKey(IN req); + + protected abstract Long getExpireSeconds(); + + protected abstract Map load(List req); + + @Override + public OUT get(IN req) { + return getBatch(Collections.singletonList(req)).get(req); + } + + @Override + public Map getBatch(List req) { + List keys = req.stream().map(this::getKey).collect(Collectors.toList()); + List valueList = RedisUtils.mget(keys, outClass); + List loadReqs = new ArrayList<>(); + for (int i = 0; i < valueList.size(); i++) { + if (Objects.isNull(valueList.get(i))) { + loadReqs.add(req.get(i)); + } + } + Map load = new HashMap<>(); + //不足的重新加载进redis + if (CollectionUtil.isNotEmpty(loadReqs)) { + load = load(loadReqs); + Map loadMap = load.entrySet().stream() + .map(a -> Pair.of(getKey(a.getKey()), a.getValue())) + .collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); + RedisUtils.mset(loadMap, getExpireSeconds()); + } + + //组装最后的结果 + Map resultMap = new HashMap<>(); + for (int i = 0; i < req.size(); i++) { + IN in = req.get(i); + OUT out = Optional.ofNullable(valueList.get(i)) + .orElse(load.get(in)); + resultMap.put(in, out); + } + return resultMap; + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java new file mode 100644 index 0000000..1d97529 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java @@ -0,0 +1,16 @@ +package com.abin.mallchat.common.common.service.cache; + +import java.util.List; +import java.util.Map; + +public interface BatchCache { + /** + * 获取单个 + */ + OUT get(IN req); + + /** + * 获取批量 + */ + Map getBatch(List req); +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java index 4eb2ff5..4d2a391 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java @@ -44,7 +44,7 @@ public class CursorUtils { .map(String::valueOf) .orElse(null); Boolean isLast = result.size() != cursorPageBaseReq.getPageSize(); - return new CursorPageBaseResp(cursor, isLast, result); + return new CursorPageBaseResp<>(cursor, isLast, result); } public CursorPageBaseResp getCursorPageByMysql(IService mapper, CursorPageBaseReq request, Consumer> initWrapper, SFunction cursorColumn) { @@ -60,7 +60,7 @@ public class CursorUtils { .map(String::valueOf) .orElse(null); Boolean isLast = page.getRecords().size() != request.getPageSize(); - return new CursorPageBaseResp(cursor, isLast, page.getRecords()); + return new CursorPageBaseResp<>(cursor, isLast, page.getRecords()); } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java index e694ec1..415c676 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java @@ -8,23 +8,17 @@ import org.springframework.data.redis.core.*; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.RedisScript; -import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; - @Slf4j -@Component public class RedisUtils { - public RedisTemplate redisTemplate; private static StringRedisTemplate stringRedisTemplate; - @PostConstruct - public void init() { + static { RedisUtils.stringRedisTemplate = SpringUtil.getBean(StringRedisTemplate.class); } @@ -49,7 +43,7 @@ public class RedisUtils { * @param key 键 * @param time 时间(秒) */ - public static boolean expire(String key, long time) { + public static Boolean expire(String key, long time) { try { if (time > 0) { stringRedisTemplate.expire(key, time, TimeUnit.SECONDS); @@ -68,10 +62,10 @@ public class RedisUtils { * @param time 时间(秒) * @param timeUnit 单位 */ - public boolean expire(String key, long time, TimeUnit timeUnit) { + public static Boolean expire(String key, long time, TimeUnit timeUnit) { try { if (time > 0) { - redisTemplate.expire(key, time, timeUnit); + stringRedisTemplate.expire(key, time, timeUnit); } } catch (Exception e) { log.error(e.getMessage(), e); @@ -86,7 +80,7 @@ public class RedisUtils { * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ - public static long getExpire(String key) { + public static Long getExpire(String key) { return stringRedisTemplate.getExpire(key, TimeUnit.SECONDS); } @@ -96,7 +90,7 @@ public class RedisUtils { * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ - public static long getExpire(String key, TimeUnit timeUnit) { + public static Long getExpire(String key, TimeUnit timeUnit) { return stringRedisTemplate.getExpire(key, timeUnit); } @@ -106,9 +100,9 @@ public class RedisUtils { * @param pattern key * @return / */ - public List scan(String pattern) { + public static List scan(String pattern) { ScanOptions options = ScanOptions.scanOptions().match(pattern).build(); - RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); + RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory(); RedisConnection rc = Objects.requireNonNull(factory).getConnection(); Cursor cursor = rc.scan(options); List result = new ArrayList<>(); @@ -131,9 +125,9 @@ public class RedisUtils { * @param size 每页数目 * @return / */ - public List findKeysForPage(String patternKey, int page, int size) { + public static List findKeysForPage(String patternKey, int page, int size) { ScanOptions options = ScanOptions.scanOptions().match(patternKey).build(); - RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); + RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory(); RedisConnection rc = Objects.requireNonNull(factory).getConnection(); Cursor cursor = rc.scan(options); List result = new ArrayList<>(size); @@ -167,9 +161,9 @@ public class RedisUtils { * @param key 键 * @return true 存在 false不存在 */ - public boolean hasKey(String key) { + public static Boolean hasKey(String key) { try { - return redisTemplate.hasKey(key); + return stringRedisTemplate.hasKey(key); } catch (Exception e) { log.error(e.getMessage(), e); return false; @@ -185,21 +179,23 @@ public class RedisUtils { public static void del(String... keys) { if (keys != null && keys.length > 0) { if (keys.length == 1) { - boolean result = stringRedisTemplate.delete(keys[0]); - log.debug("--------------------------------------------"); - log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString()); + Boolean result = stringRedisTemplate.delete(keys[0]); log.debug("--------------------------------------------"); + log.debug("删除缓存:" + keys[0] + ",结果:" + result); } else { Set keySet = new HashSet<>(); for (String key : keys) { - keySet.addAll(stringRedisTemplate.keys(key)); + Set stringSet = stringRedisTemplate.keys(key); + if (Objects.nonNull(stringSet) && !stringSet.isEmpty()) { + keySet.addAll(stringSet); + } } - long count = stringRedisTemplate.delete(keySet); + Long count = stringRedisTemplate.delete(keySet); log.debug("--------------------------------------------"); - log.debug("成功删除缓存:" + keySet.toString()); + log.debug("成功删除缓存:" + keySet); log.debug("缓存删除数量:" + count + "个"); - log.debug("--------------------------------------------"); } + log.debug("--------------------------------------------"); } } @@ -222,7 +218,7 @@ public class RedisUtils { * @param value 值 * @return true成功 false失败 */ - public static boolean set(String key, Object value) { + public static Boolean set(String key, Object value) { try { stringRedisTemplate.opsForValue().set(key, objToStr(value)); return true; @@ -243,7 +239,10 @@ public class RedisUtils { public static List mget(Collection keys, Class tClass) { List list = stringRedisTemplate.opsForValue().multiGet(keys); - return (List) list.stream().map(o -> toBeanOrNull(o, tClass)).collect(Collectors.toList()); + if (Objects.isNull(list)) { + return new ArrayList<>(); + } + return list.stream().map(o -> toBeanOrNull(o, tClass)).collect(Collectors.toList()); } static T toBeanOrNull(String json, Class tClass) { @@ -271,10 +270,10 @@ public class RedisUtils { * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ - public boolean set(String key, Object value, long time) { + public static Boolean set(String key, Object value, long time) { try { if (time > 0) { - redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + stringRedisTemplate.opsForValue().set(key, objToStr(value), time, TimeUnit.SECONDS); } else { set(key, value); } @@ -294,7 +293,7 @@ public class RedisUtils { * @param timeUnit 类型 * @return true成功 false 失败 */ - public static boolean set(String key, Object value, long time, TimeUnit timeUnit) { + public static Boolean set(String key, Object value, long time, TimeUnit timeUnit) { try { if (time > 0) { stringRedisTemplate.opsForValue().set(key, objToStr(value), time, timeUnit); @@ -317,8 +316,8 @@ public class RedisUtils { * @param item 项 不能为null * @return 值 */ - public Object hget(String key, String item) { - return redisTemplate.opsForHash().get(key, item); + public static Object hget(String key, String item) { + return stringRedisTemplate.opsForHash().get(key, item); } /** @@ -327,8 +326,8 @@ public class RedisUtils { * @param key 键 * @return 对应的多个键值 */ - public Map hmget(String key) { - return redisTemplate.opsForHash().entries(key); + public static Map hmget(String key) { + return stringRedisTemplate.opsForHash().entries(key); } @@ -339,9 +338,9 @@ public class RedisUtils { * @param map 对应多个键值 * @return true 成功 false 失败 */ - public boolean hmset(String key, Map map) { + public static Boolean hmset(String key, Map map) { try { - redisTemplate.opsForHash().putAll(key, map); + stringRedisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -357,9 +356,9 @@ public class RedisUtils { * @param time 时间(秒) * @return true成功 false失败 */ - public boolean hmset(String key, Map map, long time) { + public static Boolean hmset(String key, Map map, long time) { try { - redisTemplate.opsForHash().putAll(key, map); + stringRedisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time); } @@ -378,9 +377,9 @@ public class RedisUtils { * @param value 值 * @return true 成功 false失败 */ - public boolean hset(String key, String item, Object value) { + public static Boolean hset(String key, String item, Object value) { try { - redisTemplate.opsForHash().put(key, item, value); + stringRedisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -397,9 +396,9 @@ public class RedisUtils { * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ - public boolean hset(String key, String item, Object value, long time) { + public static Boolean hset(String key, String item, Object value, long time) { try { - redisTemplate.opsForHash().put(key, item, value); + stringRedisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time); } @@ -416,8 +415,8 @@ public class RedisUtils { * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ - public void hdel(String key, Object... item) { - redisTemplate.opsForHash().delete(key, item); + public static void hdel(String key, Object... item) { + stringRedisTemplate.opsForHash().delete(key, item); } /** @@ -427,8 +426,8 @@ public class RedisUtils { * @param item 项 不能为null * @return true 存在 false不存在 */ - public boolean hHasKey(String key, String item) { - return redisTemplate.opsForHash().hasKey(key, item); + public static Boolean hHasKey(String key, String item) { + return stringRedisTemplate.opsForHash().hasKey(key, item); } /** @@ -439,8 +438,8 @@ public class RedisUtils { * @param by 要增加几(大于0) * @return */ - public double hincr(String key, String item, double by) { - return redisTemplate.opsForHash().increment(key, item, by); + public static Double hincr(String key, String item, double by) { + return stringRedisTemplate.opsForHash().increment(key, item, by); } /** @@ -451,8 +450,8 @@ public class RedisUtils { * @param by 要减少记(小于0) * @return */ - public double hdecr(String key, String item, double by) { - return redisTemplate.opsForHash().increment(key, item, -by); + public static Double hdecr(String key, String item, double by) { + return stringRedisTemplate.opsForHash().increment(key, item, -by); } // ============================set============================= @@ -463,9 +462,9 @@ public class RedisUtils { * @param key 键 * @return */ - public Set sGet(String key) { + public static Set sGet(String key) { try { - return redisTemplate.opsForSet().members(key); + return stringRedisTemplate.opsForSet().members(key); } catch (Exception e) { log.error(e.getMessage(), e); return null; @@ -479,9 +478,9 @@ public class RedisUtils { * @param value 值 * @return true 存在 false不存在 */ - public boolean sHasKey(String key, Object value) { + public static Boolean sHasKey(String key, Object value) { try { - return redisTemplate.opsForSet().isMember(key, value); + return stringRedisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { log.error(e.getMessage(), e); return false; @@ -495,12 +494,16 @@ public class RedisUtils { * @param values 值 可以是多个 * @return 成功个数 */ - public long sSet(String key, Object... values) { + public static Long sSet(String key, Object... values) { try { - return redisTemplate.opsForSet().add(key, values); + String[] s = new String[values.length]; + for (int i = 0; i < values.length; i++) { + s[i] = objToStr(values[i]); + } + return stringRedisTemplate.opsForSet().add(key, s); } catch (Exception e) { log.error(e.getMessage(), e); - return 0; + return 0L; } } @@ -512,16 +515,20 @@ public class RedisUtils { * @param values 值 可以是多个 * @return 成功个数 */ - public long sSetAndTime(String key, long time, Object... values) { + public static Long sSetAndTime(String key, long time, Object... values) { try { - Long count = redisTemplate.opsForSet().add(key, values); + String[] s = new String[values.length]; + for (int i = 0; i < values.length; i++) { + s[i] = objToStr(values[i]); + } + Long count = stringRedisTemplate.opsForSet().add(key, s); if (time > 0) { expire(key, time); } return count; } catch (Exception e) { log.error(e.getMessage(), e); - return 0; + return 0L; } } @@ -531,12 +538,12 @@ public class RedisUtils { * @param key 键 * @return */ - public long sGetSetSize(String key) { + public static Long sGetSetSize(String key) { try { - return redisTemplate.opsForSet().size(key); + return stringRedisTemplate.opsForSet().size(key); } catch (Exception e) { log.error(e.getMessage(), e); - return 0; + return 0L; } } @@ -547,13 +554,12 @@ public class RedisUtils { * @param values 值 可以是多个 * @return 移除的个数 */ - public long setRemove(String key, Object... values) { + public static Long setRemove(String key, Object... values) { try { - Long count = redisTemplate.opsForSet().remove(key, values); - return count; + return stringRedisTemplate.opsForSet().remove(key, values); } catch (Exception e) { log.error(e.getMessage(), e); - return 0; + return 0L; } } @@ -567,9 +573,9 @@ public class RedisUtils { * @param end 结束 0 到 -1代表所有值 * @return */ - public List lGet(String key, long start, long end) { + public static List lGet(String key, long start, long end) { try { - return redisTemplate.opsForList().range(key, start, end); + return stringRedisTemplate.opsForList().range(key, start, end); } catch (Exception e) { log.error(e.getMessage(), e); return null; @@ -582,12 +588,12 @@ public class RedisUtils { * @param key 键 * @return */ - public long lGetListSize(String key) { + public static Long lGetListSize(String key) { try { - return redisTemplate.opsForList().size(key); + return stringRedisTemplate.opsForList().size(key); } catch (Exception e) { log.error(e.getMessage(), e); - return 0; + return 0L; } } @@ -598,9 +604,9 @@ public class RedisUtils { * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ - public Object lGetIndex(String key, long index) { + public static String lGetIndex(String key, long index) { try { - return redisTemplate.opsForList().index(key, index); + return stringRedisTemplate.opsForList().index(key, index); } catch (Exception e) { log.error(e.getMessage(), e); return null; @@ -614,9 +620,9 @@ public class RedisUtils { * @param value 值 * @return */ - public boolean lSet(String key, Object value) { + public static Boolean lSet(String key, Object value) { try { - redisTemplate.opsForList().rightPush(key, value); + stringRedisTemplate.opsForList().rightPush(key, objToStr(value)); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -632,9 +638,9 @@ public class RedisUtils { * @param time 时间(秒) * @return */ - public boolean lSet(String key, Object value, long time) { + public static Boolean lSet(String key, Object value, long time) { try { - redisTemplate.opsForList().rightPush(key, value); + stringRedisTemplate.opsForList().rightPush(key, objToStr(value)); if (time > 0) { expire(key, time); } @@ -652,9 +658,13 @@ public class RedisUtils { * @param value 值 * @return */ - public boolean lSet(String key, List value) { + public static Boolean lSet(String key, List value) { try { - redisTemplate.opsForList().rightPushAll(key, value); + List list = new ArrayList<>(); + for (Object item : value) { + list.add(objToStr(item)); + } + stringRedisTemplate.opsForList().rightPushAll(key, list); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -670,9 +680,13 @@ public class RedisUtils { * @param time 时间(秒) * @return */ - public boolean lSet(String key, List value, long time) { + public static Boolean lSet(String key, List value, long time) { try { - redisTemplate.opsForList().rightPushAll(key, value); + List list = new ArrayList<>(); + for (Object item : value) { + list.add(objToStr(item)); + } + stringRedisTemplate.opsForList().rightPushAll(key, list); if (time > 0) { expire(key, time); } @@ -691,9 +705,9 @@ public class RedisUtils { * @param value 值 * @return / */ - public boolean lUpdateIndex(String key, long index, Object value) { + public static Boolean lUpdateIndex(String key, long index, Object value) { try { - redisTemplate.opsForList().set(key, index, value); + stringRedisTemplate.opsForList().set(key, index, objToStr(value)); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -709,12 +723,12 @@ public class RedisUtils { * @param value 值 * @return 移除的个数 */ - public long lRemove(String key, long count, Object value) { + public static Long lRemove(String key, long count, Object value) { try { - return redisTemplate.opsForList().remove(key, count, value); + return stringRedisTemplate.opsForList().remove(key, count, value); } catch (Exception e) { log.error(e.getMessage(), e); - return 0; + return 0L; } } @@ -723,11 +737,14 @@ public class RedisUtils { * @param ids id */ public void delByKeys(String prefix, Set ids) { - Set keys = new HashSet<>(); + Set keys = new HashSet<>(); for (Long id : ids) { - keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString())); + Set stringSet = stringRedisTemplate.keys(prefix + id); + if (Objects.nonNull(stringSet) && !stringSet.isEmpty()) { + keys.addAll(stringSet); + } } - long count = redisTemplate.delete(keys); + Long count = stringRedisTemplate.delete(keys); // 此处提示可自行删除 log.debug("--------------------------------------------"); log.debug("成功删除缓存:" + keys.toString()); @@ -762,7 +779,7 @@ public class RedisUtils { * @return */ public Long zAdd(String key, Set> values) { - return redisTemplate.opsForZSet().add(key, values); + return stringRedisTemplate.opsForZSet().add(key, values); } /** @@ -770,8 +787,8 @@ public class RedisUtils { * @param values * @return */ - public Long zRemove(String key, Object... values) { - return redisTemplate.opsForZSet().remove(key, values); + public static Long zRemove(String key, Object... values) { + return stringRedisTemplate.opsForZSet().remove(key, values); } public static Long zRemove(String key, Object value) { @@ -790,8 +807,8 @@ public class RedisUtils { * @param delta * @return */ - public Double zIncrementScore(String key, String value, double delta) { - return redisTemplate.opsForZSet().incrementScore(key, value, delta); + public static Double zIncrementScore(String key, String value, double delta) { + return stringRedisTemplate.opsForZSet().incrementScore(key, value, delta); } /** @@ -801,8 +818,8 @@ public class RedisUtils { * @param value * @return 0表示第一位 */ - public Long zRank(String key, Object value) { - return redisTemplate.opsForZSet().rank(key, value); + public static Long zRank(String key, Object value) { + return stringRedisTemplate.opsForZSet().rank(key, value); } /** @@ -812,8 +829,8 @@ public class RedisUtils { * @param value * @return */ - public Long zReverseRank(String key, Object value) { - return redisTemplate.opsForZSet().reverseRank(key, value); + public static Long zReverseRank(String key, Object value) { + return stringRedisTemplate.opsForZSet().reverseRank(key, value); } /** @@ -824,8 +841,8 @@ public class RedisUtils { * @param end 结束位置, -1查询所有 * @return */ - public Set zRange(String key, long start, long end) { - return redisTemplate.opsForZSet().range(key, start, end); + public static Set zRange(String key, long start, long end) { + return stringRedisTemplate.opsForZSet().range(key, start, end); } /** @@ -836,9 +853,9 @@ public class RedisUtils { * @param end * @return */ - public Set> zRangeWithScores(String key, long start, - long end) { - return redisTemplate.opsForZSet().rangeWithScores(key, start, end); + public static Set> zRangeWithScores(String key, long start, + long end) { + return stringRedisTemplate.opsForZSet().rangeWithScores(key, start, end); } /** @@ -849,8 +866,8 @@ public class RedisUtils { * @param max 最大值 * @return */ - public Set zRangeByScore(String key, double min, double max) { - return redisTemplate.opsForZSet().rangeByScore(key, min, max); + public static Set zRangeByScore(String key, double min, double max) { + return stringRedisTemplate.opsForZSet().rangeByScore(key, min, max); } /** @@ -863,7 +880,7 @@ public class RedisUtils { */ public Set> zRangeByScoreWithScores(String key, double min, double max) { - return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max); + return stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max); } /** @@ -874,9 +891,9 @@ public class RedisUtils { * @param end * @return */ - public Set> zRangeByScoreWithScores(String key, - double min, double max, long start, long end) { - return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max, + public static Set> zRangeByScoreWithScores(String key, + double min, double max, long start, long end) { + return stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max, start, end); } @@ -888,8 +905,8 @@ public class RedisUtils { * @param end * @return */ - public Set zReverseRange(String key, long start, long end) { - return redisTemplate.opsForZSet().reverseRange(key, start, end); + public static Set zReverseRange(String key, long start, long end) { + return stringRedisTemplate.opsForZSet().reverseRange(key, start, end); } // /** @@ -967,8 +984,8 @@ public class RedisUtils { * @param max * @return */ - public Long zCount(String key, double min, double max) { - return redisTemplate.opsForZSet().count(key, min, max); + public static Long zCount(String key, double min, double max) { + return stringRedisTemplate.opsForZSet().count(key, min, max); } /** @@ -977,8 +994,8 @@ public class RedisUtils { * @param key * @return */ - public Long zSize(String key) { - return redisTemplate.opsForZSet().size(key); + public static Long zSize(String key) { + return stringRedisTemplate.opsForZSet().size(key); } /** @@ -998,8 +1015,8 @@ public class RedisUtils { * @param value * @return */ - public Double zScore(String key, Object value) { - return redisTemplate.opsForZSet().score(key, value); + public static Double zScore(String key, Object value) { + return stringRedisTemplate.opsForZSet().score(key, value); } /** @@ -1010,8 +1027,8 @@ public class RedisUtils { * @param end * @return */ - public Long zRemoveRange(String key, long start, long end) { - return redisTemplate.opsForZSet().removeRange(key, start, end); + public static Long zRemoveRange(String key, long start, long end) { + return stringRedisTemplate.opsForZSet().removeRange(key, start, end); } /** @@ -1022,8 +1039,8 @@ public class RedisUtils { * @param max * @return */ - public Long zRemoveRangeByScore(String key, double min, double max) { - return redisTemplate.opsForZSet().removeRangeByScore(key, min, max); + public static Long zRemoveRangeByScore(String key, double min, double max) { + return stringRedisTemplate.opsForZSet().removeRangeByScore(key, min, max); } /** @@ -1034,8 +1051,8 @@ public class RedisUtils { * @param destKey * @return */ - public Long zUnionAndStore(String key, String otherKey, String destKey) { - return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey); + public static Long zUnionAndStore(String key, String otherKey, String destKey) { + return stringRedisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey); } /** @@ -1044,9 +1061,9 @@ public class RedisUtils { * @param destKey * @return */ - public Long zUnionAndStore(String key, Collection otherKeys, - String destKey) { - return redisTemplate.opsForZSet() + public static Long zUnionAndStore(String key, Collection otherKeys, + String destKey) { + return stringRedisTemplate.opsForZSet() .unionAndStore(key, otherKeys, destKey); } @@ -1058,9 +1075,9 @@ public class RedisUtils { * @param destKey * @return */ - public Long zIntersectAndStore(String key, String otherKey, - String destKey) { - return redisTemplate.opsForZSet().intersectAndStore(key, otherKey, + public static Long zIntersectAndStore(String key, String otherKey, + String destKey) { + return stringRedisTemplate.opsForZSet().intersectAndStore(key, otherKey, destKey); } @@ -1072,9 +1089,9 @@ public class RedisUtils { * @param destKey * @return */ - public Long zIntersectAndStore(String key, Collection otherKeys, - String destKey) { - return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys, + public static Long zIntersectAndStore(String key, Collection otherKeys, + String destKey) { + return stringRedisTemplate.opsForZSet().intersectAndStore(key, otherKeys, destKey); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/SpElUtils.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/SpElUtils.java index ac7e90d..17f70e9 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/SpElUtils.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/SpElUtils.java @@ -8,6 +8,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import java.lang.reflect.Method; +import java.util.Optional; /** * Description: spring el表达式解析 @@ -19,7 +20,7 @@ public class SpElUtils { private static final DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); public static String parseSpEl(Method method, Object[] args, String spEl) { - String[] params = parameterNameDiscoverer.getParameterNames(method);//解析参数名 + String[] params = Optional.ofNullable(parameterNameDiscoverer.getParameterNames(method)).orElse(new String[]{});//解析参数名 EvaluationContext context = new StandardEvaluationContext();//el解析需要的上下文对象 for (int i = 0; i < params.length; i++) { context.setVariable(params[i], args[i]);//所有参数都作为原材料扔进去 diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java index cb13478..79cbefe 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java @@ -66,7 +66,7 @@ public abstract class AbstractUrlTitleDiscover implements UrlTitleDiscover { protected Document getUrlDocument(String matchUrl) { try { Connection connect = Jsoup.connect(matchUrl); - connect.timeout(1000); + connect.timeout(2000); return connect.get(); } catch (Exception e) { log.error("find title error:url:{}", matchUrl, e); diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java index 0bcd4ab..a0a33fa 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java @@ -51,6 +51,13 @@ public class UserBackpackDao extends ServiceImpl getByItemIds(List uids, List itemIds) { + return lambdaQuery().in(UserBackpack::getUid, uids) + .in(UserBackpack::getItemId, itemIds) + .eq(UserBackpack::getStatus, YesOrNoEnum.NO.getStatus()) + .list(); + } + public UserBackpack getByIdp(String idempotent) { return lambdaQuery().eq(UserBackpack::getIdempotent, idempotent).one(); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java index 8184271..659220c 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java @@ -1,5 +1,6 @@ package com.abin.mallchat.common.user.dao; +import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.mapper.UserMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -7,6 +8,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.List; + /** *

* 用户表 服务实现类 @@ -40,4 +43,14 @@ public class UserDao extends ServiceImpl { public User getByName(String name) { return lambdaQuery().eq(User::getName, name).one(); } + + public List getMemberList() { + return lambdaQuery() + .eq(User::getStatus, NormalOrNoEnum.NORMAL.getStatus()) + .orderByDesc(User::getUpdateTime)//最近活跃的1000个人,可以用lastOptTime字段,但是该字段没索引,updateTime可平替 + .last("limit 1000")//毕竟是大群聊,人数需要做个限制 + .select(User::getId, User::getName, User::getAvatar) + .list(); + + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java new file mode 100644 index 0000000..3fda5c5 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java @@ -0,0 +1,27 @@ +package com.abin.mallchat.common.user.domain.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * Description: 修改用户名 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ItemInfoDTO { + @ApiModelProperty(value = "徽章id") + private Long itemId; + @ApiModelProperty("徽章图像") + private String img; + @ApiModelProperty("徽章说明") + private String describe; + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java new file mode 100644 index 0000000..70751d8 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java @@ -0,0 +1,35 @@ +package com.abin.mallchat.common.user.domain.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + + +/** + * Description: 修改用户名 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SummeryInfoDTO { + @ApiModelProperty(value = "用户id") + private Long uid; + @ApiModelProperty(value = "用户昵称") + private String name; + @ApiModelProperty(value = "用户头像") + private String avatar; + @ApiModelProperty(value = "归属地") + private String locPlace; + @ApiModelProperty("佩戴的徽章id") + private Long wearingItemId; + @ApiModelProperty(value = "用户拥有的徽章id列表") + List itemIds; + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java index ff8b82a..15178d4 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -49,13 +49,13 @@ public class Black implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java index a46646b..3232c0a 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java @@ -7,7 +7,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -52,13 +52,13 @@ public class ItemConfig implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java index 4fac5a1..b139c41 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -41,13 +41,13 @@ public class Role implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java index da96761..8952541 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -61,13 +61,13 @@ public class UserBackpack implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/ItemEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/ItemEnum.java index 7428cfe..c50ae3a 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/ItemEnum.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/ItemEnum.java @@ -33,7 +33,7 @@ public enum ItemEnum { cache = Arrays.stream(ItemEnum.values()).collect(Collectors.toMap(ItemEnum::getId, Function.identity())); } - public static ItemEnum of(Integer type) { + public static ItemEnum of(Long type) { return cache.get(type); } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/RoleEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/RoleEnum.java index d233508..d071846 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/RoleEnum.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/RoleEnum.java @@ -29,7 +29,7 @@ public enum RoleEnum { cache = Arrays.stream(RoleEnum.values()).collect(Collectors.toMap(RoleEnum::getId, Function.identity())); } - public static RoleEnum of(Integer type) { + public static RoleEnum of(Long type) { return cache.get(type); } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java index 4302ac3..44b7321 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java @@ -95,6 +95,16 @@ public class UserCache { return cursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.OFFLINE_UID_ZET), Long::parseLong); } + public List getUserModifyTime(List uidList) { + List keys = uidList.stream().map(uid -> RedisKey.getKey(RedisKey.USER_MODIFY_STRING, uid)).collect(Collectors.toList()); + return RedisUtils.mget(keys, Long.class); + } + + public void refreshUserModifyTime(Long uid) { + String key = RedisKey.getKey(RedisKey.USER_MODIFY_STRING, uid); + RedisUtils.set(key, new Date().getTime()); + } + /** * 获取用户信息,盘路缓存模式 */ @@ -120,6 +130,11 @@ public class UserCache { return map; } + public void userInfoChange(Long uid) { + delUserInfo(uid); + refreshUserModifyTime(uid); + } + public void delUserInfo(Long uid) { String key = RedisKey.getKey(RedisKey.USER_INFO_STRING, uid); RedisUtils.del(key); diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java new file mode 100644 index 0000000..df93121 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java @@ -0,0 +1,40 @@ +package com.abin.mallchat.common.user.service.cache; + +import com.abin.mallchat.common.common.constant.RedisKey; +import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache; +import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.entity.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: 用户基本信息的缓存 + * Author: abin + * Date: 2023-06-10 + */ +@Component +public class UserInfoCache extends AbstractRedisStringCache { + @Autowired + private UserDao userDao; + + @Override + protected String getKey(Long uid) { + return RedisKey.getKey(RedisKey.USER_INFO_STRING, uid); + } + + @Override + protected Long getExpireSeconds() { + return 5 * 60L; + } + + @Override + protected Map load(List uidList) { + List needLoadUserList = userDao.listByIds(uidList); + return needLoadUserList.stream().collect(Collectors.toMap(User::getId, Function.identity())); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java new file mode 100644 index 0000000..faa8017 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java @@ -0,0 +1,68 @@ +package com.abin.mallchat.common.user.service.cache; + +import com.abin.mallchat.common.common.constant.RedisKey; +import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache; +import com.abin.mallchat.common.user.dao.UserBackpackDao; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; +import com.abin.mallchat.common.user.domain.entity.*; +import com.abin.mallchat.common.user.domain.enums.ItemTypeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: 用户所有信息的缓存 + * Author: abin + * Date: 2023-06-10 + */ +@Component +public class UserSummaryCache extends AbstractRedisStringCache { + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private UserBackpackDao userBackpackDao; + @Autowired + private ItemCache itemCache; + + @Override + protected String getKey(Long uid) { + return RedisKey.getKey(RedisKey.USER_SUMMARY_STRING, uid); + } + + @Override + protected Long getExpireSeconds() { + return 10 * 60L; + } + + @Override + protected Map load(List uidList) {//后续可优化徽章信息也异步加载 + //用户基本信息 + Map userMap = userInfoCache.getBatch(uidList); + //用户徽章信息 + List itemConfigs = itemCache.getByType(ItemTypeEnum.BADGE.getType()); + List itemIds = itemConfigs.stream().map(ItemConfig::getId).collect(Collectors.toList()); + List backpacks = userBackpackDao.getByItemIds(uidList, itemIds); + Map> userBadgeMap = backpacks.stream().collect(Collectors.groupingBy(UserBackpack::getUid)); + //用户最后一次更新时间 + return uidList.stream().map(uid -> { + SummeryInfoDTO summeryInfoDTO = new SummeryInfoDTO(); + User user = userMap.get(uid); + if (Objects.isNull(user)) { + return null; + } + List userBackpacks = userBadgeMap.getOrDefault(user.getId(), new ArrayList<>()); + summeryInfoDTO.setUid(user.getId()); + summeryInfoDTO.setName(user.getName()); + summeryInfoDTO.setAvatar(user.getAvatar()); + summeryInfoDTO.setLocPlace(Optional.ofNullable(user.getIpInfo()).map(IpInfo::getUpdateIpDetail).map(IpDetail::getCity).orElse(null)); + summeryInfoDTO.setWearingItemId(user.getItemId()); + summeryInfoDTO.setItemIds(userBackpacks.stream().map(UserBackpack::getItemId).collect(Collectors.toList())); + return summeryInfoDTO; + }) + .filter(Objects::nonNull) + .collect(Collectors.toMap(SummeryInfoDTO::getUid, Function.identity())); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java index 7207166..208c16c 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java @@ -1,7 +1,6 @@ package com.abin.mallchat.common.user.service.impl; import cn.hutool.core.lang.TypeReference; - import cn.hutool.core.thread.NamedThreadFactory; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; @@ -13,7 +12,7 @@ import com.abin.mallchat.common.user.domain.entity.IpDetail; import com.abin.mallchat.common.user.domain.entity.IpInfo; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.service.IpService; -import jodd.util.concurrent.ThreadFactoryBuilder; +import com.abin.mallchat.common.user.service.cache.UserCache; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +20,10 @@ import org.springframework.stereotype.Service; import java.util.Date; import java.util.Objects; -import java.util.concurrent.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * Description: ip @@ -31,21 +33,21 @@ import java.util.concurrent.*; @Service @Slf4j public class IpServiceImpl implements IpService, DisposableBean { - private static ExecutorService executor = new ThreadPoolExecutor(1, 1, + private static final ExecutorService EXECUTOR = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(500), - new NamedThreadFactory("refresh-ipDetail", (ThreadGroup)null,false, + new LinkedBlockingQueue<>(500), + new NamedThreadFactory("refresh-ipDetail", null, false, new GlobalUncaughtExceptionHandler())); @Autowired private UserDao userDao; - - + @Autowired + private UserCache userCache; @Override public void refreshIpDetailAsync(Long uid) { - executor.execute(() -> { + EXECUTOR.execute(() -> { User user = userDao.getById(uid); IpInfo ipInfo = user.getIpInfo(); if (Objects.isNull(ipInfo)) { @@ -62,6 +64,7 @@ public class IpServiceImpl implements IpService, DisposableBean { update.setId(uid); update.setIpInfo(ipInfo); userDao.updateById(update); + userCache.userInfoChange(uid); } else { log.error("get ip detail fail ip:{},uid:{}", ip, uid); } @@ -103,7 +106,7 @@ public class IpServiceImpl implements IpService, DisposableBean { Date begin = new Date(); for (int i = 0; i < 100; i++) { int finalI = i; - executor.execute(() -> { + EXECUTOR.execute(() -> { IpDetail ipDetail = TryGetIpDetailOrNullTreeTimes("113.90.36.126"); if (Objects.nonNull(ipDetail)) { Date date = new Date(); @@ -115,13 +118,12 @@ public class IpServiceImpl implements IpService, DisposableBean { @Override public void destroy() throws InterruptedException { - executor.shutdown(); - if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {//最多等30秒,处理不完就拉倒 + EXECUTOR.shutdown(); + if (!EXECUTOR.awaitTermination(30, TimeUnit.SECONDS)) {//最多等30秒,处理不完就拉倒 if (log.isErrorEnabled()) { - log.error("Timed out while waiting for executor [{}] to terminate", executor); + log.error("Timed out while waiting for executor [{}] to terminate", EXECUTOR); } } - - } + } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java index bf89bd0..65200ae 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java @@ -8,24 +8,19 @@ import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; import com.abin.mallchat.common.common.utils.RequestHolder; import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.*; import com.abin.mallchat.custom.chat.service.ChatService; +import com.abin.mallchat.custom.user.service.impl.UserServiceImpl; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.HashSet; -import java.util.Objects; +import java.util.List; import java.util.Set; /** @@ -39,6 +34,7 @@ import java.util.Set; @RestController @RequestMapping("/capi/chat") @Api(tags = "聊天室相关接口") +@Slf4j public class ChatController { @Autowired private ChatService chatService; @@ -53,12 +49,20 @@ public class ChatController { @GetMapping("/public/member/page") @ApiOperation("群成员列表") + @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) public ApiResult> getMemberPage(@Valid CursorPageBaseReq request) { +// black(request); CursorPageBaseResp memberPage = chatService.getMemberPage(request); filterBlackMember(memberPage); return ApiResult.success(memberPage); } + @GetMapping("/member/list") + @ApiOperation("房间内的所有群成员列表-@专用") + public ApiResult> getMemberList(@Valid ChatMessageMemberReq chatMessageMemberReq) { + return ApiResult.success(chatService.getMemberList(chatMessageMemberReq)); + } + private void filterBlackMember(CursorPageBaseResp memberPage) { Set blackMembers = getBlackUidSet(); memberPage.getList().removeIf(a -> blackMembers.contains(a.getUid().toString())); @@ -74,14 +78,28 @@ public class ChatController { return ApiResult.success(chatService.getMemberStatistic()); } + @Autowired + private UserServiceImpl userService; + @GetMapping("/public/msg/page") @ApiOperation("消息列表") + @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) public ApiResult> getMsgPage(@Valid ChatMessagePageReq request) { +// black(request); CursorPageBaseResp msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid()); filterBlackMsg(msgPage); return ApiResult.success(msgPage); } + private void black(CursorPageBaseReq baseReq) { + if (baseReq.getPageSize() > 50) { + log.info("limit request:{}", baseReq); + baseReq.setPageSize(10); + userService.blackIp(RequestHolder.get().getIp()); + } + + } + private void filterBlackMsg(CursorPageBaseResp memberPage) { Set blackMembers = getBlackUidSet(); memberPage.getList().removeIf(a -> blackMembers.contains(a.getFromUser().getUid().toString())); @@ -94,10 +112,6 @@ public class ChatController { @FrequencyControl(time = 30, count = 5, target = FrequencyControl.Target.UID) @FrequencyControl(time = 60, count = 10, target = FrequencyControl.Target.UID) public ApiResult sendMsg(@Valid @RequestBody ChatMessageReq request) { - if (Objects.isNull(request.getBody())) { - TextMsgReq req = new TextMsgReq(request.getContent(), request.getReplyMsgId());//todo 消息兼容之后删了 - request.setBody(req); - } Long msgId = chatService.sendMsg(request, RequestHolder.get().getUid()); //返回完整消息格式,方便前端展示 return ApiResult.success(chatService.getMsgResp(msgId, RequestHolder.get().getUid())); @@ -105,7 +119,7 @@ public class ChatController { @PutMapping("/msg/mark") @ApiOperation("消息标记") - @FrequencyControl(time = 20, count = 3, target = FrequencyControl.Target.UID) + @FrequencyControl(time = 10, count = 5, target = FrequencyControl.Target.UID) public ApiResult setMsgMark(@Valid @RequestBody ChatMessageMarkReq request) { chatService.setMsgMark(RequestHolder.get().getUid(), request); return ApiResult.success(); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java new file mode 100644 index 0000000..4354cb0 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java @@ -0,0 +1,24 @@ +package com.abin.mallchat.custom.chat.domain.vo.request; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * Description: 消息列表请求 + * Author: abin + * Date: 2023-03-29 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChatMessageMemberReq { + @NotNull + @ApiModelProperty("会话id") + private Long roomId; +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java index eb2041b..ac3063d 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java @@ -30,11 +30,4 @@ public class ChatMessageReq { @ApiModelProperty("消息内容,类型不同传值不同,见https://www.yuque.com/snab/mallcaht/rkb2uz5k1qqdmcmd") private Object body; - @ApiModelProperty("消息内容") - @Deprecated - private String content; - - @ApiModelProperty("回复的消息id,如果没有别传就好") - @Deprecated - private Long replyMsgId; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java index 841c75b..a58d6b8 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java @@ -6,6 +6,8 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.util.List; + /** * Description: 文本消息入参 * Author: abin @@ -22,4 +24,7 @@ public class TextMsgReq { @ApiModelProperty("回复的消息id,如果没有别传就好") private Long replyMsgId; + + @ApiModelProperty("艾特的uid") + private List atUidList; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java new file mode 100644 index 0000000..9ba50a4 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java @@ -0,0 +1,25 @@ +package com.abin.mallchat.custom.chat.domain.vo.response; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Description: 群成员列表的成员信息 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChatMemberListResp { + @ApiModelProperty("uid") + private Long uid; + @ApiModelProperty("用户名称") + private String name; + @ApiModelProperty("头像") + private String avatar; +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java index 5b7d18b..34db6c5 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java @@ -6,6 +6,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.util.List; import java.util.Map; /** @@ -22,6 +23,8 @@ public class TextMsgResp { private String content; @ApiModelProperty("消息链接映射") private Map urlTitleMap; + @ApiModelProperty("艾特的uid") + private List atUidList; @ApiModelProperty("父消息,如果没有父消息,返回的是null") private TextMsgResp.ReplyMsg reply; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java index bbf4778..43e00cc 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java @@ -3,16 +3,11 @@ package com.abin.mallchat.custom.chat.service; import com.abin.mallchat.common.chat.domain.entity.Message; import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.*; import javax.annotation.Nullable; +import java.util.List; /** * Description: 消息处理类 @@ -76,4 +71,6 @@ public interface ChatService { void setMsgMark(Long uid, ChatMessageMarkReq request); void recallMsg(Long uid, ChatMessageBaseReq request); + + List getMemberList(ChatMessageMemberReq chatMessageMemberReq); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java index aa4f4a4..dd49ed8 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java @@ -7,7 +7,6 @@ import com.abin.mallchat.common.chat.domain.entity.msg.MessageExtra; import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum; import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum; import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum; -import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover; import com.abin.mallchat.common.user.domain.entity.IpDetail; import com.abin.mallchat.common.user.domain.entity.IpInfo; import com.abin.mallchat.common.user.domain.entity.ItemConfig; @@ -27,7 +26,6 @@ import java.util.stream.Collectors; */ public class MessageAdapter { public static final int CAN_CALLBACK_GAP_COUNT = 100; - private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover(); public static Message buildMsgSave(ChatMessageReq request, Long uid) { @@ -35,16 +33,10 @@ public class MessageAdapter { .fromUid(uid) .roomId(request.getRoomId()) .status(MessageStatusEnum.NORMAL.getStatus()) - .extra(buildExtra(request)) .build(); } - private static MessageExtra buildExtra(ChatMessageReq request) { - Map contentTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(request.getContent()); - return MessageExtra.builder().urlTitleMap(contentTitleMap).build(); - } - public static List buildMsgResp(List messages, Map replyMap, Map userMap, List msgMark, Long receiveUid, Map itemMap) { Map> markMap = msgMark.stream().collect(Collectors.groupingBy(MessageMark::getMsgId)); return messages.stream().map(a -> { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java index 355fca8..adbb1d3 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java @@ -26,14 +26,8 @@ import com.abin.mallchat.common.user.domain.enums.RoleEnum; import com.abin.mallchat.common.user.service.IRoleService; import com.abin.mallchat.common.user.service.cache.ItemCache; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.*; import com.abin.mallchat.custom.chat.service.ChatService; import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter; import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter; @@ -45,7 +39,9 @@ import com.abin.mallchat.custom.chat.service.strategy.msg.AbstractMsgHandler; import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory; import com.abin.mallchat.custom.chat.service.strategy.msg.RecallMsgHandler; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -92,7 +88,7 @@ public class ChatServiceImpl implements ChatService { @Transactional public Long sendMsg(ChatMessageReq request, Long uid) { AbstractMsgHandler msgHandler = MsgHandlerFactory.getStrategyNoNull(request.getMsgType());//todo 这里先不扩展,后续再改 - msgHandler.checkMsg(request); + msgHandler.checkMsg(request, uid); //同步获取消息的跳转链接标题 Message insert = MessageAdapter.buildMsgSave(request, uid); messageDao.save(insert); @@ -196,6 +192,22 @@ public class ChatServiceImpl implements ChatService { recallMsgHandler.recall(uid, message); } + @Override + @Cacheable(cacheNames = "member", key = "'memberList.'+#req.roomId") + public List getMemberList(ChatMessageMemberReq req) { + if (Objects.equals(1L, req.getRoomId())) {//大群聊可看见所有人 + return userDao.getMemberList() + .stream() + .map(a -> { + ChatMemberListResp resp = new ChatMemberListResp(); + BeanUtils.copyProperties(a, resp); + resp.setUid(a.getId()); + return resp; + }).collect(Collectors.toList()); + } + return null; + } + private void checkRecall(Long uid, Message message) { AssertUtil.isNotEmpty(message, "消息有误"); AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回"); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java index 5c88033..1715937 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java @@ -20,7 +20,7 @@ public abstract class AbstractMsgHandler { abstract MessageTypeEnum getMsgTypeEnum(); - public abstract void checkMsg(ChatMessageReq req); + public abstract void checkMsg(ChatMessageReq req, Long uid); public abstract void saveMsg(Message msg, ChatMessageReq req); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java index 3bba9e7..a5fd9e4 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java @@ -40,7 +40,7 @@ public class RecallMsgHandler extends AbstractMsgHandler { } @Override - public void checkMsg(ChatMessageReq request) { + public void checkMsg(ChatMessageReq request, Long uid) { throw new UnsupportedOperationException(); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java index 08a8e84..33762ca 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java @@ -9,15 +9,22 @@ import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum; import com.abin.mallchat.common.chat.service.cache.MsgCache; import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum; import com.abin.mallchat.common.common.utils.AssertUtil; +import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover; import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.RoleEnum; +import com.abin.mallchat.common.user.service.IRoleService; import com.abin.mallchat.common.user.service.cache.UserCache; +import com.abin.mallchat.common.user.service.cache.UserInfoCache; import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq; import com.abin.mallchat.custom.chat.domain.vo.response.msg.TextMsgResp; import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter; +import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -34,6 +41,12 @@ public class TextMsgHandler extends AbstractMsgHandler { private MsgCache msgCache; @Autowired private UserCache userCache; + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private IRoleService iRoleService; + @Autowired + private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover(); @Override MessageTypeEnum getMsgTypeEnum() { @@ -41,7 +54,7 @@ public class TextMsgHandler extends AbstractMsgHandler { } @Override - public void checkMsg(ChatMessageReq request) { + public void checkMsg(ChatMessageReq request, Long uid) { TextMsgReq body = BeanUtil.toBean(request.getBody(), TextMsgReq.class); AssertUtil.isNotEmpty(body.getContent(), "内容不能为空"); AssertUtil.isTrue(body.getContent().length() < 500, "消息内容过长,服务器扛不住啊,兄dei"); @@ -51,14 +64,26 @@ public class TextMsgHandler extends AbstractMsgHandler { AssertUtil.isNotEmpty(replyMsg, "回复消息不存在"); AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息"); } + if (CollectionUtils.isNotEmpty(body.getAtUidList())) { + AssertUtil.isTrue(body.getAtUidList().size() > 10, "一次别艾特这么多人"); + List atUidList = body.getAtUidList(); + Map batch = userInfoCache.getBatch(atUidList); + AssertUtil.equal(atUidList.size(), batch.values().size(), "@用户不存在"); + boolean atAll = body.getAtUidList().contains(0L); + if (atAll) { + AssertUtil.isTrue(iRoleService.hasPower(uid, RoleEnum.CHAT_MANAGER), "没有权限"); + } + } } @Override public void saveMsg(Message msg, ChatMessageReq request) {//插入文本内容 TextMsgReq body = BeanUtil.toBean(request.getBody(), TextMsgReq.class); + MessageExtra extra = Optional.ofNullable(msg.getExtra()).orElse(new MessageExtra()); Message update = new Message(); update.setId(msg.getId()); update.setContent(body.getContent()); + update.setExtra(extra); //如果有回复消息 if (Objects.nonNull(body.getReplyMsgId())) { Integer gapCount = messageDao.getGapCount(request.getRoomId(), body.getReplyMsgId(), msg.getId()); @@ -66,6 +91,15 @@ public class TextMsgHandler extends AbstractMsgHandler { update.setReplyMsgId(body.getReplyMsgId()); } + //判断消息url跳转 + Map urlTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(body.getContent()); + extra.setUrlTitleMap(urlTitleMap); + //艾特功能 + if (CollectionUtils.isNotEmpty(body.getAtUidList())) { + extra.setAtUidList(body.getAtUidList()); + + } + messageDao.updateById(update); } @@ -74,6 +108,7 @@ public class TextMsgHandler extends AbstractMsgHandler { TextMsgResp resp = new TextMsgResp(); resp.setContent(msg.getContent()); resp.setUrlTitleMap(Optional.ofNullable(msg.getExtra()).map(MessageExtra::getUrlTitleMap).orElse(null)); + resp.setAtUidList(Optional.ofNullable(msg.getExtra()).map(MessageExtra::getAtUidList).orElse(null)); //回复消息 Optional reply = Optional.ofNullable(msg.getReplyMsgId()) .map(msgCache::getMsg) diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java index 143b8fb..11aa871 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java @@ -45,7 +45,7 @@ public class ItemReceiveListener { User user = userDao.getById(userBackpack.getUid()); if (Objects.isNull(user.getItemId())) { userDao.wearingBadge(userBackpack.getUid(), userBackpack.getItemId()); - userCache.delUserInfo(userBackpack.getUid()); + userCache.userInfoChange(userBackpack.getUid()); } } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java index bd1c1a7..3380edc 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java @@ -4,11 +4,11 @@ package com.abin.mallchat.custom.user.controller; import com.abin.mallchat.common.common.domain.vo.response.ApiResult; import com.abin.mallchat.common.common.utils.AssertUtil; import com.abin.mallchat.common.common.utils.RequestHolder; +import com.abin.mallchat.common.user.domain.dto.ItemInfoDTO; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; import com.abin.mallchat.common.user.domain.enums.RoleEnum; import com.abin.mallchat.common.user.service.IRoleService; -import com.abin.mallchat.custom.user.domain.vo.request.user.BlackReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.ModifyNameReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.WearingBadgeReq; +import com.abin.mallchat.custom.user.domain.vo.request.user.*; import com.abin.mallchat.custom.user.domain.vo.response.user.BadgeResp; import com.abin.mallchat.custom.user.domain.vo.response.user.UserInfoResp; import com.abin.mallchat.custom.user.service.UserService; @@ -43,6 +43,18 @@ public class UserController { return ApiResult.success(userService.getUserInfo(RequestHolder.get().getUid())); } + @PostMapping("/public/summary/userInfo/batch") + @ApiOperation("用户聚合信息-返回的代表需要刷新的") + public ApiResult> getSummeryUserInfo(@Valid @RequestBody SummeryInfoReq req) { + return ApiResult.success(userService.getSummeryUserInfo(req)); + } + + @PostMapping("/public/badges/batch") + @ApiOperation("徽章聚合信息-返回的代表需要刷新的") + public ApiResult> getItemInfo(@Valid @RequestBody ItemInfoReq req) { + return ApiResult.success(userService.getItemInfo(req)); + } + @PutMapping("/name") @ApiOperation("修改用户名") public ApiResult modifyName(@Valid @RequestBody ModifyNameReq req) { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java new file mode 100644 index 0000000..8d60c86 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java @@ -0,0 +1,34 @@ +package com.abin.mallchat.custom.user.domain.vo.request.user; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Size; +import java.util.List; + + +/** + * Description: 批量查询徽章详情 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ItemInfoReq { + @ApiModelProperty(value = "徽章信息入参") + @Size(max = 50) + private List reqList; + + @Data + public static class infoReq { + @ApiModelProperty(value = "徽章id") + private Long itemId; + @ApiModelProperty(value = "最近一次更新徽章信息时间") + private Long lastModifyTime; + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java new file mode 100644 index 0000000..79b9ad2 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java @@ -0,0 +1,34 @@ +package com.abin.mallchat.custom.user.domain.vo.request.user; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Size; +import java.util.List; + + +/** + * Description: 批量查询用户汇总详情 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SummeryInfoReq { + @ApiModelProperty(value = "用户信息入参") + @Size(max = 50) + private List reqList; + + @Data + public static class infoReq { + @ApiModelProperty(value = "uid") + private Long uid; + @ApiModelProperty(value = "最近一次更新用户信息时间") + private Long lastModifyTime; + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java index a8a8e0e..2cb2259 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java @@ -1,8 +1,8 @@ package com.abin.mallchat.custom.user.service; -import com.abin.mallchat.custom.user.domain.vo.request.user.BlackReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.ModifyNameReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.WearingBadgeReq; +import com.abin.mallchat.common.user.domain.dto.ItemInfoDTO; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; +import com.abin.mallchat.custom.user.domain.vo.request.user.*; import com.abin.mallchat.custom.user.domain.vo.response.user.BadgeResp; import com.abin.mallchat.custom.user.domain.vo.response.user.UserInfoResp; @@ -57,4 +57,14 @@ public interface UserService { void register(String openId); void black(BlackReq req); + + /** + * 获取用户汇总信息 + * + * @param req + * @return + */ + List getSummeryUserInfo(SummeryInfoReq req); + + List getItemInfo(ItemInfoReq req); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/LoginServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/LoginServiceImpl.java index d5beaa8..3ab066d 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/LoginServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/LoginServiceImpl.java @@ -24,8 +24,6 @@ public class LoginServiceImpl implements LoginService { @Autowired private JwtUtils jwtUtils; - @Autowired - private RedisUtils redisUtils; //token过期时间 private static final Integer TOKEN_EXPIRE_DAYS = 5; //token续期时间 @@ -37,6 +35,7 @@ public class LoginServiceImpl implements LoginService { * @param token * @return */ + @Override public boolean verify(String token) { Long uid = jwtUtils.getUidOrNull(token); if (Objects.isNull(uid)) { @@ -48,25 +47,26 @@ public class LoginServiceImpl implements LoginService { } @Async + @Override public void renewalTokenIfNecessary(String token) { Long uid = jwtUtils.getUidOrNull(token); if (Objects.isNull(uid)) { return; } String key = RedisKey.getKey(RedisKey.USER_TOKEN_STRING, uid); - long expireDays = redisUtils.getExpire(key, TimeUnit.DAYS); + long expireDays = RedisUtils.getExpire(key, TimeUnit.DAYS); if (expireDays == -2) {//不存在的key return; } if (expireDays < TOKEN_RENEWAL_DAYS) {//小于一天的token帮忙续期 - redisUtils.expire(key, TOKEN_EXPIRE_DAYS, TimeUnit.DAYS); + RedisUtils.expire(key, TOKEN_EXPIRE_DAYS, TimeUnit.DAYS); } } @Override public String login(Long uid) { String key = RedisKey.getKey(RedisKey.USER_TOKEN_STRING, uid); - String token = redisUtils.getStr(key); + String token = RedisUtils.getStr(key); if (StrUtil.isNotBlank(token)) { return token; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java index 2ddde78..f8c0106 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java @@ -8,6 +8,8 @@ import com.abin.mallchat.common.user.dao.BlackDao; import com.abin.mallchat.common.user.dao.ItemConfigDao; import com.abin.mallchat.common.user.dao.UserBackpackDao; import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.dto.ItemInfoDTO; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; import com.abin.mallchat.common.user.domain.entity.Black; import com.abin.mallchat.common.user.domain.entity.ItemConfig; import com.abin.mallchat.common.user.domain.entity.User; @@ -17,9 +19,8 @@ import com.abin.mallchat.common.user.domain.enums.ItemEnum; import com.abin.mallchat.common.user.domain.enums.ItemTypeEnum; import com.abin.mallchat.common.user.service.cache.ItemCache; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.user.domain.vo.request.user.BlackReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.ModifyNameReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.WearingBadgeReq; +import com.abin.mallchat.common.user.service.cache.UserSummaryCache; +import com.abin.mallchat.custom.user.domain.vo.request.user.*; import com.abin.mallchat.custom.user.domain.vo.response.user.BadgeResp; import com.abin.mallchat.custom.user.domain.vo.response.user.UserInfoResp; import com.abin.mallchat.custom.user.service.UserService; @@ -30,7 +31,10 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -56,6 +60,8 @@ public class UserServiceImpl implements UserService { private ItemCache itemCache; @Autowired private BlackDao blackDao; + @Autowired + private UserSummaryCache userSummaryCache; @Override public UserInfoResp getUserInfo(Long uid) { @@ -79,7 +85,7 @@ public class UserServiceImpl implements UserService { //改名 userDao.modifyName(uid, req.getName()); //删除缓存 - userCache.delUserInfo(uid); + userCache.userInfoChange(uid); } } @@ -105,7 +111,7 @@ public class UserServiceImpl implements UserService { //佩戴徽章 userDao.wearingBadge(uid, req.getBadgeId()); //删除用户缓存 - userCache.delUserInfo(uid); + userCache.userInfoChange(uid); } @Override @@ -128,7 +134,44 @@ public class UserServiceImpl implements UserService { applicationEventPublisher.publishEvent(new UserBlackEvent(this, byId)); } - private void blackIp(String ip) { + @Override + public List getSummeryUserInfo(SummeryInfoReq req) { + //需要前端同步的uid + List uidList = getNeedSyncUidList(req.getReqList()); + //加载用户信息 + Map batch = userSummaryCache.getBatch(uidList); + return new ArrayList<>(batch.values()); + } + + @Override + public List getItemInfo(ItemInfoReq req) {//简单做,更新时间可判断被修改 + return req.getReqList().stream().map(a -> { + ItemConfig itemConfig = itemCache.getById(a.getItemId()); + if (Objects.nonNull(a.getLastModifyTime()) && a.getLastModifyTime() >= itemConfig.getUpdateTime().getTime()) { + return null; + } + ItemInfoDTO dto = new ItemInfoDTO(); + dto.setItemId(itemConfig.getId()); + dto.setImg(itemConfig.getImg()); + dto.setDescribe(itemConfig.getDescribe()); + return dto; + }).collect(Collectors.toList()); + } + + private List getNeedSyncUidList(List reqList) { + List result = new ArrayList<>(); + List userModifyTime = userCache.getUserModifyTime(reqList.stream().map(SummeryInfoReq.infoReq::getUid).collect(Collectors.toList())); + for (int i = 0; i < reqList.size(); i++) { + SummeryInfoReq.infoReq infoReq = reqList.get(i); + Long modifyTime = userModifyTime.get(i); + if (Objects.isNull(infoReq.getLastModifyTime()) || (Objects.nonNull(modifyTime) && modifyTime > infoReq.getLastModifyTime())) { + result.add(infoReq.getUid()); + } + } + return result; + } + + public void blackIp(String ip) { if (StrUtil.isBlank(ip)) { return; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java index 20d5aaf..e994bf0 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.json.JSONUtil; +import com.abin.mallchat.common.common.annotation.FrequencyControl; import com.abin.mallchat.common.common.config.ThreadPoolConfig; import com.abin.mallchat.common.common.event.UserOfflineEvent; import com.abin.mallchat.common.common.event.UserOnlineEvent; @@ -89,6 +90,8 @@ public class WebSocketServiceImpl implements WebSocketService { */ @SneakyThrows @Override + @FrequencyControl(time = 10, count = 2, spEl = "T(com.abin.mallchat.common.common.utils.RequestHolder).get().getIp()") + @FrequencyControl(time = 100, count = 5, spEl = "T(com.abin.mallchat.common.common.utils.RequestHolder).get().getIp()") public void handleLoginReq(Channel channel) { //生成随机不重复的登录码 Integer code = generateLoginCode(channel); @@ -119,6 +122,7 @@ public class WebSocketServiceImpl implements WebSocketService { * @param channel */ @Override + @FrequencyControl(time = 10, count = 5, spEl = "T(com.abin.mallchat.common.common.utils.RequestHolder).get().getIp()") public void connect(Channel channel) { ONLINE_WS_MAP.put(channel, new WSChannelExtraDTO()); } @@ -174,6 +178,7 @@ public class WebSocketServiceImpl implements WebSocketService { getOrInitChannelExt(channel).setUid(uid); ONLINE_UID_MAP.putIfAbsent(uid, new CopyOnWriteArrayList<>()); ONLINE_UID_MAP.get(uid).add(channel); + NettyUtil.setAttr(channel, NettyUtil.UID, uid); } /** diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyCollectorHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyCollectorHandler.java new file mode 100644 index 0000000..902bab7 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyCollectorHandler.java @@ -0,0 +1,27 @@ +package com.abin.mallchat.custom.user.websocket; + +import com.abin.mallchat.common.common.constant.MDCKey; +import com.abin.mallchat.common.common.domain.dto.RequestInfo; +import com.abin.mallchat.common.common.utils.RequestHolder; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; + +import java.util.UUID; + + +@Slf4j +public class NettyCollectorHandler extends ChannelInboundHandlerAdapter { + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + String tid = UUID.randomUUID().toString(); + MDC.put(MDCKey.TID, tid); + RequestInfo info = new RequestInfo(); + info.setUid(NettyUtil.getAttr(ctx.channel(), NettyUtil.UID)); + info.setIp(NettyUtil.getAttr(ctx.channel(), NettyUtil.IP)); + RequestHolder.set(info); + + ctx.fireChannelRead(msg); + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyUtil.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyUtil.java index 2d6a9d0..d2bacef 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyUtil.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyUtil.java @@ -13,6 +13,7 @@ import io.netty.util.AttributeKey; public class NettyUtil { public static AttributeKey IP = AttributeKey.valueOf("ip"); + public static AttributeKey UID = AttributeKey.valueOf("uid"); public static void setAttr(Channel channel, AttributeKey attributeKey, T data) { Attribute attr = channel.attr(attributeKey); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServer.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServer.java index c639dbf..fb9d912 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServer.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServer.java @@ -79,6 +79,7 @@ public class NettyWebSocketServer { pipeline.addLast(new HttpObjectAggregator(8192)); //保存用户ip pipeline.addLast(new HttpHeadersHandler()); + pipeline.addLast(new NettyCollectorHandler()); /** * 说明: * 1. 对于 WebSocket,它的数据是以帧frame 的形式传递的; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java index ff16488..7f1c981 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java @@ -9,6 +9,7 @@ import com.abin.mallchat.custom.user.service.WebSocketService; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import lombok.extern.slf4j.Slf4j; @@ -20,7 +21,7 @@ public class NettyWebSocketServerHandler extends SimpleChannelInboundHandler