From 7deaba288b5553bca0db6c6b6f312d046eb135d7 Mon Sep 17 00:00:00 2001 From: ivmiku <124345843+ivmiku@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:18:37 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E8=AF=AD=E9=9F=B3=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E5=92=8C=E9=A2=84=E8=AE=BE=E5=9B=9E=E7=AD=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- navigate-8432/pom.xml | 19 ++-- .../controller/AssistantController.java | 7 -- .../com/ivmiku/tutorial/entity/Guidance.java | 14 +++ .../tutorial/mapper/GuidanceMapper.java | 8 ++ .../tutorial/service/AssistantService.java | 86 ++++++++++++++++++- 5 files changed, 115 insertions(+), 19 deletions(-) create mode 100644 navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java create mode 100644 navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java diff --git a/navigate-8432/pom.xml b/navigate-8432/pom.xml index bb3eb35..e3aa5f4 100644 --- a/navigate-8432/pom.xml +++ b/navigate-8432/pom.xml @@ -18,11 +18,6 @@ - - com.baomidou - mybatis-plus-boot-starter - 3.5.7 - org.springframework.boot spring-boot-starter-web @@ -31,10 +26,11 @@ org.springframework.boot spring-boot-starter-actuator - - - - + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.7 + com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery @@ -108,5 +104,10 @@ tencentcloud-sdk-java-tts 3.1.1076 + + com.tencentcloudapi + tencentcloud-sdk-java-asr + 3.1.1083 + \ No newline at end of file diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java index afef15d..c32bcee 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java @@ -24,11 +24,4 @@ public class AssistantController { } return Result.ok(map); } - - @GetMapping("/tts") - public Object textToSpeech(@RequestParam String input) { - Map map = new HashMap<>(); - map.put("content", assistantService.textToSpeech(input)); - return Result.ok(map); - } } diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java new file mode 100644 index 0000000..9b16ab0 --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/Guidance.java @@ -0,0 +1,14 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@TableName("guidance") +@Data +public class Guidance { + @TableId + private String id; + private String tag; + private String content; +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java new file mode 100644 index 0000000..4bdea0f --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/mapper/GuidanceMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Guidance; + +public interface GuidanceMapper extends BaseMapper { + +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java index f060c58..c06c723 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java @@ -2,11 +2,15 @@ package com.ivmiku.tutorial.service; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; -import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ivmiku.tutorial.entity.Guidance; +import com.ivmiku.tutorial.mapper.GuidanceMapper; import com.ivmiku.tutorial.utils.SnowflakeUtil; -import com.tencentcloudapi.common.AbstractModel; +import com.tencentcloudapi.asr.v20190614.AsrClient; +import com.tencentcloudapi.asr.v20190614.models.SentenceRecognitionRequest; +import com.tencentcloudapi.asr.v20190614.models.SentenceRecognitionResponse; import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.common.profile.ClientProfile; @@ -14,18 +18,23 @@ import com.tencentcloudapi.common.profile.HttpProfile; import com.tencentcloudapi.tts.v20190823.TtsClient; import com.tencentcloudapi.tts.v20190823.models.TextToVoiceRequest; import com.tencentcloudapi.tts.v20190823.models.TextToVoiceResponse; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.HashMap; +import java.util.List; import java.util.Map; @Service public class AssistantService { + @Resource + private GuidanceMapper guidanceMapper; + private final String auth = "bad1f6cad39a4c26aa9fe9e4324e096f:ZDczMDIwOTg3NjlhODdmYWVjYTY0YjM1"; private final String secretId = "AKID09INNYxYEFFJH3g9VhljVF3qbDiFdx50"; private final String secretKey = "KajjcNyNaaUCqQroqpzNoMtTHNj4Lbil"; - public Map getResponse(String userInput) { + public Map getAiResponse(String userInput) { Map message1 = new HashMap<>(); message1.put("role", "system"); message1.put("content", "模仿语音助手,对用户的问题给出简短的回答"); @@ -74,4 +83,75 @@ public class AssistantService { throw new RuntimeException(e); } } + + public String speechRecognition(String content, Integer length) { + try{ + Credential cred = new Credential(secretId, secretKey); + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("asr.tencentcloudapi.com"); + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + AsrClient client = new AsrClient(cred, "", clientProfile); + SentenceRecognitionRequest req = new SentenceRecognitionRequest(); + req.setEngSerViceType("16k_zh"); + req.setSourceType(1L); + req.setVoiceFormat("wav"); + req.setData(content); + req.setDataLen(Long.valueOf(length)); + SentenceRecognitionResponse resp = client.SentenceRecognition(req); + return resp.getResult(); + } catch (TencentCloudSDKException e) { + throw new RuntimeException(e); + } + } + + public String searchGuidance(String tag) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.like("tag", tag); + List list = guidanceMapper.selectList(queryWrapper); + if (list.isEmpty()) { + return null; + } + return list.getFirst().getContent(); + } + + public String extractTag(String query) { + Map message1 = new HashMap<>(); + message1.put("role", "system"); + message1.put("content", "根据给出的句子的意思,从以下标签中返回最匹配的一个:安全带、安检、飞机"); + Map message2 = new HashMap<>(); + message2.put("role", "user"); + message2.put("content", query); + JSONArray array = new JSONArray(); + array.add(message1); + array.add(message2); + JSONObject params = new JSONObject(); + params.put("model", "general"); + params.put("messages", array); + HttpResponse response = HttpRequest.post("https://spark-api-open.xf-yun.com/v1/chat/completions") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + auth) + .body(params.toJSONString()) + .execute(); + JSONObject result = JSONObject.parseObject(response.body()); + response.close(); + if (result.getInteger("code") != 0) { + return null; + } + JSONArray choices = result.getJSONArray("choices"); + JSONObject message = choices.getJSONObject(0); + return String.valueOf(message.getJSONObject("message")); + } + + public Map getResponse(String query) { + Map result = new HashMap<>(); + String tag = extractTag(query); + String content; + content = searchGuidance(tag); + if (content != null) { + result.put("content", content); + return result; + } + return getAiResponse(query); + } } From 641449be7ce0b4dec936583e4f6c5ca86435d9a6 Mon Sep 17 00:00:00 2001 From: ivmiku <124345843+ivmiku@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:19:01 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E7=A7=81=E4=BF=A1=E5=92=8C?= =?UTF-8?q?=E5=85=B3=E6=B3=A8=E3=80=81=E7=B2=89=E4=B8=9D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user-8072/pom.xml | 8 + .../tutorial/config/MybatisPlusConfig.java | 24 ++ .../tutorial/config/RabbitMqConfig.java | 27 ++ .../tutorial/config/SaTokenConfigure.java | 15 ++ .../tutorial/config/WebSocketConfig.java | 34 +++ .../controller/MessageController.java | 39 +++ .../controller/RelationController.java | 42 ++++ .../tutorial/controller/WebSocketServer.java | 142 +++++++++++ .../com/ivmiku/tutorial/entity/ChatId.java | 18 ++ .../com/ivmiku/tutorial/entity/Friend.java | 18 ++ .../ivmiku/tutorial/entity/FriendQuery.java | 12 + .../ivmiku/tutorial/entity/HistoryQuery.java | 16 ++ .../ivmiku/tutorial/entity/IgnoreUser.java | 21 ++ .../com/ivmiku/tutorial/entity/Message.java | 25 ++ .../com/ivmiku/tutorial/entity/SubUser.java | 18 ++ .../com/ivmiku/tutorial/entity/Subscribe.java | 13 + .../tutorial/mapper/BlackListMapper.java | 8 + .../ivmiku/tutorial/mapper/ChatIdMapper.java | 8 + .../ivmiku/tutorial/mapper/FriendMapper.java | 8 + .../ivmiku/tutorial/mapper/MessageMapper.java | 8 + .../tutorial/mapper/SubscribeMapper.java | 8 + .../tutorial/service/MessageService.java | 236 ++++++++++++++++++ .../tutorial/service/RelationService.java | 120 +++++++++ .../ivmiku/tutorial/service/UserService.java | 16 ++ .../com/ivmiku/tutorial/utils/DateUtil.java | 43 ++++ .../ivmiku/tutorial/utils/MessageUtil.java | 36 +++ .../com/ivmiku/tutorial/utils/RedisUtil.java | 103 +++++++- 27 files changed, 1062 insertions(+), 4 deletions(-) create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java create mode 100644 user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java diff --git a/user-8072/pom.xml b/user-8072/pom.xml index 7b5121b..5ca0ed8 100644 --- a/user-8072/pom.xml +++ b/user-8072/pom.xml @@ -117,6 +117,14 @@ commons 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-websocket + + + org.springframework.boot + spring-boot-starter-amqp + diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java new file mode 100644 index 0000000..71ed480 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/MybatisPlusConfig.java @@ -0,0 +1,24 @@ +package com.ivmiku.tutorial.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@MapperScan("com.ivmiku.tutorial.mapper") +public class MybatisPlusConfig { + + /** + * 添加分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType + return interceptor; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java new file mode 100644 index 0000000..d9ee381 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/RabbitMqConfig.java @@ -0,0 +1,27 @@ +package com.ivmiku.tutorial.config; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitMqConfig { + @Bean + public Queue queue1() { + return new Queue("queue1",true); + } + + @Bean + public FanoutExchange exchange1() { + return new FanoutExchange("exchange1",true, false); + } + + @Bean + public Binding binding1() { + return BindingBuilder.bind(queue1()).to(exchange1()); + } +} + diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java new file mode 100644 index 0000000..85ca18f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/SaTokenConfigure.java @@ -0,0 +1,15 @@ +package com.ivmiku.tutorial.config; + +import cn.dev33.satoken.interceptor.SaInterceptor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class SaTokenConfigure implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册 Sa-Token 拦截器,打开注解式鉴权功能 + registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java b/user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java new file mode 100644 index 0000000..b36ddc7 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/config/WebSocketConfig.java @@ -0,0 +1,34 @@ +package com.ivmiku.tutorial.config; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; +import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; +import org.springframework.web.util.WebAppRootListener; + +@Configuration +public class WebSocketConfig implements ServletContextInitializer { + @Bean + public ServerEndpointExporter serverEndpointExporter (){ + return new ServerEndpointExporter(); + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + servletContext.addListener(WebAppRootListener.class); + servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize","102400000"); + } + + @Bean + public ServletServerContainerFactoryBean createWebSocketContainer() { + ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); + // 在此处设置bufferSize + container.setMaxTextMessageBufferSize(50*1024*1024); + container.setMaxBinaryMessageBufferSize(50*1024*1024); + container.setMaxSessionIdleTimeout(15 * 60000L); + return container; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java new file mode 100644 index 0000000..326b872 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/MessageController.java @@ -0,0 +1,39 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.HistoryQuery; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.MessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.text.ParseException; + +@SaCheckLogin +@RestController +@RequestMapping("/api/message") +public class MessageController { + @Autowired + private MessageService messageService; + + @PostMapping("/history") + public Object getChatHistory(@RequestBody HistoryQuery input) throws ParseException { + Result result = Result.ok(); + if (input.getStartDate() != null && input.getEndDate() != null) { + result.setData(messageService.getChatHistoryByDate(input.getUser1Id(), input.getUser2Id(), input.getStartDate(), input.getEndDate(), input.getPage(), input.getSize())); + } else { + if (input.getPage() <= 0 || input.getSize() <=0) { + return Result.error("请输入合法分页参数"); + } else { + result.setData(messageService.getChatHistory(input.getUser1Id(), input.getUser2Id(), input.getPage(), input.getSize())); + } + } + return JSON.toJSON(result); + } + + @GetMapping("/list") + public Object getChatList(@RequestParam String user_id, @RequestParam int page, @RequestParam int size) { + return Result.ok(messageService.getChatList(user_id, page, size)); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java new file mode 100644 index 0000000..d7dcc88 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/RelationController.java @@ -0,0 +1,42 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.stp.StpUtil; +import com.ivmiku.tutorial.entity.IgnoreUser; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.RelationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@SaCheckLogin +@RestController +@RequestMapping("/api/relation") +public class RelationController { + @Autowired + private RelationService relationService; + + @PostMapping("/ignore") + public Object ignoreUser(@RequestBody IgnoreUser input) { + relationService.IgnoreUser(input.getUserId(), input.getToIgnore()); + return Result.ok(); + } + + @GetMapping("subscribe") + public Object subscribe(@RequestParam String subId) { + String userId = (String) StpUtil.getLoginId(); + relationService.subscribe(userId, subId); + return Result.ok(); + } + + @GetMapping("fan") + public Object getFanList(@RequestParam int page, @RequestParam int size) { + String userId = (String) StpUtil.getLoginId(); + return Result.ok(relationService.getFanList(userId, page, size)); + } + + @GetMapping("follow") + public Object getFollowList(@RequestParam int page, @RequestParam int size) { + String userId = (String) StpUtil.getLoginId(); + return Result.ok(relationService.getSubList(userId, page, size)); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java new file mode 100644 index 0000000..993c05f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java @@ -0,0 +1,142 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.Message; +import com.ivmiku.tutorial.service.MessageService; +import com.ivmiku.tutorial.service.RelationService; +import com.ivmiku.tutorial.utils.DateUtil; +import com.ivmiku.tutorial.utils.MessageUtil; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Controller; + +import java.io.IOException; +import java.text.ParseException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import static jakarta.websocket.CloseReason.CloseCodes.CLOSED_ABNORMALLY; + +@Controller +@ServerEndpoint(value = "/chat/{satoken}") +public class WebSocketServer implements ApplicationContextAware { + public static Map sessionMap = new ConcurrentHashMap<>(); + + public static Map controlMap = new HashMap<>(); + + private static ApplicationContext applicationContext; + + @Autowired + private MessageService messageService; + + private RabbitTemplate rabbitTemplate; + + private RelationService relationService; + + @OnMessage + public void onMessage(String message, Session session) throws IOException { + Message msg = JSON.parseObject(message, Message.class); + msg.setDate(DateUtil.getCurrentTime()); + if (MessageUtil.checkMessage(msg.getMessage())) { + session.getBasicRemote().sendText("发送的信息含有敏感词,请进行调整"); + if (!controlMap.containsKey(msg.getFromId())){ + controlMap.put(msg.getFromId(), 0); + } + if (controlMap.get(msg.getFromId()) == 4){ + session.getBasicRemote().sendText("由于多次违反社区规则,您已被封禁1小时"); + session.close(new CloseReason(CLOSED_ABNORMALLY, "账号被封禁")); + StpUtil.kickout(msg.getFromId()); + StpUtil.disable(msg.getFromId(), 3600); + controlMap.put(msg.getFromId(), 0); + } + controlMap.put(msg.getFromId(), controlMap.get(msg.getFromId())+1); + } else + if (relationService.ifIgnored(msg.getToId(), msg.getFromId())) { + session.getBasicRemote().sendText("您已被对方屏蔽"); + } else { + rabbitTemplate.convertAndSend("exchange1", "", JSON.toJSONString(msg)); + } + } + + + @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(); + } + this.messageService = WebSocketServer.applicationContext.getBean(MessageService.class); + this.rabbitTemplate = WebSocketServer.applicationContext.getBean(RabbitTemplate.class); + this.relationService = WebSocketServer.applicationContext.getBean(RelationService.class); + sessionMap.put(userId, session); + List unreadList = messageService.getUnreadMsg(userId); + for(Message msg : unreadList) { + session.getBasicRemote().sendText(JSON.toJSONString(msg)); + } + } + + @OnClose + public void onClose(CloseReason closeReason, Session session){ + sessionMap.remove(session.getId()); + } + + @OnError + public void onError(Throwable throwable) throws IOException { + throwable.printStackTrace(); + } + + public void sendToUser(Message msg) throws IOException, ParseException { + if (sessionMap.containsKey(msg.getToId())){ + sessionMap.get(msg.getToId()).getBasicRemote().sendText(JSON.toJSONString(msg)); + } + else { + messageService.insertUnreadMsg(msg.getToId(), msg); + } + msg.setChatId(messageService.getChatId(msg.getFromId(), msg.getToId())); + messageService.insertToMysql(msg); + messageService.insertToRedis(msg); + } + + public void sendToPublic(Message msg) throws IOException, ParseException { + for (Session session : sessionMap.values()) { + session.getBasicRemote().sendText(JSON.toJSONString(msg)); + } + msg.setChatId(messageService.getChatId(msg.getFromId(), msg.getToId())); + messageService.insertToMysql(msg); + messageService.insertToRedis(msg); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + WebSocketServer.applicationContext = applicationContext; + } + + @RabbitHandler + @RabbitListener(bindings = @QueueBinding( + value = @Queue(), + exchange = @Exchange(value = "exchange1",type = ExchangeTypes.FANOUT) + )) + public void sendMsg(String message) throws IOException, ParseException { + Message msg = JSON.parseObject(message, Message.class); + if (sessionMap.containsKey(msg.getToId())) { + sessionMap.get(msg.getToId()).getBasicRemote().sendText(JSON.toJSONString(msg)); + } + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java new file mode 100644 index 0000000..7da0f60 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/ChatId.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author Aurora + */ +@Data +@TableName("chatid") +public class ChatId { + @TableId(type = IdType.ASSIGN_ID) + private String id; + private String user1Id; + private String user2Id; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java new file mode 100644 index 0000000..11cb2e4 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Friend.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author Aurora + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("friend") +public class Friend { + private String user1Id; + private String user2Id; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java new file mode 100644 index 0000000..b31d876 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/FriendQuery.java @@ -0,0 +1,12 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +/** + * @author Aurora + */ +@Data +public class FriendQuery { + private String user1Id; + private String user2Id; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java new file mode 100644 index 0000000..8b6149e --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/HistoryQuery.java @@ -0,0 +1,16 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +/** + * @author Aurora + */ +@Data +public class HistoryQuery { + private String user1Id; + private String user2Id; + private int page; + private int size; + private String startDate; + private String endDate; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java new file mode 100644 index 0000000..d3c592f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/IgnoreUser.java @@ -0,0 +1,21 @@ +package com.ivmiku.tutorial.entity; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author Aurora + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("blacklist") +public class IgnoreUser { + @JSONField(ordinal = 1) + private String userId; + @JSONField(ordinal = 2) + private String toIgnore; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java new file mode 100644 index 0000000..e96f45a --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Message.java @@ -0,0 +1,25 @@ +package com.ivmiku.tutorial.entity; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Aurora + */ +@Data +@TableName("message") +public class Message implements Serializable { + @JSONField(ordinal = 1) + private String chatId; + @JSONField(ordinal = 2) + private String fromId; + @JSONField(ordinal = 3) + private String toId; + @JSONField(ordinal = 4) + private String message; + @JSONField(ordinal = 5) + private String date; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java new file mode 100644 index 0000000..60bccb5 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/SubUser.java @@ -0,0 +1,18 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +@Data +public class SubUser { + private String id; + private String username; + private String avatarUrl; + + public static SubUser setUser(User user) { + SubUser subUser = new SubUser(); + subUser.setId(user.getOpenid()); + subUser.setUsername(user.getNickname()); + subUser.setAvatarUrl(user.getAvatarUrl()); + return subUser; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java new file mode 100644 index 0000000..054070f --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/Subscribe.java @@ -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; +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java new file mode 100644 index 0000000..7d99648 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/BlackListMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.IgnoreUser; + +public interface BlackListMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java new file mode 100644 index 0000000..ec9ddaa --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/ChatIdMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.ChatId; + +public interface ChatIdMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java new file mode 100644 index 0000000..32ea471 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/FriendMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Friend; + +public interface FriendMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java new file mode 100644 index 0000000..b6d5ee1 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/MessageMapper.java @@ -0,0 +1,8 @@ +package com.ivmiku.tutorial.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ivmiku.tutorial.entity.Message; + +public interface MessageMapper extends BaseMapper { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java new file mode 100644 index 0000000..53d67c9 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/mapper/SubscribeMapper.java @@ -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 { + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java new file mode 100644 index 0000000..d7e3c88 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java @@ -0,0 +1,236 @@ +package com.ivmiku.tutorial.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ivmiku.tutorial.entity.ChatId; +import com.ivmiku.tutorial.entity.Message; +import com.ivmiku.tutorial.mapper.ChatIdMapper; +import com.ivmiku.tutorial.mapper.MessageMapper; +import com.ivmiku.tutorial.utils.RedisUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author Aurora + */ +@Service +public class MessageService { + @Autowired + private MessageMapper messageMapper; + + @Autowired + private ChatIdMapper chatIdMapper; + + @Autowired + private RedisUtil redisUtil; + + /** + * 获取会话id + * @param user1Id 用户1id + * @param user2Id 用户2id + * @return 查询结果 + */ + public String getChatId(String user1Id, String user2Id) { + if (Objects.equals(user1Id, "public") || Objects.equals(user2Id, "public")) { + return "0"; + } + String id1, id2; + if (user1Id.compareTo(user2Id) < 0) { + id1 = user1Id; + id2 = user2Id; + } else { + id1 = user2Id; + id2 = user1Id; + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user1_id", id1); + queryWrapper.eq("user2_id", id2); + ChatId chatId = chatIdMapper.selectOne(queryWrapper); + if (chatId == null) { + chatId = new ChatId(); + chatId.setUser1Id(id1); + chatId.setUser2Id(id2); + chatIdMapper.insert(chatId); + } + return chatIdMapper.selectOne(queryWrapper).getId(); + } + + /** + * 聊天记录写redis + * @param msg 要写入的信息 + * @throws ParseException + */ + @Async + public void insertToRedis(Message msg) throws ParseException { + if (!(msg.getMessage().length() >1000)) { + if (redisUtil.getZsetSize("history:" + msg.getChatId()) >= 50) { + redisUtil.zsetRightPop("history:" + msg.getChatId()); + } + redisUtil.zsetAdd("history:" + msg.getChatId(), msg); + redisUtil.setExpireTime("history:" + msg.getChatId()); + } + } + + /** + * 聊天记录写入mysql + * @param msg 要写入的消息 + */ + @Async + public void insertToMysql(Message msg) { + if (!(msg.getMessage().length() >1000)) { + messageMapper.insert(msg); + } + } + + /** + * 未读消息写入redis + * @param userId 用户id + * @param msg 未读消息 + */ + @Async + public void insertUnreadMsg(String userId, Message msg) { + redisUtil.listAdd("unread:" + userId, msg); + } + + /** + * 获取未读消息列表 + * @param userId 用户id + * @return 查询结果 + */ + public List getUnreadMsg(String userId) { + List result = redisUtil.listGet("unread:" + userId, 0, -1); + redisUtil.listClear(userId); + return result; + } + + /** + * 从数据库获取聊天记录 + * @param chatId 会话id + * @param current 分页参数 + * @param size 分页参数 + * @return 返回的查询结果 + */ + public List getChatHistoryFromDB(String chatId, int current, int size) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + Page page = new Page<>(current, size); + queryWrapper.eq("chat_id", chatId); + queryWrapper.orderByDesc("date"); + return messageMapper.selectPage(page, queryWrapper).getRecords(); + } + + /** + * 从数据库获取聊天记录,查询一定范围内 + * @param chatId 会话id + * @param current 分页参数 + * @param size 分页参数 + * @param startDate 开始日期 + * @param endDate 结束日期 + * @return 返回的查询结果 + */ + public List getChatHistoryFromDBByDate(String chatId, int current, int size, String startDate, String endDate) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.between("date", startDate, endDate); + Page page = new Page<>(current, size); + queryWrapper.eq("chat_id", chatId); + queryWrapper.orderByDesc("date"); + return messageMapper.selectPage(page, queryWrapper).getRecords(); + } + + /** + * redis获取聊天记录 + * @param chatId 会话id + * @param s 开始 + * @param e 结束 + * @return 查询结果 + */ + public List getChatHistoryFromRedis(String chatId, int s, int e) { + return redisUtil.zsetGet("history:" + chatId, s, e); + } + + /** + * 查询聊天记录 + * @param user1Id 用户1id + * @param user2Id 用户2id + * @param page 分页参数 + * @param size 分页参数 + * @return 查询结果 + * @throws ParseException + */ + public List getChatHistory(String user1Id, String user2Id, int page, int size) throws ParseException { + int start = page * size - size; + int end = page * size - 1; + String chatId = getChatId(user1Id, user2Id); + loadCache(chatId); + List result = new ArrayList<>(redisUtil.zsetGet("history:" + chatId, start, end)); + if ((end -start + 1) == result.size()) { + return result; + } + int redisSize = result.size(); + List dbList = getChatHistoryFromDB(chatId, ((end - result.size()) / size) + 1, size); + result.addAll(dbList.subList(redisSize, dbList.size())); + redisUtil.refreshExpire("history:" + chatId); + return result; + } + + /** + * 在一定时间范围内查询聊天记录 + * @param user1Id 用户1id + * @param user2Id 用户2id + * @param startDate 开始日期 + * @param endDate 结束日期 + * @param page 分页参数 + * @param size 分页参数 + * @return 查询结果 + * @throws ParseException + */ + public List getChatHistoryByDate(String user1Id, String user2Id, String startDate, String endDate, int page, int size) throws ParseException { + int start = page * size - size; + int end = page * size - 1; + String chatId = getChatId(user1Id, user2Id); + loadCache(chatId); + List result = new ArrayList<>(redisUtil.zsetGetByDate("history:" + chatId, startDate, endDate, start, size)); + redisUtil.refreshExpire("history:" + chatId); + if (result.size() == (end - start + 1)) { + return result; + } + int redisSize = result.size(); + List dbList = getChatHistoryFromDBByDate(chatId, ((end - result.size()) / size) + 1, size, startDate, endDate).subList(result.size(), size); + result.addAll(dbList.subList(redisSize, dbList.size())); + return result; + } + + /** + * 获取会话列表 + * @param userId 用户id + * @param current 分页参数 + * @param size 分页参数 + * @return 查询结果 + */ + public List getChatList(String userId, int current, int size) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user1_id", userId).or().eq("user2_id", userId); + queryWrapper.orderByDesc("id"); + Page page = new Page<>(current, size); + return chatIdMapper.selectPage(page, queryWrapper).getRecords(); + } + + /** + * 加载聊天记录到redis + * @param chatId 会话id + * @throws ParseException + */ + public void loadCache(String chatId) throws ParseException { + if (!redisUtil.ifExist("history:" + chatId)) { + List list = getChatHistoryFromDB(chatId, 1, 20); + for (Message message : list) { + insertToRedis(message); + } + } + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java new file mode 100644 index 0000000..8dc4bd3 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/RelationService.java @@ -0,0 +1,120 @@ +package com.ivmiku.tutorial.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import com.ivmiku.tutorial.entity.*; +import com.ivmiku.tutorial.mapper.BlackListMapper; +import com.ivmiku.tutorial.mapper.FriendMapper; +import com.ivmiku.tutorial.mapper.SubscribeMapper; +import com.ivmiku.tutorial.utils.RedisUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Aurora + */ +@Service +public class RelationService { + @Autowired + private BlackListMapper blackListMapper; + + @Autowired + private FriendMapper friendMapper; + + @Autowired + private RedisUtil redisUtil; + + @Autowired + private SubscribeMapper subscribeMapper; + + @Autowired + private UserService userService; + + /** + * 屏蔽用户 + * @param userId 用户id + * @param toIgnore 要屏蔽的用户id + */ + public void IgnoreUser(String userId, String toIgnore) { + blackListMapper.insert(new IgnoreUser(userId, toIgnore)); + if (redisUtil.ifExist("blacklist:" + userId)) { + redisUtil.listAdd("blacklist:" + userId, toIgnore); + } + } + + /** + * 查询用户是否屏蔽了该用户 + * @param userId 用户id + * @param ignoreId 要查询的id + * @return 查询结果 + */ + public boolean ifIgnored(String userId, String ignoreId) { + loadCache(userId); + List blackList = redisUtil.getStringList("blacklist:" + userId, 0, -1); + redisUtil.refreshExpire("blacklist:" + userId); + return blackList.contains(ignoreId); + } + + /** + * 加载缓存 + * @param userId 用户id + */ + public void loadCache(String userId) { + if (!redisUtil.ifExist("blacklist:" + userId)) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", userId); + List list = blackListMapper.selectList(queryWrapper); + List result = new ArrayList<>(); + if (list != null) { + for (IgnoreUser object : list) { + result.add(object.getToIgnore()); + } + } + for (String toIgnore : result) { + redisUtil.listAdd("blacklist:" + userId, toIgnore); + } + redisUtil.setExpireTime("blacklist:" + userId); + } + } + + public void subscribe(String id, String toId) { + Subscribe subscribe = new Subscribe(); + subscribe.setId(Long.valueOf(id)); + subscribe.setSubId(Long.valueOf(toId)); + subscribeMapper.insert(subscribe); + } + + public List getFanList(String userId, int page, int size) { + List list = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + Page pager = new Page<>(page, size); + queryWrapper.eq("sub_id", userId); + List array = subscribeMapper.selectPage(pager, queryWrapper).getRecords(); + for (Subscribe subscribe : array) { + String queryId = String.valueOf(subscribe.getId()); + User user = userService.selectUserById(queryId); + SubUser subUser = SubUser.setUser(user); + list.add(subUser); + } + return list; + } + + public List getSubList(String userId, int page, int size) { + List list = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + Page pager = new Page<>(page, size); + queryWrapper.eq("id", userId); + List array = subscribeMapper.selectPage(pager, queryWrapper).getRecords(); + for (Subscribe subscribe : array) { + String queryId = String.valueOf(subscribe.getSubId()); + User user = userService.selectUserById(queryId); + SubUser subUser = SubUser.setUser(user); + list.add(subUser); + } + return list; + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java new file mode 100644 index 0000000..86c6c77 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/UserService.java @@ -0,0 +1,16 @@ +package com.ivmiku.tutorial.service; + +import com.ivmiku.tutorial.entity.User; +import com.ivmiku.tutorial.mapper.UserMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +@Service +public class UserService { + @Resource + private UserMapper userMapper; + + public User selectUserById(String id) { + return userMapper.selectById(id); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java new file mode 100644 index 0000000..8430632 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/DateUtil.java @@ -0,0 +1,43 @@ +package com.ivmiku.tutorial.utils; + +import jakarta.annotation.PostConstruct; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +/** + * @author Aurora + */ +public class DateUtil { + /** + * 获取当前时间 + * @return 当前时间字符串 + */ + public static String getCurrentTime() { + Date date = new Date(); + SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return ft.format(date); + } + + /** + * 转换为时间戳 + * @param time 时间字符串 + * @return 时间戳 + * @throws ParseException + */ + public static long toTimeSig(String time) throws ParseException { + SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = ft.parse(time); + return date.getTime(); + } + + /** + * 设置当前时区GMT+8 + */ + @PostConstruct + public void setTimeZone() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + } +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java new file mode 100644 index 0000000..da73040 --- /dev/null +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/MessageUtil.java @@ -0,0 +1,36 @@ +package com.ivmiku.tutorial.utils; + +import com.ivmiku.tutorial.service.RelationService; +import org.springframework.stereotype.Component; + +/** + * 敏感词检测 + * @author Aurora + */ +@Component +public class MessageUtil { + private static final String[] SENSITIVE = {"你妈", "你妈逼的"}; + + private static RelationService relationService = null; + + public MessageUtil(RelationService relationService) { + MessageUtil.relationService = relationService; + } + + /** + * 查看发送的信息是否含有敏感词 + * @param message 要发送的信息 + * @return 检查结果 + */ + public static boolean checkMessage(String message) { + if (message != null) { + for(String keyword : SENSITIVE) { + if (message.contains(keyword)){ + return true; + } + } + } + return false; + } + +} diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java index 8ff2877..4f03f73 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java @@ -1,9 +1,18 @@ package com.ivmiku.tutorial.utils; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.Message; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; + /** * @author Aurora */ @@ -12,11 +21,97 @@ public class RedisUtil { @Autowired private RedisTemplate redisTemplate; - public void insertKey(String userId, String sessionKey) { - redisTemplate.opsForValue().set("sessionkey:" + userId, sessionKey); + public void listAdd(String key, Object value) { + redisTemplate.opsForList().leftPush(key, value); } - public String getKey(String userId) { - return (String) redisTemplate.opsForValue().get("sessionkey:" + userId); + public List listGet(String key, int s, int e) { + List list = redisTemplate.opsForList().range(key, s, e); + List result = new ArrayList<>(); + if (list != null) { + for (Object json : list) { + result.add(JSON.parseObject(JSON.toJSONString(json), Message.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 getKey() { + return redisTemplate.keys("history:*"); + } + + public Object rightPop(String key) { + return redisTemplate.opsForList().rightPop(key); + } + + public void zsetAdd(String key, Message value) throws ParseException { + redisTemplate.opsForZSet().add(key, value, DateUtil.toTimeSig(value.getDate())); + } + + public List zsetGet(String key, int s, int e) { + Set list = redisTemplate.opsForZSet().reverseRange(key, s, e); + List result = new ArrayList<>(); + if (list != null) { + for (Object json : list) { + result.add(JSON.parseObject(JSON.toJSONString(json), Message.class)); + } + } + return result; + } + + public Long getzsetSize(String key) { + return redisTemplate.opsForZSet().size(key); + } + + public List zsetGetByDate(String key, String startDate, String endDate, int offset, int count) throws ParseException { + Set list = redisTemplate.opsForZSet().reverseRangeByScore(key, DateUtil.toTimeSig(startDate), DateUtil.toTimeSig(endDate), offset, count); + List result = new ArrayList<>(); + if (list != null) { + for (Object json : list) { + result.add(JSON.parseObject(JSON.toJSONString(json), Message.class)); + } + } + return result; + } + + public Message zsetRightPop(String key) { + return JSON.parseObject(JSON.toJSONString(Objects.requireNonNull(redisTemplate.opsForZSet().popMin(key)).getValue()), Message.class); + } + + public Long getZsetSize(String key) { + return redisTemplate.opsForZSet().size(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 getStringList(String key, int s, int e) { + List list = redisTemplate.opsForList().range(key, s, e); + List result = new ArrayList<>(); + assert list != null; + for (Object object : list) { + result.add((String) object); + } + return result; } } From 8e659026f30aea0344c129f72a50003384594934 Mon Sep 17 00:00:00 2001 From: ivmiku <124345843+ivmiku@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:23:17 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E7=BC=93=E5=AD=98=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ivmiku/tutorial/utils/RedisUtil.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java index 4f03f73..3af4268 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java @@ -114,4 +114,12 @@ public class RedisUtil { } 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); + } } From 01d3823a02d235aa9569ee85d964d5ea3d00894e Mon Sep 17 00:00:00 2001 From: ivmiku <124345843+ivmiku@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:47:42 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E7=94=A8=E6=88=B7=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tutorial/controller/UserController.java | 27 ++++++++++++++++--- .../java/com/ivmiku/tutorial/entity/User.java | 4 +++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/UserController.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/UserController.java index f9aedfd..712db1f 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/controller/UserController.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/UserController.java @@ -2,6 +2,7 @@ package com.ivmiku.tutorial.controller; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import cn.binarywang.wx.miniapp.util.WxMaConfigHolder; import cn.dev33.satoken.stp.StpUtil; import com.alibaba.fastjson.JSONObject; @@ -12,7 +13,10 @@ import com.ivmiku.tutorial.response.Result; import com.ivmiku.tutorial.utils.RedisUtil; import jakarta.annotation.Resource; import me.chanjar.weixin.common.error.WxErrorException; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; @@ -29,11 +33,16 @@ public class UserController { private RedisUtil redisUtil; @GetMapping("/login") - public Object login(@RequestParam(name = "code") String code, @RequestParam(name = "rawdata") String rawData, @RequestParam(name = "signature") String signature -) { + public Object login(@RequestParam(name = "code") String code, + @RequestParam(name = "rawdata") String rawData, + @RequestParam(name = "signature") String signature, + @RequestParam(name = "encryptedData") String encryptedData, + @RequestParam(name = "iv") String iv) { WxMaJscode2SessionResult session; + WxMaUserInfo userInfo; try { session = wxMaService.getUserService().getSessionInfo(code); + userInfo = wxMaService.getUserService().getUserInfo(session.getSessionKey(), encryptedData, iv); } catch (WxErrorException e) { return JSON.toJSON(Result.error(e.getMessage())); } @@ -49,6 +58,8 @@ public class UserController { user.setOpenid(session.getOpenid()); user.setNickname(raw.getString("nickname")); user.setAvatarUrl(raw.getString("avatarUrl")); + user.setGender(raw.getString("gender")); + user.setAdmin(false); userMapper.insert(user); } map.put("token", StpUtil.getTokenValue()); @@ -56,4 +67,14 @@ public class UserController { WxMaConfigHolder.remove(); return JSON.toJSON(Result.ok(map)); } + + @GetMapping("/validate") + public Object validate() { + try { + StpUtil.checkLogin(); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + return Result.ok(); + } } diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/entity/User.java b/user-8072/src/main/java/com/ivmiku/tutorial/entity/User.java index 35dbcc2..ab3b4e3 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/entity/User.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/entity/User.java @@ -11,4 +11,8 @@ public class User { private String openid; private String nickname; private String avatarUrl; + private boolean isAdmin; + private String phoneNum; + private String birthday; + private String gender; } From be3c8728fb2a493e78a97f5ecc274bb0abdb6e54 Mon Sep 17 00:00:00 2001 From: ivmiku <124345843+ivmiku@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:01:22 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=E8=AF=AD=E9=9F=B3=E5=8A=A9?= =?UTF-8?q?=E6=89=8B=E6=96=B0=E5=A2=9E=E5=A4=9A=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AssistantController.java | 5 +-- .../tutorial/service/AssistantService.java | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java index c32bcee..8cd9a8d 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/AssistantController.java @@ -17,8 +17,9 @@ public class AssistantController { private AssistantService assistantService; @GetMapping("/response") - public Object getResponse(@RequestParam String input) { - Map map = assistantService.getResponse(input); + public Object getResponse(@RequestParam String input, @RequestParam int size, @RequestParam String language) { + String userInput = assistantService.speechRecognition(input, size, language); + Map map = assistantService.getResponse(userInput, language); if (map == null) { return Result.error("请求出错"); } diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java index c06c723..9da477c 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java @@ -34,10 +34,16 @@ public class AssistantService { private final String secretId = "AKID09INNYxYEFFJH3g9VhljVF3qbDiFdx50"; private final String secretKey = "KajjcNyNaaUCqQroqpzNoMtTHNj4Lbil"; - public Map getAiResponse(String userInput) { + public String getAiResponse(String userInput, String language) { Map message1 = new HashMap<>(); message1.put("role", "system"); - message1.put("content", "模仿语音助手,对用户的问题给出简短的回答"); + String prompt = "模仿语音助手,对用户的问题给出简短的回答"; + if ("Chinese".equals(language)) { + prompt += "用中文回答"; + } else if ("English".equals(language)) { + prompt += "用英文回答"; + } + message1.put("content", prompt); Map message2 = new HashMap<>(); message2.put("role", "user"); message2.put("content", userInput); @@ -59,10 +65,7 @@ public class AssistantService { } JSONArray choices = result.getJSONArray("choices"); JSONObject message = choices.getJSONObject(0); - JSONObject content = message.getJSONObject("message"); - Map map = new HashMap<>(); - map.put("content", content.get("content")); - return map; + return message.getString("message"); } public String textToSpeech(String content) { @@ -84,7 +87,7 @@ public class AssistantService { } } - public String speechRecognition(String content, Integer length) { + public String speechRecognition(String content, Integer length, String language) { try{ Credential cred = new Credential(secretId, secretKey); HttpProfile httpProfile = new HttpProfile(); @@ -93,7 +96,11 @@ public class AssistantService { clientProfile.setHttpProfile(httpProfile); AsrClient client = new AsrClient(cred, "", clientProfile); SentenceRecognitionRequest req = new SentenceRecognitionRequest(); - req.setEngSerViceType("16k_zh"); + if ("Chinese".equals(language)) { + req.setEngSerViceType("16k_zh"); + } else if ("English".equals(language)) { + req.setEngSerViceType("16k_en"); + } req.setSourceType(1L); req.setVoiceFormat("wav"); req.setData(content); @@ -143,15 +150,16 @@ public class AssistantService { return String.valueOf(message.getJSONObject("message")); } - public Map getResponse(String query) { + public Map getResponse(String query, String language) { Map result = new HashMap<>(); String tag = extractTag(query); String content; content = searchGuidance(tag); - if (content != null) { - result.put("content", content); - return result; + if (content == null) { + content = getAiResponse(query, language); } - return getAiResponse(query); + Map map = new HashMap<>(); + map.put("content", textToSpeech(content)); + return map; } } From e6048a8568a1bdedfddc3ab81c394bec3b42e942 Mon Sep 17 00:00:00 2001 From: ivmiku <124345843+ivmiku@users.noreply.github.com> Date: Wed, 28 Aug 2024 23:14:52 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix:=E5=88=86=E5=B8=83=E5=BC=8F=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E4=B8=8B=E7=9A=84websocket=E9=80=9A=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tutorial/service/AssistantService.java | 4 ++-- .../tutorial/controller/WebSocketServer.java | 11 ++++------- .../tutorial/service/MessageService.java | 18 +++++++++++++++--- .../com/ivmiku/tutorial/utils/RedisUtil.java | 5 +++++ .../main/resources/application-dev.properties | 6 ++++-- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java index 9da477c..da0e312 100644 --- a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/AssistantService.java @@ -39,9 +39,9 @@ public class AssistantService { message1.put("role", "system"); String prompt = "模仿语音助手,对用户的问题给出简短的回答"; if ("Chinese".equals(language)) { - prompt += "用中文回答"; + prompt += ",用中文回答"; } else if ("English".equals(language)) { - prompt += "用英文回答"; + prompt += ",用英文回答"; } message1.put("content", prompt); Map message2 = new HashMap<>(); diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java b/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java index 993c05f..3f27ac6 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/controller/WebSocketServer.java @@ -11,11 +11,7 @@ import jakarta.websocket.*; import jakarta.websocket.server.PathParam; import jakarta.websocket.server.ServerEndpoint; import org.springframework.amqp.core.ExchangeTypes; -import org.springframework.amqp.rabbit.annotation.Exchange; -import org.springframework.amqp.rabbit.annotation.Queue; -import org.springframework.amqp.rabbit.annotation.QueueBinding; -import org.springframework.amqp.rabbit.annotation.RabbitHandler; -import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.annotation.*; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; @@ -28,7 +24,6 @@ import java.text.ParseException; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import static jakarta.websocket.CloseReason.CloseCodes.CLOSED_ABNORMALLY; @@ -70,6 +65,7 @@ public class WebSocketServer implements ApplicationContextAware { if (relationService.ifIgnored(msg.getToId(), msg.getFromId())) { session.getBasicRemote().sendText("您已被对方屏蔽"); } else { + messageService.insertMessage(msg); rabbitTemplate.convertAndSend("exchange1", "", JSON.toJSONString(msg)); } } @@ -133,10 +129,11 @@ public class WebSocketServer implements ApplicationContextAware { value = @Queue(), exchange = @Exchange(value = "exchange1",type = ExchangeTypes.FANOUT) )) - public void sendMsg(String message) throws IOException, ParseException { + public void sendMsg(String message) throws IOException { Message msg = JSON.parseObject(message, Message.class); if (sessionMap.containsKey(msg.getToId())) { sessionMap.get(msg.getToId()).getBasicRemote().sendText(JSON.toJSONString(msg)); + messageService.deleteMessage(msg); } } } diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java b/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java index d7e3c88..779c1d5 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/service/MessageService.java @@ -104,9 +104,12 @@ public class MessageService { * @return 查询结果 */ public List getUnreadMsg(String userId) { - List result = redisUtil.listGet("unread:" + userId, 0, -1); - redisUtil.listClear(userId); - return result; + if (redisUtil.ifExist("unread:" + userId)) { + List result = redisUtil.listGet("unread:" + userId, 0, -1); + redisUtil.listClear("unread:" + userId); + return result; + } + return new ArrayList<>(); } /** @@ -233,4 +236,13 @@ public class MessageService { } } } + + public void insertMessage(Message message) { + String id = message.getToId(); + redisUtil.listAdd("unread:" + id, message); + } + + public void deleteMessage(Message message) { + redisUtil.deleteFromList(message); + } } diff --git a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java index 3af4268..fb0c172 100644 --- a/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java +++ b/user-8072/src/main/java/com/ivmiku/tutorial/utils/RedisUtil.java @@ -122,4 +122,9 @@ public class RedisUtil { public String getKey(String userId) { return (String) redisTemplate.opsForValue().get("sessionkey:" + userId); } + + public void deleteFromList(Message message) { + String id = message.getToId(); + redisTemplate.opsForList().remove("unread:" + id, 0, message); + } } diff --git a/user-8072/src/main/resources/application-dev.properties b/user-8072/src/main/resources/application-dev.properties index 90fc9fb..449d2b6 100644 --- a/user-8072/src/main/resources/application-dev.properties +++ b/user-8072/src/main/resources/application-dev.properties @@ -11,8 +11,10 @@ server.port=8072 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root -spring.datasource.password=123456 +spring.datasource.password=12345abcde spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&ServerTimezone=Asia/Shanghai -dubbo.application.qos-enable=false \ No newline at end of file +dubbo.application.qos-enable=false + +spring.rabbitmq.port=5672 \ No newline at end of file