From eaa622851fd5c701868518969ea51ec061b223b0 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期三, 26 六月 2024 17:03:48 +0800
Subject: [PATCH] websocket集成、加时、强制收卷

---
 src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java         |   26 +++++
 src/main/java/com/ycl/jxkg/config/WebSocketConfig.java          |   19 +++
 src/main/java/com/ycl/jxkg/service/ExamService.java             |   18 +++
 src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java      |   27 +++++
 src/main/java/com/ycl/jxkg/server/WebsocketServer.java          |  120 ++++++++++++++++++++++++
 src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java     |   24 ++++
 src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java    |   25 +++++
 src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java       |   18 +++
 pom.xml                                                         |    7 +
 src/main/java/com/ycl/jxkg/controller/admin/ExamController.java |   16 +++
 10 files changed, 300 insertions(+), 0 deletions(-)

diff --git a/pom.xml b/pom.xml
index 6a1ebf1..81ae332 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,13 @@
 
 
     <dependencies>
+
+        <!-- websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
diff --git a/src/main/java/com/ycl/jxkg/config/WebSocketConfig.java b/src/main/java/com/ycl/jxkg/config/WebSocketConfig.java
new file mode 100644
index 0000000..906cc46
--- /dev/null
+++ b/src/main/java/com/ycl/jxkg/config/WebSocketConfig.java
@@ -0,0 +1,19 @@
+package com.ycl.jxkg.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * @author锛歺p
+ * @date锛�2024/6/26 15:49
+ */
+@Configuration
+public class WebSocketConfig {
+
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+
+}
diff --git a/src/main/java/com/ycl/jxkg/controller/admin/ExamController.java b/src/main/java/com/ycl/jxkg/controller/admin/ExamController.java
index 77c04b8..ac0ea48 100644
--- a/src/main/java/com/ycl/jxkg/controller/admin/ExamController.java
+++ b/src/main/java/com/ycl/jxkg/controller/admin/ExamController.java
@@ -1,7 +1,9 @@
 package com.ycl.jxkg.controller.admin;
 
 import com.ycl.jxkg.base.Result;
+import com.ycl.jxkg.domain.form.AddTimeForm;
 import com.ycl.jxkg.domain.form.ExamForm;
+import com.ycl.jxkg.domain.form.ForceSubmitForm;
 import com.ycl.jxkg.domain.query.ExamQuery;
 import com.ycl.jxkg.group.Add;
 import com.ycl.jxkg.group.Update;
@@ -101,4 +103,18 @@
         return examService.monitorList(query);
     }
 
+    @PostMapping("/add/time")
+    @PreAuthorize("hasAuthority('exam:add:time')")
+    @ApiOperation(value = "娣诲姞鑰冭瘯鏃堕暱", notes = "娣诲姞鑰冭瘯鏃堕暱")
+    public Result addTime(@RequestBody @Validated AddTimeForm form) {
+        return examService.addTime(form);
+    }
+
+    @PostMapping("/force/submit")
+    @PreAuthorize("hasAuthority('exam:add:time')")
+    @ApiOperation(value = "寮哄埗鎻愪氦璇曞嵎", notes = "寮哄埗鎻愪氦璇曞嵎")
+    public Result forceSubmit(@RequestBody @Validated ForceSubmitForm form) {
+        return examService.forceSubmit(form);
+    }
+
 }
