pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/config/WebSocketConfig.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/controller/admin/ExamController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/server/WebsocketServer.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/service/ExamService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
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> src/main/java/com/ycl/jxkg/config/WebSocketConfig.java
New file @@ -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:xp * @date:2024/6/26 15:49 */ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 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); } } src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java
New file @@ -0,0 +1,26 @@ package com.ycl.jxkg.domain.form; import lombok.Data; import javax.validation.constraints.NotNull; /** * @author:xp * @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; } src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java
New file @@ -0,0 +1,24 @@ package com.ycl.jxkg.domain.form; import lombok.Data; import javax.validation.constraints.NotNull; /** * 强制提交试卷 * * @author:xp * @date:2024/6/26 16:15 */ @Data public class ForceSubmitForm { /** 考试 */ @NotNull(message = "请选择考试") private Integer examId; /** 给谁加 */ @NotNull(message = "请选择要强制提交的学员") private Integer userId; } src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java
New file @@ -0,0 +1,18 @@ package com.ycl.jxkg.domain.vo; import lombok.Data; /** * @author:xp * @date:2024/6/26 16:43 */ @Data public class WebsocketDataVO { /** 命令,根据不同的命令执行不同的操作 */ private String commend; /** 指令对应的数据 */ private Object data; } src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java
New file @@ -0,0 +1,27 @@ package com.ycl.jxkg.enums; import lombok.Getter; /** * websocket事件 * * @author:xp * @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; } } src/main/java/com/ycl/jxkg/server/WebsocketServer.java
New file @@ -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:xp * @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("【WebSocket消息】有新的连接,总数为:" + SESSIONS.size()); } catch (Exception e) { e.printStackTrace(); } } @OnClose public void onClose(Session session) { try { SESSIONS.remove(session); log.info("【WebSocket消息】连接断开,总数为:" + SESSIONS.size()); } catch (Exception e) { e.printStackTrace(); } } @OnMessage public void onMessage(String message) { log.info("【WebSocket消息】收到客户端消息:" + message); } /** * 此为广播消息 * * @param message 消息 */ public void sendAllMessage(String message) { log.info("【WebSocket消息】广播消息:" + 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("【WebSocket消息】单点消息:" + 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("【WebSocket消息】单点消息:" + message); session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } } } 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); } 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); // 发送websocket消息 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); // 发送websocket消息 websocketServer.sendOneMessage(form.getUserId(), JSON.toJSONString(form)); return Result.ok("操作成功"); } }