Prechádzať zdrojové kódy

消息服务加redis,修改表结构,完成收到ws消息时的逻辑

nnkwrik 6 rokov pred
rodič
commit
64e57a7195
25 zmenil súbory, kde vykonal 450 pridanie a 83 odobranie
  1. 1 0
      .gitignore
  2. 5 1
      common/src/main/java/io/github/nnkwrik/common/dto/Response.java
  3. 19 0
      common/src/main/java/io/github/nnkwrik/common/exception/GlobalException.java
  4. 7 0
      common/src/main/java/io/github/nnkwrik/common/exception/GlobalExceptionHandler.java
  5. 6 3
      common/src/main/java/io/github/nnkwrik/common/util/JsonUtil.java
  6. 5 0
      dev/redis/start.sh
  7. 9 0
      im-service/pom.xml
  8. 16 7
      im-service/src/main/java/io/github/nnkwrik/imservice/controller/TestController.java
  9. 39 0
      im-service/src/main/java/io/github/nnkwrik/imservice/dao/ChatMapper.java
  10. 10 7
      im-service/src/main/java/io/github/nnkwrik/imservice/dao/HistoryMapper.java
  11. 0 25
      im-service/src/main/java/io/github/nnkwrik/imservice/dao/UserMapper.java
  12. 5 3
      im-service/src/main/java/io/github/nnkwrik/imservice/model/po/Chat.java
  13. 4 5
      im-service/src/main/java/io/github/nnkwrik/imservice/model/po/History.java
  14. 15 0
      im-service/src/main/java/io/github/nnkwrik/imservice/model/po/LastChat.java
  15. 3 5
      im-service/src/main/java/io/github/nnkwrik/imservice/model/vo/WsMessage.java
  16. 30 0
      im-service/src/main/java/io/github/nnkwrik/imservice/redis/RedisClient.java
  17. 72 0
      im-service/src/main/java/io/github/nnkwrik/imservice/redis/RedisConfig.java
  18. 1 1
      im-service/src/main/java/io/github/nnkwrik/imservice/service/WebSocketService.java
  19. 98 16
      im-service/src/main/java/io/github/nnkwrik/imservice/service/impl/WebSocketServiceImpl.java
  20. 21 9
      im-service/src/main/java/io/github/nnkwrik/imservice/websocket/ChatEndpoint.java
  21. 27 0
      im-service/src/main/java/io/github/nnkwrik/imservice/websocket/ChatEndpointConfigure.java
  22. 6 1
      im-service/src/main/java/io/github/nnkwrik/imservice/websocket/WebSocketConfig.java
  23. 4 0
      im-service/src/main/resources/application.yml
  24. 8 0
      im-service/src/main/resources/banner.txt
  25. 39 0
      im-service/src/test/java/io/github/nnkwrik/imservice/dao/TestChatMapper.java

+ 1 - 0
.gitignore

@@ -13,6 +13,7 @@
 # other
 dev/mysql/data/*
 dev/mysql/log/*
+dev/redis/log/*
 auth-service/src/main/resources/application-secret.yml
 **/*.key
 **/*.pub

+ 5 - 1
common/src/main/java/io/github/nnkwrik/common/dto/Response.java

@@ -23,7 +23,11 @@ public class Response<T> {
     public static final int SELLER_AND_GOODS_IS_NOT_MATCH = 4004;
 
     //user
-    public static final int USER_IS_NOT_EXIST = 3001;
+    public static final int USER_IS_NOT_EXIST = 2001;
+
+    //im
+    public static final int MESSAGE_FORMAT_IS_WRONG = 5001;
+    public static final int MESSAGE_IS_INCOMPLETE = 5002;
 
     private int errno;
     private String errmsg;

+ 19 - 0
common/src/main/java/io/github/nnkwrik/common/exception/GlobalException.java

@@ -0,0 +1,19 @@
+package io.github.nnkwrik.common.exception;
+
+import lombok.Data;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/06 9:15
+ */
+@Data
+public class GlobalException extends Exception {
+    private int errno;
+    private String errmsg;
+
+
+    public GlobalException(int errno, String errmsg) {
+        this.errno = errno;
+        this.errmsg = errmsg;
+    }
+}

