瀏覽代碼

增加websocket和前端通信。

wukai 2 年之前
父節點
當前提交
7125aabea9

+ 16 - 1
dayun-admin/pom.xml

@@ -60,7 +60,22 @@
             <groupId>com.jjt</groupId>
             <artifactId>jjt-generator</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-test</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 21 - 4
dayun-admin/src/main/java/com/jjt/biz/controller/ApiController.java

@@ -18,6 +18,7 @@ import com.jjt.common.utils.poi.ExcelUtil;
 import com.jjt.common.utils.sign.Base64;
 import com.jjt.common.utils.spring.SpringUtils;
 import com.jjt.framework.config.ServerConfig;
+import com.jjt.framework.websocket.WebSocketUsers;
 import org.apache.coyote.http11.upgrade.UpgradeInfo;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -28,10 +29,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
 /**
  * 关键字Controller
@@ -117,6 +115,15 @@ public class ApiController extends BaseController {
                 info.setKeyType(illegal.getKeyType());
             }
             wifiInfoService.insertWifiInfo(info);
+            Map<String, Object> wsMap = new HashMap<>();
+            wsMap.put("lat", info.getLat());
+            wsMap.put("lng", info.getLng());
+            wsMap.put("name", info.getSsid());
+            wsMap.put("type", "WIFI");
+            wsMap.put("time", info.getTime());
+            wsMap.put("illegal", info.getIsIllegal());
+            wsMap.put("keyword", info.getKeyType());
+            WebSocketUsers.sendMessageToUsersByText(JSON.toJSONString(wsMap));
         });
         return AjaxResult.success();
     }
@@ -176,6 +183,16 @@ public class ApiController extends BaseController {
                     info.setKeyType(illegal.getKeyType());
                 }
             }
+
+            Map<String, Object> wsMap = new HashMap<>();
+            wsMap.put("lat", info.getLat());
+            wsMap.put("lng", info.getLng());
+            wsMap.put("name", info.getName());
+            wsMap.put("type", "蓝牙");
+            wsMap.put("time", info.getTime());
+            wsMap.put("illegal", info.getIsIllegal());
+            wsMap.put("keyword", info.getKeyType());
+            WebSocketUsers.sendMessageToUsersByText(JSON.toJSONString(wsMap));
             bluetoothInfoService.insertBluetoothInfo(info);
         });
         return AjaxResult.success();

+ 11 - 0
dayun-admin/src/main/java/com/jjt/biz/controller/IndexController.java

@@ -1,5 +1,6 @@
 package com.jjt.biz.controller;
 
+import com.alibaba.fastjson2.JSON;
 import com.jjt.biz.domain.*;
 import com.jjt.biz.service.IBluetoothInfoService;
 import com.jjt.biz.service.IDeviceInfoService;
@@ -13,6 +14,7 @@ import com.jjt.common.enums.BusinessType;
 import com.jjt.common.utils.DateUtils;
 import com.jjt.common.utils.StringUtils;
 import com.jjt.common.utils.poi.ExcelUtil;
+import com.jjt.framework.websocket.WebSocketUsers;
 import com.jjt.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -47,6 +49,15 @@ public class IndexController extends BaseController {
     @Resource
     private ISysConfigService configService;
 
+    @GetMapping("/msg")
+    public Map<String, Object> msg(InfoReq req) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("beginTime", "xx");
+        params.put("endTime", "yy");
+        WebSocketUsers.sendMessageToUsersByText(JSON.toJSONString(params));
+        return params;
+    }
+
     /**
      * 首页信息
      */

+ 1 - 1
dayun-admin/src/main/resources/application.yml

@@ -37,7 +37,7 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: test
+    active: dev
   # 文件上传
   servlet:
     multipart:

+ 13 - 14
dayun-common/src/main/java/com/jjt/common/utils/file/MimeTypeUtils.java

@@ -2,11 +2,10 @@ package com.jjt.common.utils.file;
 
 /**
  * 媒体类型工具类
- * 
+ *
  * @author ruoyi
  */
