wangliang 5 lat temu
rodzic
commit
48a80e1fca
17 zmienionych plików z 385 dodań i 34 usunięć
  1. 1 1
      themis-backend/src/main/java/com/qmth/themis/backend/interceptor/AuthInterceptor.java
  2. 4 0
      themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java
  3. 12 0
      themis-business/src/main/java/com/qmth/themis/business/entity/TEExamStudentLog.java
  4. 15 0
      themis-business/src/main/java/com/qmth/themis/business/service/EhcacheService.java
  5. 8 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentLogService.java
  6. 53 1
      themis-business/src/main/java/com/qmth/themis/business/service/impl/EhcacheServiceImpl.java
  7. 13 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentLogServiceImpl.java
  8. 30 0
      themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java
  9. 4 0
      themis-common/src/main/java/com/qmth/themis/common/enums/ExceptionResultEnum.java
  10. 175 0
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java
  11. 11 9
      themis-exam/src/main/java/com/qmth/themis/exam/interceptor/AuthInterceptor.java
  12. 9 0
      themis-exam/src/main/java/com/qmth/themis/exam/util/ServletUtil.java
  13. 2 2
      themis-exam/src/main/resources/application.properties
  14. 9 9
      themis-exam/src/main/resources/ehcache.xml
  15. 23 6
      themis-mq/src/main/java/com/qmth/themis/mq/listener/RocketUserLogConsumer.java
  16. 3 0
      themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqDtoServiceImpl.java
  17. 13 6
      themis-task/src/main/java/com/qmth/themis/task/quartz/MqJob.java

+ 1 - 1
themis-backend/src/main/java/com/qmth/themis/backend/interceptor/AuthInterceptor.java

@@ -54,7 +54,7 @@ public class AuthInterceptor implements HandlerInterceptor {
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
-        log.info("HandlerInterceptor preHandle is come in");
+        log.info("backend HandlerInterceptor preHandle is come in");
         String url = request.getServletPath();
         String method = request.getMethod();
         Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());

+ 4 - 0
themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java