diff --git a/src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java b/src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java
new file mode 100644
index 0000000..1e17bf1
--- /dev/null
+++ b/src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java
@@ -0,0 +1,26 @@
+package com.ycl.jxkg.domain.form;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author锛歺p
+ * @date锛�2024/6/26 16:15
+ */
+@Data
+public class AddTimeForm {
+
+    /** 鑰冭瘯 */
+    @NotNull(message = "璇烽�夋嫨鑰冭瘯")
+    private Integer examId;
+
+    /** 缁欒皝鍔� */
+    @NotNull(message = "璇烽�夋嫨缁欒皝鍔�")
+    private Integer userId;
+
+    /** 娣诲姞澶氬皯鏃堕棿锛氱 */
+    @NotNull(message = "璇峰~鍐欏姞鏃剁鏁�")
+    private Integer addTimeSecond;
+
+}
diff --git a/src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java b/src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java
new file mode 100644
index 0000000..ec360fd
--- /dev/null
+++ b/src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java
@@ -0,0 +1,24 @@
+package com.ycl.jxkg.domain.form;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 寮哄埗鎻愪氦璇曞嵎
+ *
+ * @author锛歺p
+ * @date锛�2024/6/26 16:15
+ */
+@Data
+public class ForceSubmitForm {
+
+    /** 鑰冭瘯 */
+    @NotNull(message = "璇烽�夋嫨鑰冭瘯")
+    private Integer examId;
+
+    /** 缁欒皝鍔� */
+    @NotNull(message = "璇烽�夋嫨瑕佸己鍒舵彁浜ょ殑瀛﹀憳")
+    private Integer userId;
+
+}
diff --git a/src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java b/src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java
new file mode 100644
index 0000000..57373d9
--- /dev/null
+++ b/src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java
@@ -0,0 +1,18 @@
+package com.ycl.jxkg.domain.vo;
+
+import lombok.Data;
+
+/**
+ * @author锛歺p
+ * @date锛�2024/6/26 16:43
+ */
+@Data
+public class WebsocketDataVO {
+
+    /** 鍛戒护锛屾牴鎹笉鍚岀殑鍛戒护鎵ц涓嶅悓鐨勬搷浣� */
+    private String commend;
+
+    /** 鎸囦护瀵瑰簲鐨勬暟鎹� */
+    private Object data;
+
+}
diff --git a/src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java b/src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java
new file mode 100644
index 0000000..c0e3564
--- /dev/null
+++ b/src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java
@@ -0,0 +1,27 @@
+package com.ycl.jxkg.enums;
+
+import lombok.Getter;
+
+/**
+ * websocket浜嬩欢
+ *
+ * @author锛歺p
+ * @date锛�2024/6/26 16:50
+ */
+@Getter
+public enum WebsocketCommendEnum {
+
+
+    DELAYED("delayed", "寤堕暱鑰冭瘯鏃堕棿"),
+    FORCE_SUBMIT("forceSubmit", "寮哄埗鎻愪氦"),
+    ;
+
+    private final String commend;
+
+    private final String desc;
+
+    WebsocketCommendEnum(String commend, String desc) {
+        this.commend = commend;
+        this.desc = desc;
+    }
+}
diff --git a/src/main/java/com/ycl/jxkg/server/WebsocketServer.java b/src/main/java/com/ycl/jxkg/server/WebsocketServer.java
new file mode 100644
index 0000000..3e27189
--- /dev/null
+++ b/src/main/java/com/ycl/jxkg/server/WebsocketServer.java
@@ -0,0 +1,120 @@
+package com.ycl.jxkg.server;
+
+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.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * @author锛歺p
+ * @date锛�2024/6/26 15:51
+ */
+@Component
+@Slf4j
+@ServerEndpoint("/websocket/{userId}")
+public class WebsocketServer {
+
+    /**
+     * 绾跨▼瀹夊叏鐨勬棤搴忕殑闆嗗悎
+     */
+    private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();
+
+    /**
+     * 瀛樺偍鍦ㄧ嚎杩炴帴鏁�
+     */
+    private static final Map<Integer, Session> SESSION_POOL = new HashMap<>();
+
+    @OnOpen
+    public void onOpen(Session session, @PathParam(value = "userId") Integer userId) {
+        try {
+            SESSIONS.add(session);
+            SESSION_POOL.put(userId, session);
+            log.info("銆怶ebSocket娑堟伅銆戞湁鏂扮殑杩炴帴锛屾�绘暟涓猴細" + SESSIONS.size());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @OnClose
+    public void onClose(Session session) {
+        try {
+            SESSIONS.remove(session);
+            log.info("銆怶ebSocket娑堟伅銆戣繛鎺ユ柇寮�锛屾�绘暟涓猴細" + SESSIONS.size());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @OnMessage
+    public void onMessage(String message) {
+        log.info("銆怶ebSocket娑堟伅銆戞敹鍒板鎴风娑堟伅锛�" + message);
+    }
+
+    /**
+     * 姝や负骞挎挱娑堟伅
+     *
+     * @param message 娑堟伅
+     */
+    public void sendAllMessage(String message) {
+        log.info("銆怶ebSocket娑堟伅銆戝箍鎾秷鎭細" + message);
+        for (Session session : SESSIONS) {
+            try {
+                if (session.isOpen()) {
+                    session.getAsyncRemote().sendText(message);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 姝や负鍗曠偣娑堟伅
+     *
+     * @param userId  鐢ㄦ埛缂栧彿
+     * @param message 娑堟伅
+     */
+    public void sendOneMessage(Integer userId, String message) {
+        Session session = SESSION_POOL.get(userId);
+        if (session != null && session.isOpen()) {
+            try {
+                synchronized (session) {
+                    log.info("銆怶ebSocket娑堟伅銆戝崟鐐规秷鎭細" + message);
+                    session.getAsyncRemote().sendText(message);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 姝や负鍗曠偣娑堟伅(澶氫汉)
+     *
+     * @param userIds 鐢ㄦ埛缂栧彿鍒楄〃
+     * @param message 娑堟伅
+     */
+    public void sendMoreMessage(List<Integer> userIds, String message) {
+        for (Integer userId : userIds) {
+            Session session = SESSION_POOL.get(userId);
+            if (session != null && session.isOpen()) {
+                try {
+                    log.info("銆怶ebSocket娑堟伅銆戝崟鐐规秷鎭細" + message);
+                    session.getAsyncRemote().sendText(message);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/main/java/com/ycl/jxkg/service/ExamService.java b/src/main/java/com/ycl/jxkg/service/ExamService.java
index 0dcb219..d79fdd1 100644
--- a/src/main/java/com/ycl/jxkg/service/ExamService.java
+++ b/src/main/java/com/ycl/jxkg/service/ExamService.java
@@ -3,7 +3,9 @@
 import com.ycl.jxkg.domain.entity.Exam;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ycl.jxkg.base.Result;
+import com.ycl.jxkg.domain.form.AddTimeForm;
 import com.ycl.jxkg.domain.form.ExamForm;
+import com.ycl.jxkg.domain.form.ForceSubmitForm;
 import com.ycl.jxkg.domain.query.ExamQuery;
 import com.ycl.jxkg.domain.vo.ExamSubmitVO;
 
@@ -120,4 +122,20 @@
      * @return 鐩戞帶鍒楄〃
      */
     Result monitorList(ExamQuery query);
+
+    /**
+     * 娣诲姞鑰冭瘯鏃堕棿
+     *
+     * @param form
+     * @return
+     */
+    Result addTime(AddTimeForm form);
+
+    /**
+     * 寮哄埗鎻愪氦璇曞嵎
+     *
+     * @param form
+     * @return
+     */
+    Result forceSubmit(ForceSubmitForm form);
 }
diff --git a/src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java b/src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java
index 33c5843..cb54732 100644
--- a/src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java
+++ b/src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java
@@ -12,14 +12,18 @@
 import com.ycl.jxkg.domain.entity.Question;
 import com.ycl.jxkg.domain.exam.PaperFixQuestionDTO;
 import com.ycl.jxkg.domain.exam.PaperQuestionSettingDTO;
+import com.ycl.jxkg.domain.form.AddTimeForm;
 import com.ycl.jxkg.domain.form.ExamForm;
+import com.ycl.jxkg.domain.form.ForceSubmitForm;
 import com.ycl.jxkg.domain.query.ExamQuery;
 import com.ycl.jxkg.domain.question.QuestionObject;
 import com.ycl.jxkg.domain.vo.*;
 import com.ycl.jxkg.enums.ExamPaperTypeEnum;
+import com.ycl.jxkg.enums.WebsocketCommendEnum;
 import com.ycl.jxkg.enums.general.ExamStatusEnum;
 import com.ycl.jxkg.enums.general.ExamSubmitTempStatusEnum;
 import com.ycl.jxkg.mapper.*;
+import com.ycl.jxkg.server.WebsocketServer;
 import com.ycl.jxkg.service.ExamPaperService;
 import com.ycl.jxkg.service.ExamService;
 import com.ycl.jxkg.utils.PageUtil;
@@ -50,6 +54,7 @@
     private final ClassesUserMapper classesUserMapper;
     private final ExamPaperMapper examPaperMapper;
     private final ExamPaperService examPaperService;
+    private final WebsocketServer websocketServer;
 
     /**
      * 娣诲姞
@@ -433,4 +438,24 @@
         IPage<ExamSubmitTempVO> page = PageUtil.getPage(query, ExamSubmitTempVO.class);
         return Result.ok().data(examSubmitTempMapper.monitorList(page, query));
     }
+
+    @Override
+    public Result addTime(AddTimeForm form) {
+        WebsocketDataVO websocket = new WebsocketDataVO();
+        websocket.setCommend(WebsocketCommendEnum.DELAYED.getCommend());
+        websocket.setData(form);
+        // 鍙戦�亀ebsocket娑堟伅
+        websocketServer.sendOneMessage(form.getUserId(), JSON.toJSONString(form));
+        return Result.ok("鎿嶄綔鎴愬姛");
+    }
+
+    @Override
+    public Result forceSubmit(ForceSubmitForm form) {
+        WebsocketDataVO websocket = new WebsocketDataVO();
+        websocket.setCommend(WebsocketCommendEnum.FORCE_SUBMIT.getCommend());
+        websocket.setData(form);
+        // 鍙戦�亀ebsocket娑堟伅
+        websocketServer.sendOneMessage(form.getUserId(), JSON.toJSONString(form));
+        return Result.ok("鎿嶄綔鎴愬姛");
+    }
 }

--
Gitblit v1.8.0