xiangpei
2024-06-26 eaa622851fd5c701868518969ea51ec061b223b0
websocket集成、加时、强制收卷
4个文件已修改
6个文件已添加
300 ■■■■■ 已修改文件
pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/config/WebSocketConfig.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/controller/admin/ExamController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/form/AddTimeForm.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/form/ForceSubmitForm.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/domain/vo/WebsocketDataVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/enums/WebsocketCommendEnum.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/server/WebsocketServer.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/service/ExamService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ycl/jxkg/service/impl/ExamServiceImpl.java 25 ●●●●● 补丁 | 查看 | 原始文档 | 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("操作成功");
    }
}