@@ -39,17 +39,21 @@ public class SystemConstant {
     public static final String EXPORT_INIT = "准备开始处理导出数据";
     public static final String RECORDS = "records";
     public static final String USER = "user:";
+    public static final String STUDENT = "student:";
     public static final String SESSION = "session:";
     public static final String ORG = "org:";
     public static final String LINK = "LINK";
     public static final String MENU = "MENU";
     public static final String AUTH_CACHE = "auth_cache";
+    public static final String STUDENT_CACHE = "student_cache";
     public static final String ALL_PATH = "/**";
     public static final String ACCOUNT = "account";
+    public static final String STUDENT_ACCOUNT = "student";
     public static final String COUNT = "count";
     public static final String ERROR = "/error";
     public static final String SESSION_TOPIC_BUFFER_LIST = "session:topic:buffer:list";
     public static final String USERLOG_TOPIC_BUFFER_LIST = "userLog:topic:buffer:list";
+    public static final String STUDENTLOG_TOPIC_BUFFER_LIST = "studentLog:topic:buffer:list";
     public static final String TASKLOG_TOPIC_BUFFER_LIST = "taskLog:topic:buffer:list";
     public static final String TYPE = "type";
     public static final String LOCAL = "local";

+ 12 - 0
themis-business/src/main/java/com/qmth/themis/business/entity/TEExamStudentLog.java

@@ -3,6 +3,7 @@ package com.qmth.themis.business.entity;
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.qmth.themis.common.contanst.Constants;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -57,6 +58,17 @@ public class TEExamStudentLog implements Serializable {
     @TableField(value = "create_time", fill = FieldFill.INSERT)
     private Date createTime;
 
+    public TEExamStudentLog() {
+
+    }
+
+    public TEExamStudentLog(Integer type, String description, String remark) {
+        this.id = Constants.idGen.next();
+        this.type = type;
+        this.description = description;
+        this.remark = remark;
+    }
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }

+ 15 - 0
themis-business/src/main/java/com/qmth/themis/business/service/EhcacheService.java

@@ -25,4 +25,19 @@ public interface EhcacheService {
      * @param userId
      */
     public void removeAccountCache(Long userId);
+
+    /**
+     * 添加学生缓存
+     *
+     * @param o
+     * @return
+     */
+    public AuthDto addStudentCache(Object o);
+
+    /**
+     * 删除学生缓存
+     *
+     * @param userId
+     */
+    public void removeStudentCache(Long userId);
 }

+ 8 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentLogService.java

@@ -12,4 +12,12 @@ import com.qmth.themis.business.entity.TEExamStudentLog;
  */
 public interface TEExamStudentLogService extends IService<TEExamStudentLog> {
 
+    /**
+     * 保存学生轨迹
+     *
+     * @param mqTimestamp
+     * @param o
+     * @return
+     */
+    public boolean saveStudentLogInfo(long mqTimestamp, Object... o);
 }

+ 53 - 1
themis-business/src/main/java/com/qmth/themis/business/service/impl/EhcacheServiceImpl.java

@@ -14,8 +14,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -46,6 +46,9 @@ public class EhcacheServiceImpl implements EhcacheService {
     @Resource
     TBOrgService tbOrgService;
 
+    @Resource
+    TEStudentService teStudentService;
+
     /**
      * 添加用户缓存
      *
@@ -110,4 +113,53 @@ public class EhcacheServiceImpl implements EhcacheService {
     public void removeAccountCache(Long userId) {
         EhcacheUtil.remove(SystemConstant.AUTH_CACHE, userId);
     }
+
+    /**
+     * 添加学生缓存
+     *
+     * @param o
+     * @return
+     */
+    @Override
+    public AuthDto addStudentCache(Object o) {
+        AuthDto authDto = null;
+        try {
+            TEStudent teStudent = null;
+            if (o instanceof TEStudent) {
+                teStudent = (TEStudent) o;
+            } else {
+                teStudent = teStudentService.getById(Long.parseLong(String.valueOf(o)));
+            }
+            if (Objects.isNull(teStudent)) {
+                throw new BusinessException(ExceptionResultEnum.STUDENT_NO);
+            }
+            TBOrg tbOrg = tbOrgService.getById(teStudent.getOrgId());
+            //根据学生角色查权限
+            QueryWrapper<TBRolePrivilege> rpWrapper = new QueryWrapper<>();
+            rpWrapper.lambda().eq(TBRolePrivilege::getRoleCode, RoleEnum.STUDENT.name());
+            List<TBRolePrivilege> tbRolePrivilegeList = tbRolePrivilegeService.list(rpWrapper);
+            Set<Long> privilegeIds = tbRolePrivilegeList.stream().map(s -> s.getPrivilegeId()).collect(Collectors.toSet());
+            QueryWrapper<TBPrivilege> pWrapper = new QueryWrapper<>();
+            pWrapper.lambda().in(TBPrivilege::getId, privilegeIds).eq(TBPrivilege::getType, SystemConstant.LINK);
+            List<TBPrivilege> tbPrivilegeList = tbPrivilegeService.list(pWrapper);
+            Set<String> roleCodes = new HashSet<>();
+            roleCodes.add(RoleEnum.STUDENT.name());
+            authDto = new AuthDto(roleCodes, tbPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()), tbOrg);
+            EhcacheUtil.put(SystemConstant.STUDENT_CACHE, teStudent.getId(), authDto);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BusinessException("添加学生缓存失败");
+        }
+        return authDto;
+    }
+
+    /**
+     * 删除学生缓存
+     *
+     * @param studentId
+     */
+    @Override
+    public void removeStudentCache(Long studentId) {
+        EhcacheUtil.remove(SystemConstant.STUDENT_CACHE, studentId);
+    }
 }

+ 13 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentLogServiceImpl.java

