Procházet zdrojové kódy

添加消息服务,添加消息服务的表结构

nnkwrik před 6 roky
rodič
revize
f8fdc4c483

+ 14 - 1
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.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
@@ -11,13 +12,13 @@ import java.util.Map;
  * @date 18/11/19 16:54
  */
 public class JsonUtil {
-    private static ObjectMapper mapper = new ObjectMapper();
 
     public static TypeReference<Map<String, String>> simpleJsonMap =
             new TypeReference<Map<String, String>>(){};
 
     public static Map<String, String> fromJson(String rawData, TypeReference typeReference) {
         try {
+            ObjectMapper mapper = new ObjectMapper();
             return mapper.readValue(rawData, typeReference);
 
         } catch (IOException e) {
@@ -28,6 +29,7 @@ public class JsonUtil {
 
     public static <T> T fromJson(String rawData, Class<T> classType) {
         try {
+            ObjectMapper mapper = new ObjectMapper();
             return mapper.readValue(rawData, classType);
         } catch (IOException e) {
             e.printStackTrace();
@@ -35,4 +37,15 @@ public class JsonUtil {
         return null;
     }
 
+    public static String toJson(Object object){
+
+            ObjectMapper mapper = new ObjectMapper();
+        try {
+            return mapper.writeValueAsString(object);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
 }

+ 100 - 0
im-service/pom.xml

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.github.nnkwrik</groupId>
+    <artifactId>im-service</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>im-service</name>
+    <description>Demo project for Spring Boot</description>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.1.1.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <spring-cloud.version>Greenwich.M3</spring-cloud.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+        <!--<dependency>-->
+        <!--<groupId>org.springframework.cloud</groupId>-->
+        <!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
+        <!--</dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.github.nnkwrik</groupId>
+            <artifactId>common</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>${spring-cloud.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>spring-milestones</id>
+            <name>Spring Milestones</name>
+            <url>https://repo.spring.io/milestone</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+
+</project>

+ 12 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/ImServiceApplication.java

@@ -0,0 +1,12 @@
+package io.github.nnkwrik.imservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ImServiceApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(ImServiceApplication.class, args);
+    }
+}

+ 18 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/config/WebSocketConfig.java

@@ -0,0 +1,18 @@
+package io.github.nnkwrik.imservice.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 11:32
+ */
+@Configuration
+public class WebSocketConfig {
+
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+}

+ 22 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/controller/TestController.java

@@ -0,0 +1,22 @@
+package io.github.nnkwrik.imservice.controller;
+
+import io.github.nnkwrik.imservice.websocket.WebSocket;
+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.RestController;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 12:08
+ */
+@RestController
+public class TestController {
+    @Autowired
+    private WebSocket webSocket;
+
+    @RequestMapping("/testsend/{openId}")
+    public void testsend(@PathVariable("openId") String openId){
+        webSocket.sendMessage(openId,"success to send");
+    }
+}

+ 20 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/dao/HistoryMapper.java

@@ -0,0 +1,20 @@
+package io.github.nnkwrik.imservice.dao;
+
+import io.github.nnkwrik.imservice.model.po.ChatHistory;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 22:20
+ */
+@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);
+}

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

@@ -0,0 +1,25 @@
+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);
+}

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

@@ -0,0 +1,20 @@
+package io.github.nnkwrik.imservice.model.po;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 21:23
+ */
+@Data
+public class ChatHistory {
+    private Integer id;
+    private Integer chatUserId;
+    private Boolean u1ToU2;
+    private Integer messageType;    //0:系统消息,1.用户消息
+    private String hint;            //相关的商品id等
+    private String messageBody;
+    private Date createTime;
+}

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

@@ -0,0 +1,16 @@
+package io.github.nnkwrik.imservice.model.po;
+
+import lombok.Data;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 21:19
+ */
+@Data
+public class ChatUser {
+    private Integer id;
+    private String u1;   //u1 < u2
+    private String u2;
+    private Boolean u1ToU2; //指最后一条信息
+    private Integer unreadCount;
+}

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

@@ -0,0 +1,26 @@
+package io.github.nnkwrik.imservice.model.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 21:37
+ */
+@Data
+public class WsMessage {
+    private Integer chatUserId;
+    private String senderId;
+    private String receiverId;
+    private Integer unreadCount;
+    private Integer totalUnreadCount;
+
+    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;
+}

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

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

+ 50 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/service/impl/WebSocketServiceImpl.java

@@ -0,0 +1,50 @@
+package io.github.nnkwrik.imservice.service.impl;
+
+import io.github.nnkwrik.common.util.JsonUtil;
+import io.github.nnkwrik.imservice.dao.HistoryMapper;
+import io.github.nnkwrik.imservice.dao.UserMapper;
+import io.github.nnkwrik.imservice.model.vo.WsMessage;
+import io.github.nnkwrik.imservice.service.WebSocketService;
+import io.github.nnkwrik.imservice.websocket.WebSocket;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 12:30
+ */
+@Service
+public class WebSocketServiceImpl implements WebSocketService {
+    @Autowired
+    private WebSocket webSocket;
+
+    @Autowired
+    private UserMapper userMapper;
+
+    @Autowired
+    private HistoryMapper historyMapper;
+
+    @Override
+    public void sendMessage(String receiverId, String message) {
+        WsMessage wsMessage = JsonUtil.fromJson(message,WsMessage.class);
+
+        Integer unreadCount;
+        if (wsMessage.getSenderId().compareTo(wsMessage.getReceiverId())>0){
+            unreadCount = userMapper.getUnreadCountByChat(wsMessage.getReceiverId(),wsMessage.getSenderId());
+        }else {
+            unreadCount = userMapper.getUnreadCountByChat(wsMessage.getSenderId(),wsMessage.getReceiverId());
+        }
+        unreadCount++;
+
+        if (webSocket.hasConnect(receiverId)){
+            wsMessage.setUnreadCount(unreadCount);
+            webSocket.sendMessage(receiverId,JsonUtil.toJson(wsMessage));
+        }
+
+        //更新数据库
+
+
+
+    }
+
+}

+ 69 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/websocket/WebSocket.java

@@ -0,0 +1,69 @@
+package io.github.nnkwrik.imservice.websocket;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author nnkwrik
+ * @date 18/12/05 11:34
+ */
+@Component
+@ServerEndpoint("/im/{openId}")
+@Slf4j
+public class WebSocket {
+
+    private static ConcurrentMap<String, Session> sessionMap = new ConcurrentHashMap<>();
+
+    @OnOpen
+    public void onOpen(@PathParam("openId") String openId, Session session) {
+        sessionMap.put(openId, session);
+        log.info("【websocket消息】有新的连接, openId = [{}]", openId);
+    }
+
+    @OnClose
+    public void onClose(@PathParam("openId") String openId) {
+        sessionMap.remove(openId);
+        log.info("【websocket消息】连接断开, openId = [{}]", openId);
+    }
+
+    @OnMessage
+    public void onMessage(@PathParam("openId") String openId, String message) {
+        log.info("【websocket消息】收到客户端发来的消息:openId = [{}],消息内容 = [{}]", openId, message);
+    }
+
+    public boolean sendMessage(String openId, String message) {
+        Session session = sessionMap.get(openId);
+        if (session == null) {
+            log.info("消息发送失败,不存在该session:openId = [{}],消息内容 = [{}]", openId, message);
+            return false;
+        } else {
+            try {
+                session.getBasicRemote().sendText(message);
+                log.info("消息发送成功:openId = [{}],消息内容 = [{}]", openId, message);
+                return true;
+            } catch (IOException e) {
+                log.info("消息发送失败:openId = [{}],消息内容 = [{}]", openId, message);
+                e.printStackTrace();
+                return false;
+            }
+        }
+    }
+
+    public boolean hasConnect(String openId) {
+        if (sessionMap.get(openId) != null) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

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

@@ -0,0 +1,31 @@
+eureka:
+  client:
+    service-url:
+      defaultZone: http://localhost:8801/eureka/
+spring:
+  application:
+    name: im-service
+  datasource:
+    url: jdbc:mysql://localhost:3306/im_service
+    username: root
+    password: 1234
+    driver-class-name: com.mysql.cj.jdbc.Driver
+#  jackson:
+#    default-property-inclusion: non_null  #如果值为null,构造json时不加入
+#    date-format: yyyy-MM-dd HH:mm    #指定Json中Date对象的传输格式.对于DTO还是使用以往的方式
+#    locale: zh_CN
+#    time-zone: Asia/Shanghai
+
+server:
+  port: 8805
+
+mybatis:
+  configuration:
+    map-underscore-to-camel-case: true
+#
+#logging:
+#  level:
+#    org.springframework.web: info
+#    io.github.nnkwrik.goodsservice: debug
+#jwt:
+#  pub-key-file-name: RSA.pub

+ 16 - 0
im-service/src/test/java/io/github/nnkwrik/imservice/ImServiceApplicationTests.java

@@ -0,0 +1,16 @@
+package io.github.nnkwrik.imservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class ImServiceApplicationTests {
+
+    @Test
+    public void contextLoads() {
+    }
+
+}