-public class MimeTypeUtils
-{
+public class MimeTypeUtils {
     public static final String IMAGE_PNG = "image/png";
 
     public static final String IMAGE_JPG = "image/jpg";
@@ -16,16 +15,16 @@ public class MimeTypeUtils
     public static final String IMAGE_BMP = "image/bmp";
 
     public static final String IMAGE_GIF = "image/gif";
-    
-    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
 
-    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
+    public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
 
-    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
-            "asf", "rm", "rmvb" };
+    public static final String[] FLASH_EXTENSION = {"swf", "flv"};
 
-    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
+    public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb"};
 
+    public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
+    //这里设置允许下载文件的规则
     public static final String[] DEFAULT_ALLOWED_EXTENSION = {
             // 图片
             "bmp", "gif", "jpg", "jpeg", "png",
@@ -36,12 +35,12 @@ public class MimeTypeUtils
             // 视频格式
             "mp4", "avi", "rmvb",
             // pdf
-            "pdf" };
+            "pdf",
+            "apk"
+    };
 
-    public static String getExtension(String prefix)
-    {
-        switch (prefix)
-        {
+    public static String getExtension(String prefix) {
+        switch (prefix) {
             case IMAGE_PNG:
                 return "png";
             case IMAGE_JPG:

+ 6 - 2
dayun-framework/pom.xml

@@ -18,7 +18,7 @@
     <dependencies>
 
         <!-- SpringBoot Web容器 -->
-         <dependency>
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
@@ -34,7 +34,11 @@
             <groupId>com.alibaba</groupId>
             <artifactId>druid-spring-boot-starter</artifactId>
         </dependency>
-
+        <!-- SpringBoot Websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
         <!-- 验证码 -->
         <dependency>
             <groupId>pro.fessional</groupId>

+ 2 - 0
dayun-framework/src/main/java/com/jjt/framework/config/SecurityConfig.java

@@ -111,6 +111,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/login", "/register", "/captchaImage").permitAll()
                 // 增加API接口允许匿名访问
                 .antMatchers("/api/**").permitAll()
+                // 增加websocket允许匿名访问
+                .antMatchers("/websocket/**").permitAll()
                 // 静态资源,可匿名访问
                 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()

+ 58 - 0
dayun-framework/src/main/java/com/jjt/framework/websocket/SemaphoreUtils.java

@@ -0,0 +1,58 @@
+package com.jjt.framework.websocket;
+
+import java.util.concurrent.Semaphore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 信号量相关处理
+ * 
+ * @author ruoyi
+ */
+public class SemaphoreUtils
+{
+    /**
+     * SemaphoreUtils 日志控制器
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
+
+    /**
+     * 获取信号量
+     * 
+     * @param semaphore
+     * @return
+     */
+    public static boolean tryAcquire(Semaphore semaphore)
+    {
+        boolean flag = false;
+
+        try
+        {
+            flag = semaphore.tryAcquire();
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("获取信号量异常", e);
+        }
+
+        return flag;
+    }
+
+    /**
+     * 释放信号量
+     * 
+     * @param semaphore
+     */
+    public static void release(Semaphore semaphore)
+    {
+
+        try
+        {
+            semaphore.release();
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("释放信号量异常", e);
+        }
+    }
+}

+ 20 - 0
dayun-framework/src/main/java/com/jjt/framework/websocket/WebSocketConfig.java

@@ -0,0 +1,20 @@
+package com.jjt.framework.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * websocket 配置
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class WebSocketConfig
+{
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter()
+    {
+        return new ServerEndpointExporter();
+    }
+}

+ 95 - 0
dayun-framework/src/main/java/com/jjt/framework/websocket/WebSocketServer.java

@@ -0,0 +1,95 @@
+package com.jjt.framework.websocket;
+
+import java.util.concurrent.Semaphore;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * websocket 消息处理
+ *
+ * @author ruoyi
+ */
+@Component
+@ServerEndpoint("/websocket/message")
+public class WebSocketServer {
+    /**
+     * WebSocketServer 日志控制器
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
+
+    /**
+     * 默认最多允许同时在线人数100
+     */
+    public static int socketMaxOnlineCount = 100;
+
+    private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
+
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session) throws Exception {
+        boolean semaphoreFlag = false;
+        // 尝试获取信号量
+        semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
+        if (!semaphoreFlag) {
+            // 未获取到信号量
+            LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
+            WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount);
+            session.close();
+        } else {
+            // 添加用户
+            WebSocketUsers.put(session.getId(), session);
+            LOGGER.info("\n 建立连接 - {}", session);
+            LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
+            WebSocketUsers.sendMessageToUserByText(session, "连接成功");
+        }
+    }
+
+    /**
+     * 连接关闭时处理
+     */
+    @OnClose
+    public void onClose(Session session) {
+        LOGGER.info("\n 关闭连接 - {}", session);
+        // 移除用户
+        WebSocketUsers.remove(session.getId());
+        // 获取到信号量则需释放
+        SemaphoreUtils.release(socketSemaphore);
+    }
+
+    /**
+     * 抛出异常时处理
+     */
+    @OnError
+    public void onError(Session session, Throwable exception) throws Exception {
+        if (session.isOpen()) {
+            // 关闭连接
+            session.close();
+        }
+        String sessionId = session.getId();
+        LOGGER.info("\n 连接异常 - {}", sessionId);
+        LOGGER.info("\n 异常信息 - {}", exception);
+        // 移出用户
+        WebSocketUsers.remove(sessionId);
+        // 获取到信号量则需释放
+        SemaphoreUtils.release(socketSemaphore);
+    }
+
+    /**
+     * 服务器接收到客户端消息时调用的方法
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        String msg = message.replace("你", "我").replace("吗", "");
+        WebSocketUsers.sendMessageToUserByText(session, msg);
+    }
+}

+ 118 - 0
dayun-framework/src/main/java/com/jjt/framework/websocket/WebSocketUsers.java

@@ -0,0 +1,118 @@
+package com.jjt.framework.websocket;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.websocket.Session;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * websocket 客户端用户集
+ *
+ * @author ruoyi
+ */
+public class WebSocketUsers {
+    /**
+     * WebSocketUsers 日志控制器
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class);
+
+    /**
+     * 用户集
+     */
+    private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();
+
+    /**
+     * 存储用户
+     *
+     * @param key     唯一键
+     * @param session 用户信息
+     */
+    public static void put(String key, Session session) {
+        USERS.put(key, session);
+    }
+
+    /**
+     * 移除用户
+     *
+     * @param session 用户信息
+     * @return 移除结果
+     */
+    public static boolean remove(Session session) {
+        String key = null;
+        boolean flag = USERS.containsValue(session);
+        if (flag) {
+            Set<Map.Entry<String, Session>> entries = USERS.entrySet();
+            for (Map.Entry<String, Session> entry : entries) {
+                Session value = entry.getValue();
+                if (value.equals(session)) {
+                    key = entry.getKey();
+                    break;
+                }
+            }
+        } else {
+            return true;
+        }
+        return remove(key);
+    }
+
+    /**
+     * 移出用户
+     *
+     * @param key 键
+     */
+    public static boolean remove(String key) {
+        LOGGER.info("\n 正在移出用户 - {}", key);
+        Session remove = USERS.remove(key);
+        if (remove != null) {
+            boolean containsValue = USERS.containsValue(remove);
+            LOGGER.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
+            return containsValue;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * 获取在线用户列表
+     *
+     * @return 返回用户集合
+     */
+    public static Map<String, Session> getUsers() {
+        return USERS;
+    }
+
+    /**
+     * 群发消息文本消息
+     *
+     * @param message 消息内容
+     */
+    public static void sendMessageToUsersByText(String message) {
+        Collection<Session> values = USERS.values();
+        for (Session value : values) {
+            sendMessageToUserByText(value, message);
+        }
+    }
+
+    /**
+     * 发送文本消息
+     *
+     * @param userName 自己的用户名
+     * @param message  消息内容
+     */
+    public static void sendMessageToUserByText(Session session, String message) {
+        if (session != null) {
+            try {
+                session.getBasicRemote().sendText(message);
+            } catch (IOException e) {
+                LOGGER.error("\n[发送消息异常]", e);
+            }
+        } else {
+            LOGGER.info("\n[你已离线]");
+        }
+    }
+}