@@ -16,4 +16,17 @@ import org.springframework.stereotype.Service;
 @Service
 public class TEExamStudentLogServiceImpl extends ServiceImpl<TEExamStudentLogMapper, TEExamStudentLog> implements TEExamStudentLogService {
 
+    /**
+     * 保存学生轨迹
+     *
+     * @param mqTimestamp
+     * @param o
+     * @return
+     */
+    @Override
+    public boolean saveStudentLogInfo(long mqTimestamp, Object... o) {
+        TEExamStudentLog teExamStudentLog = new TEExamStudentLog(Integer.parseInt(String.valueOf(o[0])), String.valueOf(o[1]), String.valueOf(o[2]));
+        this.save(teExamStudentLog);
+        return true;
+    }
 }

+ 30 - 0
themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java

@@ -102,6 +102,36 @@ public class RedisUtil {
         redisTemplate.opsForValue().set(SystemConstant.USER + userId, o, SystemConstant.REDIS_EXPIRE_TIME, TimeUnit.SECONDS);
     }
 
+    /**
+     * 设置学生信息
+     *
+     * @param studentId
+     * @param o
+     */
+    public void setStudent(Long studentId, Object o) {
+        redisTemplate.opsForValue().set(SystemConstant.STUDENT + studentId, o, SystemConstant.REDIS_EXPIRE_TIME, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 删除学生缓存
+     *
+     * @param studentId
+     */
+    public void deleteStudent(Long studentId) {
+        redisTemplate.delete(SystemConstant.STUDENT + studentId);
+    }
+
+    /**
+     * 获取学生信息
+     *
+     * @param studentId
+     * @return
+     */
+    public Object getStudent(Long studentId) {
+        return redisTemplate.opsForValue().get(SystemConstant.STUDENT + studentId);
+    }
+
+
     /**
      * 刷新用户缓存
      *

+ 4 - 0
themis-common/src/main/java/com/qmth/themis/common/enums/ExceptionResultEnum.java

@@ -92,6 +92,8 @@ public enum ExceptionResultEnum {
 
     ENABLE_IS_NULL("102", "禁用/启用状态不能为空"),
 
+    STUDENT_IS_NULL("102", "学生信息不能为空"),
+
     EXAM_CODE_IS_NULL("102", "考试批次编码不能为空"),
 
     EXAM_NAME_IS_NULL("102", "考试批次名称不能为空"),
@@ -132,6 +134,8 @@ public enum ExceptionResultEnum {
 
     USER_ENABLE("109", "用户已停用"),
 
+    STUDENT_ENABLE("109", "学生已停用"),
+
     NOT_FOUND("404", "请求地址错误"),
 
     SERVICE_NOT_FOUND("500", "服务器错误"),

+ 175 - 0
themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java

@@ -0,0 +1,175 @@
+package com.qmth.themis.exam.api;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.dto.AuthDto;
+import com.qmth.themis.business.entity.TBSession;
+import com.qmth.themis.business.entity.TEStudent;
+import com.qmth.themis.business.enums.MqEnum;
+import com.qmth.themis.business.enums.RoleEnum;
+import com.qmth.themis.business.enums.SystemOperationEnum;
+import com.qmth.themis.business.service.EhcacheService;
+import com.qmth.themis.business.service.TEStudentService;
+import com.qmth.themis.business.util.EhcacheUtil;
+import com.qmth.themis.business.util.JacksonUtil;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.business.util.SessionUtil;
+import com.qmth.themis.common.contanst.Constants;
+import com.qmth.themis.common.enums.ExceptionResultEnum;
+import com.qmth.themis.common.enums.Platform;
+import com.qmth.themis.common.enums.Source;
+import com.qmth.themis.common.exception.BusinessException;
+import com.qmth.themis.common.signature.SignatureInfo;
+import com.qmth.themis.common.signature.SignatureType;
+import com.qmth.themis.common.util.AesUtil;
+import com.qmth.themis.common.util.Result;
+import com.qmth.themis.common.util.ResultUtil;
+import com.qmth.themis.exam.config.DictionaryConfig;
+import com.qmth.themis.exam.util.ServletUtil;
+import com.qmth.themis.mq.service.MqDtoService;
+import io.swagger.annotations.*;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @Description: 考生 前端控制器
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/6/25
+ */
+@Api(tags = "考生Controller")
+@RestController
+@RequestMapping("/${prefix.url.exam}/student")
+public class TEStudentController {
+    private final static Logger log = LoggerFactory.getLogger(TEStudentController.class);
+
+    @Resource
+    TEStudentService teStudentService;
+
+    @Resource
+    EhcacheService ehcacheService;
+
+    @Resource
+    DictionaryConfig dictionaryConfig;
+
+    @Resource
+    RedisUtil redisUtil;
+
+    @Resource
+    MqDtoService mqDtoService;
+
+    @ApiOperation(value = "学生登录接口")
+    @RequestMapping(value = "/login", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "学生信息", response = TEStudent.class)})
+    public Result login(@ApiParam(value = "学生信息", required = true) @RequestBody TEStudent teStudent) throws NoSuchAlgorithmException {
+        if (Objects.isNull(teStudent)) {
+            throw new BusinessException(ExceptionResultEnum.STUDENT_IS_NULL);
+        }
+        if (Objects.isNull(teStudent.getIdentity()) || Objects.equals(teStudent.getIdentity(), "")) {
+            throw new BusinessException(ExceptionResultEnum.LOGIN_NAME_IS_NULL);
+        }
+        if (Objects.isNull(teStudent.getPassword()) || Objects.equals(teStudent.getPassword(), "")) {
+            throw new BusinessException(ExceptionResultEnum.PASSWORD_IS_NULL);
+        }
+        String identity = teStudent.getIdentity();
+        String password = teStudent.getPassword();
+
+        QueryWrapper<TEStudent> wrapper = new QueryWrapper<>();
+        wrapper.lambda().eq(TEStudent::getIdentity, identity);
+        TEStudent user = teStudentService.getOne(wrapper);
+        //学生不存在
+        if (Objects.isNull(user)) {
+            throw new BusinessException(ExceptionResultEnum.STUDENT_NO);
+        }
+        String loginPassword = AesUtil.decryptCs7(password, Constants.AES_RULE);
+        //密码错误
+        String aesPassword = AesUtil.decryptCs7(user.getPassword(), Constants.AES_RULE);
+        if (!Objects.equals(loginPassword, aesPassword)) {
+            throw new BusinessException(ExceptionResultEnum.PASSWORD_NO);
+        }
+        return userLoginCommon(user);
+    }
+
+    /**
+     * 学生登录公用
+     *
+     * @param teStudent
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public Result userLoginCommon(TEStudent teStudent) throws NoSuchAlgorithmException {
+        //停用
+        if (teStudent.getEnable().intValue() == 0) {
+            throw new BusinessException(ExceptionResultEnum.STUDENT_ENABLE);
+        }
+        Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
+        String deviceId = ServletUtil.getRequestDeviceId();
+        //添加用户鉴权缓存
+        AuthDto authDto = ehcacheService.addStudentCache(teStudent);
+        //生成token
+        String token = RandomStringUtils.randomAlphanumeric(32);
+        //添加用户缓存
+        redisUtil.setStudent(teStudent.getId(), teStudent);
+        //添加用户会话缓存
+        String sessionId = SessionUtil.digest(teStudent.getId(), authDto.getRoleCodes().toString().replaceAll(",", "&&").replaceAll(" ", ""), platform.getSource());
+
+        Date expire = SystemConstant.getExpireTime(platform);
+        TBSession tbSession = new TBSession(sessionId, String.valueOf(teStudent.getId()), authDto.getRoleCodes().toString(), platform.getSource(), platform.name(), deviceId, ServletUtil.getRequest().getLocalAddr(), token, expire);
+        redisUtil.setUserSession(sessionId, tbSession);
+        //mq发送消息start
+        mqDtoService.assembleSendOneWayMsg(dictionaryConfig.mqConfigDomain().getSessionTopic(), platform.getSource(), tbSession, MqEnum.SESSION.name(), tbSession.getId(), teStudent.getIdentity());
+        mqDtoService.assembleSendOneWayMsg(dictionaryConfig.mqConfigDomain().getUserLogTopic(), authDto.getRoleCodes().toString().contains(RoleEnum.STUDENT.name()) ? dictionaryConfig.mqConfigDomain().getUserLogTopicStudentTag() : dictionaryConfig.mqConfigDomain().getUserLogTopicUserTag(), SystemOperationEnum.LOGIN, MqEnum.EXAM_STUDENT_LOG.name(), teStudent.getId(), teStudent.getIdentity());
+        //mq发送消息end
+        //测试
+        String test = SignatureInfo.build(SignatureType.TOKEN, sessionId, token);
+        Map<String, Object> map = new HashMap<>();
+//        map.put(SystemConstant.ACCESS_TOKEN, token);
+        map.put(SystemConstant.ACCESS_TOKEN, test);
+        map.put(SystemConstant.STUDENT_ACCOUNT, teStudent);
+        map.put(SystemConstant.SESSION_ID, sessionId);
+        return ResultUtil.ok(map);
+    }
+
+    @ApiOperation(value = "登出接口")
+    @RequestMapping(value = "/logout", method = RequestMethod.GET)
+    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
+    public Result logout() throws NoSuchAlgorithmException {
+        TEStudent teStudent = (TEStudent) ServletUtil.getRequestStudentAccount();
+        TBSession tbSession = (TBSession) ServletUtil.getRequestSession();
+        AuthDto authDto = (AuthDto) EhcacheUtil.get(SystemConstant.STUDENT_CACHE, teStudent.getId());
+        if (Objects.isNull(tbSession)) {
+            throw new BusinessException(ExceptionResultEnum.LOGIN_NO);
+        }
+        redisUtil.deleteUserSession(tbSession.getId());
+        //循环检查该用户下其他平台是否存在session,不存在则删除用户缓存和鉴权缓存
+        boolean delete = true;
+        for (Source s : Source.values()) {
+            String sessionId = SessionUtil.digest(teStudent.getId(), authDto.getRoleCodes().toString().replaceAll(",", "&&").replaceAll(" ", ""), s.name());
+            if (Objects.nonNull(redisUtil.getUserSession(sessionId))) {
+                delete = false;
+                break;
+            }
+        }
+        if (delete) {
+            redisUtil.deleteStudent(teStudent.getId());
+            ehcacheService.removeStudentCache(teStudent.getId());
+        }
+        //mq发送消息start
+        mqDtoService.assembleSendOneWayMsg(dictionaryConfig.mqConfigDomain().getUserLogTopic(), authDto.getRoleCodes().toString().contains(RoleEnum.STUDENT.name()) ? dictionaryConfig.mqConfigDomain().getUserLogTopicStudentTag() : dictionaryConfig.mqConfigDomain().getUserLogTopicUserTag(), SystemOperationEnum.LOGOUT, MqEnum.EXAM_STUDENT_LOG.name(), teStudent.getId(), teStudent.getIdentity());
+        //mq发送消息end
+        return ResultUtil.ok(JacksonUtil.parseJson(SystemConstant.SUCCESS));
+    }
+}

+ 11 - 9
themis-exam/src/main/java/com/qmth/themis/exam/interceptor/AuthInterceptor.java

@@ -5,9 +5,11 @@ import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.dto.AuthDto;
 import com.qmth.themis.business.entity.TBSession;
 import com.qmth.themis.business.entity.TBUser;
+import com.qmth.themis.business.entity.TEStudent;
 import com.qmth.themis.business.enums.RoleEnum;
 import com.qmth.themis.business.service.EhcacheService;
 import com.qmth.themis.business.service.TBUserService;
+import com.qmth.themis.business.service.TEStudentService;
 import com.qmth.themis.business.util.EhcacheUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
@@ -47,14 +49,14 @@ public class AuthInterceptor implements HandlerInterceptor {
     DictionaryConfig dictionaryConfig;
 
     @Resource
-    TBUserService tbUserService;
+    TEStudentService teStudentService;
 
     @Resource
     RedisUtil redisUtil;
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
-        log.info("HandlerInterceptor preHandle is come in");
+        log.info("exam HandlerInterceptor preHandle is come in");
         String url = request.getServletPath();
         String method = request.getMethod();
         Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
@@ -96,19 +98,19 @@ public class AuthInterceptor implements HandlerInterceptor {
                     if (expireTime.getTime() <= System.currentTimeMillis()) {//先判断时间是否过期
                         throw new BusinessException(ExceptionResultEnum.LOGIN_NO);
                     }
-                    TBUser tbUser = (TBUser) redisUtil.getUser(userId);
-                    if (Objects.isNull(tbUser)) {
-                        tbUser = tbUserService.getById(userId);
-                        redisUtil.setUser(tbUser.getId(), tbUser);
+                    TEStudent teStudent = (TEStudent) redisUtil.getStudent(userId);
+                    if (Objects.isNull(teStudent)) {
+                        teStudent = teStudentService.getById(userId);
+                        redisUtil.setStudent(teStudent.getId(), teStudent);
                     }
 
                     request.setAttribute(SystemConstant.SESSION, tbSession);
-                    request.setAttribute(SystemConstant.ACCOUNT, tbUser);
+                    request.setAttribute(SystemConstant.STUDENT_ACCOUNT, teStudent);
 
-                    AuthDto authDto = (AuthDto) EhcacheUtil.get(SystemConstant.AUTH_CACHE, userId);
+                    AuthDto authDto = (AuthDto) EhcacheUtil.get(SystemConstant.STUDENT_CACHE, userId);
                     //验证权限
                     if (Objects.isNull(authDto)) {
-                        authDto = ehcacheService.addAccountCache(userId);
+                        authDto = ehcacheService.addStudentCache(userId);
                     }
                     request.setAttribute(SystemConstant.ORG, authDto.getTbOrg());
                     //系统管理员拥有所有权限

+ 9 - 0
themis-exam/src/main/java/com/qmth/themis/exam/util/ServletUtil.java

@@ -151,6 +151,15 @@ public class ServletUtil {
         return getRequest().getAttribute(SystemConstant.ACCOUNT);
     }
 
+    /**
+     * 获取请求的student account
+     *
+     * @return
+     */
+    public static Object getRequestStudentAccount() {
+        return getRequest().getAttribute(SystemConstant.STUDENT_ACCOUNT);
+    }
+
     /**
      * 获取请求的org
      *

+ 2 - 2
themis-exam/src/main/resources/application.properties

@@ -19,7 +19,7 @@ db.username=root
 db.password=123456789
 #redis\u6570\u636E\u6E90\u914D\u7F6E
 redis.host=${db.host}
-redis.database=14
+redis.database=15
 redis.port=6379
 redis.password=
 spring.datasource.url=jdbc:mysql://${db.host}:${db.port}/${db.name}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
@@ -189,4 +189,4 @@ prefix.url.exam=api/oe
 
 #\u65E0\u9700\u9274\u6743\u7684url
 no.auth.urls=/webjars/**,/druid/**,/swagger-ui.html,/doc.html,/swagger-resources/**,/v2/api-docs,/webjars/springfox-swagger-ui/**,/api/oe/student/login,/file/**,/upload/**,/client/**,/base_photo/**
-common.system.urls=/api/admin/user/logout,/api/admin/sys/env
+common.system.urls=/api/oe/student/logout

+ 9 - 9
themis-exam/src/main/resources/ehcache.xml

@@ -15,13 +15,13 @@
             timeToLiveSeconds="2400"
             memoryStoreEvictionPolicy="LRU" />
 
-<!--    <cache-->
-<!--            name="account"-->
-<!--            eternal="false"-->
-<!--            maxElementsInMemory="1000"-->
-<!--            overflowToDisk="false"-->
-<!--            diskPersistent="false"-->
-<!--            timeToIdleSeconds="0"-->
-<!--            timeToLiveSeconds="2400"-->
-<!--            memoryStoreEvictionPolicy="LRU" />-->
+    <cache
+            name="student_cache"
+            eternal="false"
+            maxElementsInMemory="1000"
+            overflowToDisk="false"
+            diskPersistent="false"
+            timeToIdleSeconds="0"
+            timeToLiveSeconds="43200"
+            memoryStoreEvictionPolicy="LRU" />
 </ehcache>

+ 23 - 6
themis-mq/src/main/java/com/qmth/themis/mq/listener/RocketUserLogConsumer.java

@@ -5,6 +5,7 @@ import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.business.entity.TMRocketMessage;
 import com.qmth.themis.business.enums.MqEnum;
 import com.qmth.themis.business.enums.SystemOperationEnum;
+import com.qmth.themis.business.service.TEExamStudentLogService;
 import com.qmth.themis.business.service.TEUserLogService;
 import com.qmth.themis.business.service.TMRocketMessageService;
 import com.qmth.themis.business.util.JacksonUtil;
@@ -49,6 +50,9 @@ public class RocketUserLogConsumer implements MessageListenerConcurrently {
     @Resource
     TEUserLogService teUserLogService;
 
+    @Resource
+    TEExamStudentLogService teExamStudentLogService;
+
     @Resource
     TMRocketMessageService tmRocketMessageService;
 
@@ -61,18 +65,31 @@ public class RocketUserLogConsumer implements MessageListenerConcurrently {
             String threadName = Thread.currentThread().getName();
             Gson gson = new Gson();
             for (MessageExt messageExt : msgs) {
-                log.info(":{}-:{} userLogConsumer重试次数:{}", threadId, threadName, messageExt.getReconsumeTimes());
+                log.info(":{}-:{} logConsumer重试次数:{}", threadId, threadName, messageExt.getReconsumeTimes());
 //                MqDto mqDto = (MqDto) toJavaObject(parseObject(new String(messageExt.getBody(), Constants.CHARSET)), MqDto.class);
                 mqDto = JacksonUtil.readJson(new String(messageExt.getBody(), Constants.CHARSET), MqDto.class);
-                log.info(":{}-:{} userLogConsumer接收到的消息:{}", threadId, threadName, JacksonUtil.parseJson(mqDto));
-//                log.info(":{}-:{} userLogConsumer mqDto sequence:{},tag:{}", threadId, threadName, mqDto.getSequence(), mqDto.getTag());
-                if (Objects.nonNull(mqDto.getAck()) && mqDto.getAck().intValue() != SystemConstant.STANDARD_ACK_TYPE && Objects.nonNull(redisUtil.getMqTopicList(SystemConstant.USERLOG_TOPIC_BUFFER_LIST, mqDto.getId())) && redisUtil.lock(SystemConstant.REDIS_LOCK_MQ_PREFIX, mqDto.getId(), SystemConstant.REDIS_LOCK_MQ_TIME_OUT, TimeUnit.SECONDS)) {
+                log.info(":{}-:{} logConsumer接收到的消息:{}", threadId, threadName, JacksonUtil.parseJson(mqDto));
+                String tag = mqDto.getTag();
+                Object o = null;
+                String mqTopic = null;
+                if (tag.contains("user")) {
+                    o = redisUtil.getMqTopicList(SystemConstant.USERLOG_TOPIC_BUFFER_LIST, mqDto.getId());
+                    mqTopic = SystemConstant.USERLOG_TOPIC_BUFFER_LIST;
+                } else if (tag.contains("student")) {
+                    o = redisUtil.getMqTopicList(SystemConstant.STUDENTLOG_TOPIC_BUFFER_LIST, mqDto.getId());
+                    mqTopic = SystemConstant.STUDENTLOG_TOPIC_BUFFER_LIST;
+                }
+                if (Objects.nonNull(mqDto.getAck()) && mqDto.getAck().intValue() != SystemConstant.STANDARD_ACK_TYPE && Objects.nonNull(o) && redisUtil.lock(SystemConstant.REDIS_LOCK_MQ_PREFIX, mqDto.getId(), SystemConstant.REDIS_LOCK_MQ_TIME_OUT, TimeUnit.SECONDS)) {
                     log.info(":{}-:{} 插入用户轨迹日志", threadId, threadName);
-                    teUserLogService.saveUserLogInfo(mqDto.getTimestamp(), mqDto.getObjId(), MqEnum.valueOf(String.valueOf(mqDto.getType())).getId(), SystemOperationEnum.valueOf(String.valueOf(mqDto.getBody())).getCode(), JacksonUtil.parseJson(mqDto));
+                    if (tag.contains("user")) {
+                        teUserLogService.saveUserLogInfo(mqDto.getTimestamp(), mqDto.getObjId(), MqEnum.valueOf(String.valueOf(mqDto.getType())).getId(), SystemOperationEnum.valueOf(String.valueOf(mqDto.getBody())).getCode(), JacksonUtil.parseJson(mqDto));
+                    } else if (tag.contains("student")) {
+                        teExamStudentLogService.saveStudentLogInfo(mqDto.getTimestamp(), MqEnum.valueOf(String.valueOf(mqDto.getType())).getId(), SystemOperationEnum.valueOf(String.valueOf(mqDto.getBody())).getCode(), JacksonUtil.parseJson(mqDto));
+                    }
                     mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
                     TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
                     tmRocketMessageService.saveOrUpdate(tmRocketMessage);
-                    redisUtil.deleteMqTopicList(SystemConstant.USERLOG_TOPIC_BUFFER_LIST, mqDto.getId());
+//                    redisUtil.deleteMqTopicList(mqTopic, mqDto.getId());
                     return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                 } else {
                     log.info(":{}-:{} 消息ack未确认,重发", threadId, threadName);

+ 3 - 0
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqDtoServiceImpl.java

@@ -95,6 +95,9 @@ public class MqDtoServiceImpl implements MqDtoService {
                 case 0:
                     redisUtil.setMqTopicList(SystemConstant.SESSION_TOPIC_BUFFER_LIST, mqDto.getId(), mqDto);
                     break;
+                case 1:
+                    redisUtil.setMqTopicList(SystemConstant.STUDENTLOG_TOPIC_BUFFER_LIST, mqDto.getId(), mqDto);
+                    break;
                 case 5:
                     redisUtil.setMqTopicList(SystemConstant.USERLOG_TOPIC_BUFFER_LIST, mqDto.getId(), mqDto);
                     break;

+ 13 - 6
themis-task/src/main/java/com/qmth/themis/task/quartz/MqJob.java

@@ -31,14 +31,21 @@ public class MqJob extends QuartzJobBean {
     @Resource
     ProducerServer producerServer;
 
+    @Resource
+    MyThreadPool myThreadPool;
+
     @Override
     protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
-        log.info("session_topic_job进来了");
-        this.assembleJob(SystemConstant.SESSION_TOPIC_BUFFER_LIST);
-        log.info("userLog_topic_job进来了");
-        this.assembleJob(SystemConstant.USERLOG_TOPIC_BUFFER_LIST);
-        log.info("task_topic_job进来了");
-        this.assembleJob(SystemConstant.TASKLOG_TOPIC_BUFFER_LIST);
+        myThreadPool.arbitratePoolTaskExecutor.execute(() -> {
+            log.info("session_topic_job进来了");
+            this.assembleJob(SystemConstant.SESSION_TOPIC_BUFFER_LIST);
+            log.info("userLog_topic_job进来了");
+            this.assembleJob(SystemConstant.USERLOG_TOPIC_BUFFER_LIST);
+            log.info("studentLog_topic_job进来了");
+            this.assembleJob(SystemConstant.STUDENTLOG_TOPIC_BUFFER_LIST);
+            log.info("task_topic_job进来了");
+            this.assembleJob(SystemConstant.TASKLOG_TOPIC_BUFFER_LIST);
+        });
     }
 
     /**