mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-13 21:53:41 +08:00
@@ -21,9 +21,10 @@ CREATE TABLE `item_config` (
|
|||||||
-- Records of item_config
|
-- Records of item_config
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
INSERT INTO `item_config` VALUES (1, 1, NULL, '用户可以使用改名卡,更改自己的名字。mallchat名称全局唯一,快抢订你的专属昵称吧', '2023-03-25 22:27:30.511', '2023-03-25 22:27:30.511');
|
INSERT INTO `item_config` VALUES (1, 1, NULL, '用户可以使用改名卡,更改自己的名字。mallchat名称全局唯一,快抢订你的专属昵称吧', '2023-03-25 22:27:30.511', '2023-03-25 22:27:30.511');
|
||||||
INSERT INTO `item_config` VALUES (2, 2, 'https://cdn-icons-png.flaticon.com/512/10667/10667168.png ', '爆赞徽章,单条消息被点赞超过10次,即可获得', '2023-05-07 17:50:31.090', '2023-05-07 18:12:05.824');
|
INSERT INTO `item_config` VALUES (2, 2, 'https://cdn-icons-png.flaticon.com/128/1533/1533913.png', '爆赞徽章,单条消息被点赞超过10次,即可获得', '2023-05-07 17:50:31.090', '2023-05-07 18:12:05.824');
|
||||||
INSERT INTO `item_config` VALUES (3, 2, 'https://cdn-icons-png.flaticon.com/512/6198/6198527.png ', '抹茶聊天前10名注册的用户才能获得的专属徽章', '2023-05-07 17:50:31.100', '2023-05-07 18:12:01.448');
|
INSERT INTO `item_config` VALUES (3, 2, 'https://cdn-icons-png.flaticon.com/512/6198/6198527.png ', '抹茶聊天前10名注册的用户才能获得的专属徽章', '2023-05-07 17:50:31.100', '2023-05-07 18:12:01.448');
|
||||||
INSERT INTO `item_config` VALUES (4, 2, 'https://cdn-icons-png.flaticon.com/512/10232/10232583.png', '抹茶聊天前100名注册的用户才能获得的专属徽章', '2023-05-07 17:50:31.109', '2023-05-07 17:56:36.059');
|
INSERT INTO `item_config` VALUES (4, 2, 'https://cdn-icons-png.flaticon.com/512/10232/10232583.png', '抹茶聊天前100名注册的用户才能获得的专属徽章', '2023-05-07 17:50:31.109', '2023-05-07 17:56:36.059');
|
||||||
|
INSERT INTO `item_config` VALUES (5, 2, 'https://cdn-icons-png.flaticon.com/128/2909/2909937.png', '抹茶知识星球成员的专属徽章', '2023-05-07 17:50:31.109', '2023-05-07 17:56:36.059');
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for message
|
-- Table structure for message
|
||||||
|
|||||||
@@ -93,9 +93,8 @@
|
|||||||
<version>2.0.9</version>
|
<version>2.0.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.validator</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
<version>6.0.1.Final</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.abin.mallchat.common.common.exception;
|
|||||||
|
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.BindException;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
@@ -23,6 +24,18 @@ public class GlobalExceptionHandler {
|
|||||||
return ApiResult.fail(-1, message.substring(0, message.length() - 1));
|
return ApiResult.fail(-1, message.substring(0, message.length() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validation参数校验异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(value = BindException.class)
|
||||||
|
public ApiResult bindException(BindException e) {
|
||||||
|
StringBuilder errorMsg = new StringBuilder();
|
||||||
|
e.getBindingResult().getFieldErrors().forEach(x -> errorMsg.append(x.getField()).append(x.getDefaultMessage()).append(","));
|
||||||
|
String message = errorMsg.toString();
|
||||||
|
log.info("validation parameters error!The reason is:{}", message);
|
||||||
|
return ApiResult.fail(-1, message.substring(0, message.length() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理空指针的异常
|
* 处理空指针的异常
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ import java.util.List;
|
|||||||
public class UserBackpackDao extends ServiceImpl<UserBackpackMapper, UserBackpack> {
|
public class UserBackpackDao extends ServiceImpl<UserBackpackMapper, UserBackpack> {
|
||||||
|
|
||||||
public Integer getCountByValidItemId(Long uid, Long itemId) {
|
public Integer getCountByValidItemId(Long uid, Long itemId) {
|
||||||
LambdaQueryWrapper<UserBackpack> wrapper = new QueryWrapper<UserBackpack>().lambda()
|
return lambdaQuery().eq(UserBackpack::getUid, uid)
|
||||||
.eq(UserBackpack::getUid, uid)
|
|
||||||
.eq(UserBackpack::getItemId, itemId)
|
.eq(UserBackpack::getItemId, itemId)
|
||||||
.eq(UserBackpack::getStatus, YesOrNoEnum.NO.getStatus());
|
.eq(UserBackpack::getStatus, YesOrNoEnum.NO.getStatus())
|
||||||
return count(wrapper);
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserBackpack getFirstValidItem(Long uid, Long itemId) {
|
public UserBackpack getFirstValidItem(Long uid, Long itemId) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public enum ItemEnum {
|
|||||||
LIKE_BADGE(2L, ItemTypeEnum.BADGE, "爆赞徽章"),
|
LIKE_BADGE(2L, ItemTypeEnum.BADGE, "爆赞徽章"),
|
||||||
REG_TOP10_BADGE(3L, ItemTypeEnum.BADGE, "前十注册徽章"),
|
REG_TOP10_BADGE(3L, ItemTypeEnum.BADGE, "前十注册徽章"),
|
||||||
REG_TOP100_BADGE(4L, ItemTypeEnum.BADGE, "前100注册徽章"),
|
REG_TOP100_BADGE(4L, ItemTypeEnum.BADGE, "前100注册徽章"),
|
||||||
|
PLANET(5L, ItemTypeEnum.BADGE, "知识星球"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Long id;
|
private final Long id;
|
||||||
|
|||||||
@@ -35,11 +35,18 @@ public class UserBackpackServiceImpl implements IUserBackpackService {
|
|||||||
private ItemCache itemCache;
|
private ItemCache itemCache;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApplicationEventPublisher applicationEventPublisher;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
@Autowired
|
||||||
|
private UserBackpackServiceImpl userBackpackService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@RedissonLock(key = "#uid", waitTime = 5000)//相同用户会同时发奖,需要排队不能直接拒绝
|
|
||||||
public void acquireItem(Long uid, Long itemId, IdempotentEnum idempotentEnum, String businessId) {
|
public void acquireItem(Long uid, Long itemId, IdempotentEnum idempotentEnum, String businessId) {
|
||||||
|
//组装幂等号
|
||||||
String idempotent = getIdempotent(itemId, idempotentEnum, businessId);
|
String idempotent = getIdempotent(itemId, idempotentEnum, businessId);
|
||||||
|
userBackpackService.doAcquireItem(uid, itemId, idempotent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RedissonLock(key = "#idempotent", waitTime = 5000)//相同幂等如果同时发奖,需要排队等上一个执行完,取出之前数据返回
|
||||||
|
public void doAcquireItem(Long uid, Long itemId, String idempotent) {
|
||||||
UserBackpack userBackpack = userBackpackDao.getByIdp(idempotent);
|
UserBackpack userBackpack = userBackpackDao.getByIdp(idempotent);
|
||||||
//幂等检查
|
//幂等检查
|
||||||
if (Objects.nonNull(userBackpack)) {
|
if (Objects.nonNull(userBackpack)) {
|
||||||
|
|||||||
@@ -44,13 +44,13 @@ public class ChatController {
|
|||||||
|
|
||||||
@GetMapping("/public/room/page")
|
@GetMapping("/public/room/page")
|
||||||
@ApiOperation("会话列表")
|
@ApiOperation("会话列表")
|
||||||
public ApiResult<CursorPageBaseResp<ChatRoomResp>> getRoomPage(CursorPageBaseReq request) {
|
public ApiResult<CursorPageBaseResp<ChatRoomResp>> getRoomPage(@Valid CursorPageBaseReq request) {
|
||||||
return ApiResult.success(chatService.getRoomPage(request, RequestHolder.get().getUid()));
|
return ApiResult.success(chatService.getRoomPage(request, RequestHolder.get().getUid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/public/member/page")
|
@GetMapping("/public/member/page")
|
||||||
@ApiOperation("群成员列表")
|
@ApiOperation("群成员列表")
|
||||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(CursorPageBaseReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid CursorPageBaseReq request) {
|
||||||
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
||||||
filterBlackMember(memberPage);
|
filterBlackMember(memberPage);
|
||||||
return ApiResult.success(memberPage);
|
return ApiResult.success(memberPage);
|
||||||
@@ -72,7 +72,7 @@ public class ChatController {
|
|||||||
|
|
||||||
@GetMapping("/public/msg/page")
|
@GetMapping("/public/msg/page")
|
||||||
@ApiOperation("消息列表")
|
@ApiOperation("消息列表")
|
||||||
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(ChatMessagePageReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(@Valid ChatMessagePageReq request) {
|
||||||
CursorPageBaseResp<ChatMessageResp> msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid());
|
CursorPageBaseResp<ChatMessageResp> msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid());
|
||||||
filterBlackMsg(msgPage);
|
filterBlackMsg(msgPage);
|
||||||
return ApiResult.success(msgPage);
|
return ApiResult.success(msgPage);
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ public abstract class AbstractMsgMarkStrategy {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void mark(Long uid, Long msgId) {
|
public void mark(Long uid, Long msgId) {
|
||||||
exec(uid, msgId, MessageMarkActTypeEnum.MARK);
|
doMark(uid, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void unMark(Long uid, Long msgId) {
|
public void unMark(Long uid, Long msgId) {
|
||||||
exec(uid, msgId, MessageMarkActTypeEnum.UN_MARK);
|
doUnMark(uid, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@@ -44,6 +44,14 @@ public abstract class AbstractMsgMarkStrategy {
|
|||||||
MsgMarkFactory.register(getTypeEnum().getType(), this);
|
MsgMarkFactory.register(getTypeEnum().getType(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void doMark(Long uid, Long msgId) {
|
||||||
|
exec(uid, msgId, MessageMarkActTypeEnum.MARK);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doUnMark(Long uid, Long msgId) {
|
||||||
|
exec(uid, msgId, MessageMarkActTypeEnum.UN_MARK);
|
||||||
|
}
|
||||||
|
|
||||||
protected void exec(Long uid, Long msgId, MessageMarkActTypeEnum actTypeEnum) {
|
protected void exec(Long uid, Long msgId, MessageMarkActTypeEnum actTypeEnum) {
|
||||||
Integer markType = getTypeEnum().getType();
|
Integer markType = getTypeEnum().getType();
|
||||||
Integer actType = actTypeEnum.getType();
|
Integer actType = actTypeEnum.getType();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class DisLikeStrategy extends AbstractMsgMarkStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mark(Long uid, Long msgId) {
|
public void doMark(Long uid, Long msgId) {
|
||||||
super.mark(uid, msgId);
|
super.mark(uid, msgId);
|
||||||
//同时取消点赞的动作
|
//同时取消点赞的动作
|
||||||
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.LIKE.getType()).unMark(uid, msgId);
|
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.LIKE.getType()).unMark(uid, msgId);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class LikeStrategy extends AbstractMsgMarkStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mark(Long uid, Long msgId) {
|
public void doMark(Long uid, Long msgId) {
|
||||||
super.mark(uid, msgId);
|
super.mark(uid, msgId);
|
||||||
//同时取消点踩的动作
|
//同时取消点踩的动作
|
||||||
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.DISLIKE.getType()).unMark(uid, msgId);
|
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.DISLIKE.getType()).unMark(uid, msgId);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
|||||||
import io.netty.handler.logging.LogLevel;
|
import io.netty.handler.logging.LogLevel;
|
||||||
import io.netty.handler.logging.LoggingHandler;
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -65,7 +66,7 @@ public class NettyWebSocketServer {
|
|||||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||||
ChannelPipeline pipeline = socketChannel.pipeline();
|
ChannelPipeline pipeline = socketChannel.pipeline();
|
||||||
//30秒客户端没有向服务器发送心跳则关闭连接
|
//30秒客户端没有向服务器发送心跳则关闭连接
|
||||||
// pipeline.addLast(new IdleStateHandler(30, 0, 0));
|
pipeline.addLast(new IdleStateHandler(30, 0, 0));
|
||||||
// 因为使用http协议,所以需要使用http的编码器,解码器
|
// 因为使用http协议,所以需要使用http的编码器,解码器
|
||||||
pipeline.addLast(new HttpServerCodec());
|
pipeline.addLast(new HttpServerCodec());
|
||||||
// 以块方式写,添加 chunkedWriter 处理器
|
// 以块方式写,添加 chunkedWriter 处理器
|
||||||
|
|||||||
Reference in New Issue
Block a user