feat: 完善相关功能
This commit is contained in:
@@ -2,17 +2,21 @@ package com.ivmiku.tutorial.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ivmiku.tutorial.entity.Comment;
|
||||
import com.ivmiku.tutorial.entity.Pages;
|
||||
import com.ivmiku.tutorial.response.AtNotifier;
|
||||
import com.ivmiku.tutorial.response.Result;
|
||||
import com.ivmiku.tutorial.service.CommentService;
|
||||
import com.ivmiku.tutorial.service.FileService;
|
||||
import com.ivmiku.tutorial.util.MyRedisUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.apiguardian.api.API;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -36,6 +40,13 @@ public class CommentController {
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@Resource
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Resource
|
||||
private MyRedisUtil redisUtil;
|
||||
|
||||
|
||||
/**
|
||||
* 创建评论接口。
|
||||
*/
|
||||
@@ -66,6 +77,14 @@ public class CommentController {
|
||||
|
||||
commentService.createComment(comment);
|
||||
logger.info("评论创建成功,评论ID:{}", comment.getCommentId());
|
||||
if (!mentionedUserId.isEmpty()) {
|
||||
AtNotifier notifier = new AtNotifier();
|
||||
notifier.setFromId(comment.getUserOpenid());
|
||||
notifier.setToId(mentionedUserId);
|
||||
notifier.setPostId(String.valueOf(comment.getCommentId()));
|
||||
rabbitTemplate.convertAndSend("exchange2", "", JSON.toJSONString(notifier));
|
||||
redisUtil.listAdd("at:" + notifier.getToId(), JSON.toJSONString(notifier));
|
||||
}
|
||||
return Result.ok(comment);
|
||||
}
|
||||
|
||||
@@ -106,6 +125,14 @@ public class CommentController {
|
||||
|
||||
commentService.createComment(reply);
|
||||
logger.info("评论回复成功,评论ID:{}", reply.getCommentId());
|
||||
if (!mentionedUserId.isEmpty()) {
|
||||
AtNotifier notifier = new AtNotifier();
|
||||
notifier.setFromId(reply.getUserOpenid());
|
||||
notifier.setToId(mentionedUserId);
|
||||
notifier.setPostId(String.valueOf(reply.getCommentId()));
|
||||
rabbitTemplate.convertAndSend("exchange2", "", JSON.toJSONString(notifier));
|
||||
redisUtil.listAdd("at:" + notifier.getToId(), JSON.toJSONString(notifier));
|
||||
}
|
||||
return Result.ok(reply);
|
||||
}
|
||||
|
||||
@@ -115,7 +142,6 @@ public class CommentController {
|
||||
comment.setUserOpenid(StpUtil.getLoginIdAsString());
|
||||
comment.setContent(content);
|
||||
comment.setMentionedUserId(mentionedUserId);
|
||||
|
||||
if ("post".equals(type)) {
|
||||
comment.setPostId(postId);
|
||||
} else if ("tutorial".equals(type)) {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.ivmiku.tutorial.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ivmiku.tutorial.entity.UserDTO;
|
||||
import com.ivmiku.tutorial.response.Result;
|
||||
import com.ivmiku.tutorial.service.impl.SearchService;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Controller
|
||||
@ServerEndpoint(value = "/search/{satoken}")
|
||||
public class WebSocketServer {
|
||||
public static Map<String, Session> sessionMap = new ConcurrentHashMap<>();
|
||||
private static ApplicationContext applicationContext;
|
||||
private SearchService searchService;
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, EndpointConfig endpointConfig, @PathParam("satoken") String satoken) throws IOException {
|
||||
String userId = (String) StpUtil.getLoginIdByToken(satoken);
|
||||
if (userId == null) {
|
||||
session.getBasicRemote().sendText("Invalid Token");
|
||||
session.close();
|
||||
}
|
||||
sessionMap.put(userId, session);
|
||||
this.searchService = WebSocketServer.applicationContext.getBean(SearchService.class);
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(CloseReason closeReason, Session session){
|
||||
sessionMap.remove(session.getId());
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Throwable throwable) throws IOException {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) throws IOException {
|
||||
char first = message.charAt(0);
|
||||
String userId = null;
|
||||
for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
|
||||
if (entry.getValue().equals(session)) {
|
||||
userId = entry.getKey();
|
||||
}
|
||||
}
|
||||
switch (first) {
|
||||
case '@' -> {
|
||||
String sub = message.substring(1);
|
||||
List<UserDTO> result = searchService.getUserList(sub, userId);
|
||||
session.getBasicRemote().sendText(JSON.toJSONString(Result.ok(result)));
|
||||
}
|
||||
case '#' -> {
|
||||
String sub = message.substring(1);
|
||||
List<String> list = searchService.getTag(message);
|
||||
session.getBasicRemote().sendText(JSON.toJSONString(Result.ok(list)));
|
||||
}
|
||||
//预留给社区搜索
|
||||
default -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ivmiku.tutorial.entity;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Aurora
|
||||
*/
|
||||
@TableName("subscribe")
|
||||
@Data
|
||||
public class Subscribe {
|
||||
private Long id;
|
||||
private Long subId;
|
||||
}
|
||||
@@ -4,11 +4,15 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@TableName("user")
|
||||
@Data
|
||||
@TableName("User")
|
||||
public class User {
|
||||
@TableId
|
||||
private String openid;
|
||||
private String nickname;
|
||||
private String avatarUrl;
|
||||
private boolean isAdmin;
|
||||
private String phoneNum;
|
||||
private String birthday;
|
||||
private String gender;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ivmiku.tutorial.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserDTO {
|
||||
private String nickname;
|
||||
private String avatarUrl;
|
||||
private String phoneNum;
|
||||
private String birthday;
|
||||
private String gender;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ivmiku.tutorial.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ivmiku.tutorial.entity.Subscribe;
|
||||
|
||||
public interface SubscribeMapper extends BaseMapper<Subscribe> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ivmiku.tutorial.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ivmiku.tutorial.entity.User;
|
||||
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ivmiku.tutorial.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -8,10 +9,13 @@ import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ivmiku.tutorial.entity.Comment;
|
||||
import com.ivmiku.tutorial.mapper.CommentMapper;
|
||||
import com.ivmiku.tutorial.response.AtNotifier;
|
||||
import com.ivmiku.tutorial.service.CommentService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -30,6 +34,9 @@ public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> impl
|
||||
@Autowired
|
||||
protected CommentMapper commentMapper;
|
||||
|
||||
@Resource
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
* 保存评论。
|
||||
* 将评论数据保存到数据库。
|
||||
@@ -186,6 +193,13 @@ public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> impl
|
||||
reply.setMentionedUserId(mentionedUserId);
|
||||
}
|
||||
createComment(reply);
|
||||
if (mentionedUserId != null) {
|
||||
AtNotifier notifier = new AtNotifier();
|
||||
notifier.setFromId(reply.getUserOpenid());
|
||||
notifier.setToId(mentionedUserId);
|
||||
notifier.setPostId(String.valueOf(reply.getCommentId()));
|
||||
rabbitTemplate.convertAndSend("exchange2", "", JSON.toJSONString(notifier));
|
||||
}
|
||||
|
||||
logger.info("评论回复成功,评论ID:{}", reply.getCommentId());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.ivmiku.tutorial.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.ivmiku.tutorial.entity.Subscribe;
|
||||
import com.ivmiku.tutorial.entity.Tag;
|
||||
import com.ivmiku.tutorial.entity.User;
|
||||
import com.ivmiku.tutorial.entity.UserDTO;
|
||||
import com.ivmiku.tutorial.mapper.PostTagMapper;
|
||||
import com.ivmiku.tutorial.mapper.SubscribeMapper;
|
||||
import com.ivmiku.tutorial.mapper.TagMapper;
|
||||
import com.ivmiku.tutorial.mapper.UserMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class SearchService {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Resource
|
||||
private TagMapper tagMapper;
|
||||
|
||||
@Resource
|
||||
private SubscribeMapper subscribeMapper;
|
||||
|
||||
public List<UserDTO> getUserList(String text, String userId) {
|
||||
int len = text.length();
|
||||
QueryWrapper<Subscribe> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user1_id", userId);
|
||||
List<Subscribe> list = subscribeMapper.selectList(queryWrapper);
|
||||
List<UserDTO> result = new ArrayList<>();
|
||||
for (Subscribe subscribe : list) {
|
||||
String user2Id = String.valueOf(subscribe.getSubId());
|
||||
User user = userMapper.selectById(user2Id);
|
||||
if (user.getNickname().substring(0, len).equals(text)) {
|
||||
UserDTO userDTO = new UserDTO();
|
||||
userDTO.setNickname(user.getNickname());
|
||||
userDTO.setAvatarUrl(user.getAvatarUrl());
|
||||
result.add(userDTO);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<String> getTag(String text) {
|
||||
QueryWrapper<Tag> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.likeRight("name", text);
|
||||
List<Tag> list = tagMapper.selectList(queryWrapper);
|
||||
List<String> result = new ArrayList<>();
|
||||
for (Tag tag : list) {
|
||||
result.add(tag.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.ivmiku.tutorial.util;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ivmiku.tutorial.response.AtNotifier;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Aurora
|
||||
*/
|
||||
@Component
|
||||
public class MyRedisUtil {
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public void listAdd(String key, Object value) {
|
||||
redisTemplate.opsForList().leftPush(key, value);
|
||||
}
|
||||
|
||||
public List<AtNotifier> listGet(String key, int s, int e) {
|
||||
List<Object> list = redisTemplate.opsForList().range(key, s, e);
|
||||
List<AtNotifier> result = new ArrayList<>();
|
||||
if (list != null) {
|
||||
for (Object json : list) {
|
||||
result.add(JSON.parseObject(JSON.toJSONString(json), AtNotifier.class));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void listClear(String key) {
|
||||
redisTemplate.opsForList().trim(key, 1, 0);
|
||||
}
|
||||
|
||||
public Long getListSize(String key) {
|
||||
return redisTemplate.opsForList().size(key);
|
||||
}
|
||||
|
||||
public Set<String> getKey() {
|
||||
return redisTemplate.keys("history:*");
|
||||
}
|
||||
|
||||
public Object rightPop(String key) {
|
||||
return redisTemplate.opsForList().rightPop(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void setExpireTime(String key) {
|
||||
if (redisTemplate.opsForValue().getOperations().getExpire(key) > 0) {
|
||||
redisTemplate.expire(key, 3, TimeUnit.DAYS);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshExpire(String key) {
|
||||
redisTemplate.persist(key);
|
||||
redisTemplate.expire(key, 3, TimeUnit.DAYS);
|
||||
}
|
||||
|
||||
public boolean ifExist(String key) {
|
||||
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
|
||||
}
|
||||
|
||||
public List<String> getStringList(String key, int s, int e) {
|
||||
List<Object> list = redisTemplate.opsForList().range(key, s, e);
|
||||
List<String> result = new ArrayList<>();
|
||||
assert list != null;
|
||||
for (Object object : list) {
|
||||
result.add((String) object);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void insertKey(String openid, String sessionKey) {
|
||||
redisTemplate.opsForValue().set("sessionkey:" + openid, sessionKey);
|
||||
}
|
||||
|
||||
public String getKey(String userId) {
|
||||
return (String) redisTemplate.opsForValue().get("sessionkey:" + userId);
|
||||
}
|
||||
|
||||
public void deleteFromList(AtNotifier message) {
|
||||
String id = message.getToId();
|
||||
redisTemplate.opsForList().remove("unread:" + id, 0, message);
|
||||
}
|
||||
}
|
||||
@@ -13,15 +13,12 @@ server.port=8073
|
||||
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=123456
|
||||
spring.datasource.password=Shuodedaoli114514
|
||||
spring.datasource.url=jdbc:mysql://mysql:3306/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
|
||||
spring.cloud.nacos.discovery.server-addr=nacos:8848
|
||||
spring.cloud.nacos.discovery.enabled=true
|
||||
|
||||
management.zipkin.tracing.endpoint=http://127.0.0.1:9411/api/v2/spans
|
||||
management.tracing.sampling.probability=1.0
|
||||
|
||||
dubbo.application.qos-enable=false
|
||||
|
||||
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
|
||||
Reference in New Issue
Block a user