+ 7 - 0
common/src/main/java/io/github/nnkwrik/common/exception/GlobalExceptionHandler.java

@@ -14,6 +14,13 @@ import org.springframework.web.bind.annotation.ResponseBody;
 @Slf4j
 public class GlobalExceptionHandler {
 
+    @ResponseBody
+    @ExceptionHandler(GlobalException.class)
+    public Object handleJWTException(GlobalException e) {
+        log.info("发生异常,errno = {},errmsg = {}", e.getErrno(), e.getErrmsg());
+        return Response.fail(e.getErrno(), e.getErrmsg());
+    }
+
     @ResponseBody
     @ExceptionHandler(JWTException.class)
     public Object handleJWTException(JWTException e) {

+ 6 - 3
common/src/main/java/io/github/nnkwrik/common/util/JsonUtil.java

@@ -1,5 +1,6 @@
 package io.github.nnkwrik.common.util;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -14,7 +15,8 @@ import java.util.Map;
 public class JsonUtil {
 
     public static TypeReference<Map<String, String>> simpleJsonMap =
-            new TypeReference<Map<String, String>>(){};
+            new TypeReference<Map<String, String>>() {
+            };
 
     public static Map<String, String> fromJson(String rawData, TypeReference typeReference) {
         try {
@@ -37,9 +39,10 @@ public class JsonUtil {
         return null;
     }
 
-    public static String toJson(Object object){
+    public static String toJson(Object object) {
 
-            ObjectMapper mapper = new ObjectMapper();
+        ObjectMapper mapper = new ObjectMapper()
+                .setSerializationInclusion(JsonInclude.Include.NON_NULL);
         try {
             return mapper.writeValueAsString(object);
         } catch (JsonProcessingException e) {

+ 5 - 0
dev/redis/start.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+cur_dir=`pwd`
+docker stop fangxianyu-redis
+docker rm fangxianyu-redis
+docker run -idt --name fangxianyu-redis -v ${cur_dir}/data:/data -p 6379:6379 redis:3.2

+ 9 - 0
im-service/pom.xml

@@ -41,6 +41,15 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>

+ 16 - 7
im-service/src/main/java/io/github/nnkwrik/imservice/controller/TestController.java

@@ -1,9 +1,8 @@
 package io.github.nnkwrik.imservice.controller;
 
-import io.github.nnkwrik.imservice.websocket.WebSocket;
+import io.github.nnkwrik.imservice.service.WebSocketService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 /**
@@ -12,11 +11,21 @@ import org.springframework.web.bind.annotation.RestController;
  */
 @RestController
 public class TestController {
+//    @Autowired
+//    private WebSocket webSocket;
+
     @Autowired
-    private WebSocket webSocket;
+    private WebSocketService webSocketService;
+
+//    @RequestMapping("/testsend/{openId}")
+//    public void testsend(@PathVariable("openId") String openId) {
+//        webSocket.sendMessage(openId, Response.ok("success to send"));
+//    }
 
-    @RequestMapping("/testsend/{openId}")
-    public void testsend(@PathVariable("openId") String openId){
-        webSocket.sendMessage(openId,"success to send");
+    @GetMapping("/testNull")
+    public String testNull() {
+        return "webSocketService == null?true:false " + (webSocketService == null ? true : false);
     }
+
+
 }

+ 39 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/dao/ChatMapper.java

@@ -0,0 +1,39 @@
+package io.github.nnkwrik.imservice.dao;
+
+import io.github.nnkwrik.imservice.model.po.Chat;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectKey;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 21:54
+ */
+@Mapper
+public interface ChatMapper {
+//    @Select("select id, u1, u2, unread_count\n" +
+//            "from chat_user\n" +
+//            "where ((u1 = #{open_id} and u1_to_u2 = false) or (u2 = #{open_id} and u1_to_u2 = true))\n" +
+//            "  and unread_count > 0")
+//    Chat getUserUnreadChat(@Param("open_id") String openId);
+
+//    @Select("select unread_count from chat_user where u1=#{u1} and u2=#{u2}")
+//    Integer getUnreadCountByChat(@Param("u1") String u1Id, @Param("u2") String u2Id);
+
+
+//    Integer getUnreadCount(@Param("u1") String u1Id, @Param("u2") String u2Id);
+
+    @Select("select id\n" +
+            "from chat\n" +
+            "where u1 = #{u1}\n" +
+            "  and u2 = #{u2}\n" +
+            "  and goods_id = #{goods_id}")
+    Integer getChatId(@Param("u1") String u1, @Param("u2") String u2, @Param("goods_id") int goodsId);
+
+
+    @Select("insert into chat (u1, u2, goods_id)\n" +
+            "values (#{u1}, #{u2}, #{goodsId})")
+    @SelectKey(resultType = Integer.class, before = false, keyProperty = "id", statement = "SELECT LAST_INSERT_ID()")
+    void addChat(Chat chat);
+}

+ 10 - 7
im-service/src/main/java/io/github/nnkwrik/imservice/dao/HistoryMapper.java

@@ -1,6 +1,6 @@
 package io.github.nnkwrik.imservice.dao;
 
-import io.github.nnkwrik.imservice.model.po.ChatHistory;
+import io.github.nnkwrik.imservice.model.po.History;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -11,10 +11,13 @@ import org.apache.ibatis.annotations.Select;
  */
 @Mapper
 public interface HistoryMapper {
-    @Select("select message_type,hint,message_body,create_time\n" +
-            "from chat_history\n" +
-            "where chat_user_id = 1\n" +
-            "ORDER BY create_time DESC\n" +
-            "LIMIT 1")
-    ChatHistory getMostRecentByChatId(@Param("chat_user_id")Integer chatUserId);
+    @Select("insert into history (chat_id, u1_to_u2, message_type, message_body, send_time)\n" +
+            "values (#{chatId}, #{u1ToU2}, #{messageType}, #{messageBody}, #{sendTime});")
+    void addHistory(History history);
+//    @Select("select message_type,hint,message_body,create_time\n" +
+//            "from chat_history\n" +
+//            "where chat_user_id = 1\n" +
+//            "ORDER BY create_time DESC\n" +
+//            "LIMIT 1")
+//    History getMostRecentByChatId(@Param("chat_user_id")Integer chatUserId);
 }

+ 0 - 25
im-service/src/main/java/io/github/nnkwrik/imservice/dao/UserMapper.java

@@ -1,25 +0,0 @@
-package io.github.nnkwrik.imservice.dao;
-
-import io.github.nnkwrik.imservice.model.po.ChatUser;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
-
-/**
- * @author nnkwrik
- * @date 18/12/05 21:54
- */
-@Mapper
-public interface UserMapper {
-//    @Select("select id, u1, u2, unread_count\n" +
-//            "from chat_user\n" +
-//            "where ((u1 = #{open_id} and u1_to_u2 = false) or (u2 = #{open_id} and u1_to_u2 = true))\n" +
-//            "  and unread_count > 0")
-//    ChatUser getUserUnreadChat(@Param("open_id") String openId);
-
-    @Select("select unread_count from chat_user where u1=#{u1} and u2=#{u2}")
-    Integer getUnreadCountByChat(@Param("u1") String u1Id, @Param("u2") String u2Id);
-
-
-//    Integer getUnreadCount(@Param("u1") String u1Id, @Param("u2") String u2Id);
-}

+ 5 - 3
im-service/src/main/java/io/github/nnkwrik/imservice/model/po/ChatUser.java → im-service/src/main/java/io/github/nnkwrik/imservice/model/po/Chat.java

@@ -7,10 +7,12 @@ import lombok.Data;
  * @date 18/12/05 21:19
  */
 @Data
-public class ChatUser {
+public class Chat {
     private Integer id;
     private String u1;   //u1 < u2
     private String u2;
-    private Boolean u1ToU2; //指最后一条信息
-    private Integer unreadCount;
+    private Integer goodsId;
+
+    private Boolean showToU1;
+    private Boolean showToU2;
 }

+ 4 - 5
im-service/src/main/java/io/github/nnkwrik/imservice/model/po/ChatHistory.java → im-service/src/main/java/io/github/nnkwrik/imservice/model/po/History.java

@@ -9,12 +9,11 @@ import java.util.Date;
  * @date 18/12/05 21:23
  */
 @Data
-public class ChatHistory {
+public class History {
     private Integer id;
-    private Integer chatUserId;
+    private Integer chatId;
     private Boolean u1ToU2;
-    private Integer messageType;    //0:系统消息,1.用户消息
-    private String hint;            //相关的商品id等
+    private Integer messageType;    //0:系统消息,1.用户消息,2.建立连接(u1点开了u2但没发消息, u1ToU2 = false,type = )
     private String messageBody;
-    private Date createTime;
+    private Date sendTime;
 }

+ 15 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/model/po/LastChat.java

@@ -0,0 +1,15 @@
+package io.github.nnkwrik.imservice.model.po;
+
+import io.github.nnkwrik.imservice.model.vo.WsMessage;
+import lombok.Data;
+
+/**
+ * 存入redis,展示最后一条信息的内容
+ * @author nnkwrik
+ * @date 18/12/06 10:02
+ */
+@Data
+public class LastChat {
+    private Integer unreadCount;
+    private WsMessage lastMsg;
+}

+ 3 - 5
im-service/src/main/java/io/github/nnkwrik/imservice/model/vo/WsMessage.java

@@ -3,6 +3,7 @@ package io.github.nnkwrik.imservice.model.vo;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 
+import java.io.Serializable;
 import java.util.Date;
 
 /**
@@ -11,16 +12,13 @@ import java.util.Date;
  */
 @Data
 public class WsMessage {
-    private Integer chatUserId;
     private String senderId;
     private String receiverId;
-    private Integer unreadCount;
-    private Integer totalUnreadCount;
+    private Integer goodsId;
 
     private Integer messageType;    //0:系统消息,1.用户消息
-    private String hint;
     private String messageBody;
 
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", locale = "CHINA", timezone = "Asia/Shanghai")
-    private Date createTime;
+    private Date sendTime;
 }

+ 30 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/redis/RedisClient.java

@@ -0,0 +1,30 @@
+package io.github.nnkwrik.imservice.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/06 15:08
+ */
+@Component
+public class RedisClient {
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+
+    public <T> T hget(String key, String field) {
+        return (T) redisTemplate.opsForHash().get(key, field);
+    }
+
+    public void hset(String key, String field, Object value) {
+        redisTemplate.opsForHash().put(key, field, value);
+    }
+
+    public <T> List<T> hvals(String key) {
+        return redisTemplate.opsForHash().values(key);
+    }
+}

+ 72 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/redis/RedisConfig.java

@@ -0,0 +1,72 @@
+package io.github.nnkwrik.imservice.redis;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+
+import java.time.Duration;
+
+/**
+ * Redis缓存配置类
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport {
+
+    @Value("${spring.redis.host}")
+    private String host;
+    @Value("${spring.redis.port}")
+    private int port;
+    @Value("${spring.redis.timeout}")
+    private Duration timeout;
+
+    //缓存管理器
+    @Bean
+    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
+        //设置缓存过期时间
+        Duration expiration = Duration.ofSeconds(10000);
+        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
+                .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(expiration)).build();
+        return cacheManager;
+    }
+
+    @Bean
+    public JedisConnectionFactory redisConnectionFactory() {
+        JedisConnectionFactory factory = new JedisConnectionFactory();
+        factory.setHostName(host);
+        factory.setPort(port);
+        factory.setTimeout(Math.toIntExact(timeout.toMillis()));
+        return factory;
+    }
+
+    @Bean
+    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
+        StringRedisTemplate template = new StringRedisTemplate(factory);
+        setSerializer(template);//设置序列化工具
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    private void setSerializer(StringRedisTemplate template){
+        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+        ObjectMapper om = new ObjectMapper();
+        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        jackson2JsonRedisSerializer.setObjectMapper(om);
+        template.setValueSerializer(jackson2JsonRedisSerializer);
+        template.setHashValueSerializer(jackson2JsonRedisSerializer);
+    }
+}

+ 1 - 1
im-service/src/main/java/io/github/nnkwrik/imservice/service/WebSocketService.java

@@ -5,5 +5,5 @@ package io.github.nnkwrik.imservice.service;
  * @date 18/12/05 12:28
  */
 public interface WebSocketService {
-    void sendMessage(String openId, String message);
+    void OnMessage(String senderId, String message);
 }

+ 98 - 16
im-service/src/main/java/io/github/nnkwrik/imservice/service/impl/WebSocketServiceImpl.java

@@ -1,50 +1,132 @@
 package io.github.nnkwrik.imservice.service.impl;
 
+import io.github.nnkwrik.common.dto.Response;
+import io.github.nnkwrik.common.exception.GlobalException;
 import io.github.nnkwrik.common.util.JsonUtil;
+import io.github.nnkwrik.imservice.dao.ChatMapper;
 import io.github.nnkwrik.imservice.dao.HistoryMapper;
-import io.github.nnkwrik.imservice.dao.UserMapper;
+import io.github.nnkwrik.imservice.model.po.Chat;
+import io.github.nnkwrik.imservice.model.po.History;
+import io.github.nnkwrik.imservice.model.po.LastChat;
 import io.github.nnkwrik.imservice.model.vo.WsMessage;
+import io.github.nnkwrik.imservice.redis.RedisClient;
 import io.github.nnkwrik.imservice.service.WebSocketService;
-import io.github.nnkwrik.imservice.websocket.WebSocket;
+import io.github.nnkwrik.imservice.websocket.ChatEndpoint;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.Date;
 
 /**
  * @author nnkwrik
  * @date 18/12/05 12:30
  */
 @Service
+@Slf4j
 public class WebSocketServiceImpl implements WebSocketService {
     @Autowired
-    private WebSocket webSocket;
+    private ChatEndpoint chatEndpoint;
 
     @Autowired
-    private UserMapper userMapper;
+    private ChatMapper chatMapper;
 
     @Autowired
     private HistoryMapper historyMapper;
 
-    @Override
-    public void sendMessage(String receiverId, String message) {
-        WsMessage wsMessage = JsonUtil.fromJson(message,WsMessage.class);
+    @Autowired
+    private RedisClient redisClient;
 
-        Integer unreadCount;
-        if (wsMessage.getSenderId().compareTo(wsMessage.getReceiverId())>0){
-            unreadCount = userMapper.getUnreadCountByChat(wsMessage.getReceiverId(),wsMessage.getSenderId());
-        }else {
-            unreadCount = userMapper.getUnreadCountByChat(wsMessage.getSenderId(),wsMessage.getReceiverId());
+    @Override
+    public void OnMessage(String senderId, String rawData) {
+        WsMessage message = null;
+        try {
+            message = createWsMessage(rawData);
+        } catch (GlobalException e) {
+            chatEndpoint.sendMessage(senderId, Response.fail(e.getErrno(), e.getErrmsg()));
+            return;
         }
-        unreadCount++;
 
-        if (webSocket.hasConnect(receiverId)){
-            wsMessage.setUnreadCount(unreadCount);
-            webSocket.sendMessage(receiverId,JsonUtil.toJson(wsMessage));
+        //如果接收方在线,转发ws消息到接收方
+        if (chatEndpoint.hasConnect(message.getReceiverId())) {
+            chatEndpoint.sendMessage(message.getReceiverId(), Response.ok(message));
         }
 
+        //更新redis
+        updateRedis(message);
         //更新数据库
+        updateSQL(message);
+    }
 
+    private void updateRedis(WsMessage message) {
+        LastChat lastChat = redisClient.hget(message.getReceiverId(), message.getGoodsId()+"");
+        if (lastChat != null) {
+            lastChat.setUnreadCount(lastChat.getUnreadCount() + 1);
+            lastChat.setLastMsg(message);
+        } else {
+            lastChat = new LastChat();
+            lastChat.setUnreadCount(1);
+            lastChat.setLastMsg(message);
+        }
+        redisClient.hset(message.getReceiverId(), message.getGoodsId()+"", lastChat);
+    }
 
+    private void updateSQL(WsMessage message) {
+        String u1 = null;
+        String u2 = null;
+        if (message.getSenderId().compareTo(message.getReceiverId()) > 0) {
+            u1 = message.getReceiverId();
+            u2 = message.getSenderId();
+        } else {
+            u1 = message.getSenderId();
+            u2 = message.getReceiverId();
+        }
 
+        //取chatid
+        Integer chatId = chatMapper.getChatId(u1, u2, message.getGoodsId());
+        if (chatId == null) {
+            Chat chat = new Chat();
+            chat.setU1(u1);
+            chat.setU2(u2);
+            chat.setGoodsId(message.getGoodsId());
+            chatMapper.addChat(chat);
+            chatId = chat.getId();
+        }
+
+
+        //添加聊天记录
+        History history = new History();
+        BeanUtils.copyProperties(message, history);
+        history.setChatId(chatId);
+        boolean u1ToU2 = u1.equals(message.getSendTime()) ? true : false;
+        history.setU1ToU2(u1ToU2);
+        historyMapper.addHistory(history);
+    }
+
+    private WsMessage createWsMessage(String rawData) throws GlobalException {
+        WsMessage wsMessage = JsonUtil.fromJson(rawData, WsMessage.class);
+        if (wsMessage == null) {
+            String msg = "消息反序列化失败";
+            log.info(msg);
+            throw new GlobalException(Response.MESSAGE_FORMAT_IS_WRONG, msg);
+        }
+        if (StringUtils.isEmpty(wsMessage.getSenderId()) ||
+                StringUtils.isEmpty(wsMessage.getReceiverId()) ||
+                ObjectUtils.isEmpty(wsMessage.getGoodsId()) ||
+                ObjectUtils.isEmpty(wsMessage.getMessageType()) ||
+                ObjectUtils.isEmpty(wsMessage.getMessageBody())) {
+            String msg = "消息不完整";
+            log.info(msg);
+            throw new GlobalException(Response.MESSAGE_IS_INCOMPLETE, msg);
+        }
+
+        if (wsMessage.getSendTime() == null) {
+            wsMessage.setSendTime(new Date());
+        }
+        return wsMessage;
     }
 
 }

+ 21 - 9
im-service/src/main/java/io/github/nnkwrik/imservice/websocket/WebSocket.java → im-service/src/main/java/io/github/nnkwrik/imservice/websocket/ChatEndpoint.java

@@ -1,6 +1,10 @@
 package io.github.nnkwrik.imservice.websocket;
 
+import io.github.nnkwrik.common.dto.Response;
+import io.github.nnkwrik.common.util.JsonUtil;
+import io.github.nnkwrik.imservice.service.WebSocketService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import javax.websocket.OnClose;
@@ -18,9 +22,12 @@ import java.util.concurrent.ConcurrentMap;
  * @date 18/12/05 11:34
  */
 @Component
-@ServerEndpoint("/im/{openId}")
+@ServerEndpoint(value = "/ws/{openId}", configurator = ChatEndpointConfigure.class)
 @Slf4j
-public class WebSocket {
+public class ChatEndpoint {
+
+    @Autowired
+    private WebSocketService webSocketService;
 
     private static ConcurrentMap<String, Session> sessionMap = new ConcurrentHashMap<>();
 
@@ -37,22 +44,27 @@ public class WebSocket {
     }
 
     @OnMessage
-    public void onMessage(@PathParam("openId") String openId, String message) {
-        log.info("【websocket消息】收到客户端发来的消息:openId = [{}],消息内容 = [{}]", openId, message);
+    public void onMessage(@PathParam("openId") String sender, String message) {
+        log.info("【websocket消息】收到客户端发来的消息:发送者 = [{}],消息内容 = [{}]", sender, message);
+        if (webSocketService == null) {
+            log.info("webSocketService为空");
+        }
+        webSocketService.OnMessage(sender, message);
     }
 
-    public boolean sendMessage(String openId, String message) {
+    public boolean sendMessage(String openId, Response response) {
         Session session = sessionMap.get(openId);
+
         if (session == null) {
-            log.info("消息发送失败,不存在该session:openId = [{}],消息内容 = [{}]", openId, message);
+            log.info("消息发送失败,不存在该session:openId = [{}],消息内容 = [{}]", openId, response);
             return false;
         } else {
             try {
-                session.getBasicRemote().sendText(message);
-                log.info("消息发送成功:openId = [{}],消息内容 = [{}]", openId, message);
+                session.getBasicRemote().sendText(JsonUtil.toJson(response));
+                log.info("消息发送成功:openId = [{}],消息内容 = [{}]", openId, response);
                 return true;
             } catch (IOException e) {
-                log.info("消息发送失败:openId = [{}],消息内容 = [{}]", openId, message);
+                log.info("消息发送失败:openId = [{}],消息内容 = [{}]", openId, response);
                 e.printStackTrace();
                 return false;
             }

+ 27 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/websocket/ChatEndpointConfigure.java

@@ -0,0 +1,27 @@
+package io.github.nnkwrik.imservice.websocket;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import javax.websocket.server.ServerEndpointConfig;
+
+/**不自定义就无法在ChatEndpoint中autowire spring的Bean
+ * @author nnkwrik
+ * @date 18/12/06 20:34
+ */
+public class ChatEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
+    private static volatile BeanFactory context;
+
+    @Override
+    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
+        return context.getBean(clazz);
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        System.out.println("auto load" + this.hashCode());
+        ChatEndpointConfigure.context = applicationContext;
+    }
+}

+ 6 - 1
im-service/src/main/java/io/github/nnkwrik/imservice/config/WebSocketConfig.java → im-service/src/main/java/io/github/nnkwrik/imservice/websocket/WebSocketConfig.java

@@ -1,4 +1,4 @@
-package io.github.nnkwrik.imservice.config;
+package io.github.nnkwrik.imservice.websocket;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -15,4 +15,9 @@ public class WebSocketConfig {
     public ServerEndpointExporter serverEndpointExporter() {
         return new ServerEndpointExporter();
     }
+
+    @Bean
+    public ChatEndpointConfigure newConfigure() {
+        return new ChatEndpointConfigure();
+    }
 }

+ 4 - 0
im-service/src/main/resources/application.yml

@@ -10,6 +10,10 @@ spring:
     username: root
     password: 1234
     driver-class-name: com.mysql.cj.jdbc.Driver
+  redis:
+    port: 6379
+    host: localhost
+    timeout: 30s
 #  jackson:
 #    default-property-inclusion: non_null  #如果值为null,构造json时不加入
 #    date-format: yyyy-MM-dd HH:mm    #指定Json中Date对象的传输格式.对于DTO还是使用以往的方式

+ 8 - 0
im-service/src/main/resources/banner.txt

@@ -0,0 +1,8 @@
+   __   __  __  ____      __      ___
+ /'_ `\/\ \/\ \/\_ ,`\  /'__`\   / __`\
+/\ \L\ \ \ \_\ \/_/  /_/\ \L\.\_/\ \L\ \
+\ \____ \ \____/ /\____\ \__/.\_\ \____/
+ \/___L\ \/___/  \/____/\/__/\/_/\/___/
+   /\____/
+   \_/__/     ${AnsiColor.YELLOW}:: 一款仿闲鱼开源交易平台 ::
+             ${AnsiColor.BLUE}GitHub : nnkwrik/fangxianyu

+ 39 - 0
im-service/src/test/java/io/github/nnkwrik/imservice/dao/TestChatMapper.java

@@ -0,0 +1,39 @@
+package io.github.nnkwrik.imservice.dao;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/06 16:06
+ */
+@RunWith(SpringRunner.class)
+//@SpringBootTest <-ServerEndpointExporter会报错
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class TestChatMapper {
+
+    @Autowired
+    private ChatMapper chatMapper;
+
+    @Test
+    public void testGetChatId(){
+        String u1 = "1";
+        String u2 = "3";
+        int goodsId = 0;
+
+        //exist
+        Integer chatId = chatMapper.getChatId(u1, u2, goodsId);
+        System.out.println(chatId);
+
+        //not exist
+        Integer chatId2 = chatMapper.getChatId("21", "11", goodsId);
+        System.out.println(chatId2);
+
+    }
+
+
+
+}