xiatian 4 år sedan
förälder
incheckning
e808e550e2
17 ändrade filer med 496 tillägg och 52 borttagningar
  1. 22 9
      themis-backend/src/main/java/com/qmth/themis/backend/start/StartRunning.java
  2. 16 0
      themis-business/src/main/java/com/qmth/themis/business/cache/RedisKeyHelper.java
  3. 111 0
      themis-business/src/main/java/com/qmth/themis/business/cache/bean/LivenessVerifyCacheBean.java
  4. 9 8
      themis-business/src/main/java/com/qmth/themis/business/entity/TOeLivenessVerifyHistory.java
  5. 25 0
      themis-business/src/main/java/com/qmth/themis/business/enums/LivenessTypeEnum.java
  6. 8 0
      themis-business/src/main/java/com/qmth/themis/business/service/TOeLivenessVerifyHistoryService.java
  7. 1 1
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  8. 51 1
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeLivenessVerifyHistoryServiceImpl.java
  9. 2 3
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEFaceController.java
  10. 75 0
      themis-exam/src/main/java/com/qmth/themis/exam/api/TELivenessController.java
  11. 4 1
      themis-exam/src/main/java/com/qmth/themis/exam/start/StartRunning.java
  12. 10 3
      themis-mq/src/main/java/com/qmth/themis/mq/enums/MqGroupEnum.java
  13. 2 1
      themis-mq/src/main/java/com/qmth/themis/mq/enums/MqTagEnum.java
  14. 6 0
      themis-mq/src/main/java/com/qmth/themis/mq/service/MqLogicService.java
  15. 49 11
      themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java
  16. 79 0
      themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/LivenessVerifyConcurrentlyImpl.java
  17. 26 14
      themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

+ 22 - 9
themis-backend/src/main/java/com/qmth/themis/backend/start/StartRunning.java

@@ -1,12 +1,7 @@
 package com.qmth.themis.backend.start;
 
-import com.qmth.themis.business.constant.SpringContextHolder;
-import com.qmth.themis.business.constant.SystemConstant;
-import com.qmth.themis.mq.enums.MqGroupEnum;
-import com.qmth.themis.mq.enums.MqTagEnum;
-import com.qmth.themis.mq.enums.MqTopicEnum;
-import com.qmth.themis.mq.listener.RocketMessageConsumer;
-import com.qmth.themis.mq.templete.impl.*;
+import javax.annotation.Resource;
+
 import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -14,7 +9,18 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.Resource;
+import com.qmth.themis.business.constant.SpringContextHolder;
+import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.mq.enums.MqGroupEnum;
+import com.qmth.themis.mq.enums.MqTagEnum;
+import com.qmth.themis.mq.enums.MqTopicEnum;
+import com.qmth.themis.mq.listener.RocketMessageConsumer;
+import com.qmth.themis.mq.templete.impl.CalculateObjectiveScoreConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.FaceVerifyConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.SessionConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.TaskConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.UserLogConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.WebsocketUnNormalConcurrentlyImpl;
 
 /**
  * @Description: 服务启动时初始化运行,哪个微服务模块需要则拿此模版去用
@@ -77,7 +83,14 @@ public class StartRunning implements CommandLineRunner {
          * websocket mq end
          */
         //计算客观分
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.normalGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.calculateObjectiveScoreGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
+        
+        //人脸验证保存
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.faceVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.faceVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
+        
+        //活体验证保存
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.livenessVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.livenessVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
+        
         SystemConstant.initTempFiles();
         log.info("服务器启动时执行 end");
     }

+ 16 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/RedisKeyHelper.java

@@ -32,6 +32,12 @@ public class RedisKeyHelper {
 	 * 人脸验证
 	 */
 	private static String faceVerifyKeyPrefix = "face_verify::";
+	
+	/**
+	 * 活体验证
+	 */
+	private static String livenessVerifyKeyPrefix = "liveness_verify::";
+	
 
 	/**
 	 * 场次
@@ -118,5 +124,15 @@ public class RedisKeyHelper {
 	public static String faceVerifyCacheKey(Long id) {
 		return faceVerifyKeyPrefix + id;
 	}
+	
+	/**
+	 * 活体验证
+	 * 
+	 * @param id
+	 * @return
+	 */
+	public static String livenessVerifyCacheKey(Long id) {
+		return livenessVerifyKeyPrefix + id;
+	}
 
 }

+ 111 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/bean/LivenessVerifyCacheBean.java

@@ -0,0 +1,111 @@
+package com.qmth.themis.business.cache.bean;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.qmth.themis.business.enums.LivenessTypeEnum;
+
+/**活体验证记录
+ * @Description: 
+ * @Author: xiatian
+ * @Date: 2020-07-31
+ */
+public class LivenessVerifyCacheBean implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 281742662773373959L;
+
+	//主键
+    private Long id;
+
+    //考试记录ID
+    private Long examRecordId;
+
+    private LivenessTypeEnum type;
+
+    //随机动作与结果
+    private String actions;
+
+    //重试次数
+    private Integer retry;
+
+    //本地验证是否通过,0:不通过,1:通过
+    private Integer pass;
+
+    //开始时间
+    private Date startTime;
+
+    //完成时间
+    private Date finishTime;
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getExamRecordId() {
+        return examRecordId;
+    }
+
+    public void setExamRecordId(Long examRecordId) {
+        this.examRecordId = examRecordId;
+    }
+
+    public LivenessTypeEnum getType() {
+        return type;
+    }
+
+    public void setType(LivenessTypeEnum type) {
+        this.type = type;
+    }
+
+    public String getActions() {
+        return actions;
+    }
+
+    public void setActions(String actions) {
+        this.actions = actions;
+    }
+
+    public Integer getRetry() {
+        return retry;
+    }
+
+    public void setRetry(Integer retry) {
+        this.retry = retry;
+    }
+
+    public Integer getPass() {
+        return pass;
+    }
+
+    public void setPass(Integer pass) {
+        this.pass = pass;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getFinishTime() {
+        return finishTime;
+    }
+
+    public void setFinishTime(Date finishTime) {
+        this.finishTime = finishTime;
+    }
+
+}

+ 9 - 8
themis-business/src/main/java/com/qmth/themis/business/entity/TOeLivenessVerifyHistory.java

@@ -1,14 +1,15 @@
 package com.qmth.themis.business.entity;
 
+import java.io.Serializable;
+import java.util.Date;
+
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
-import com.qmth.themis.business.enums.ExamTypeEnum;
+import com.qmth.themis.business.enums.LivenessTypeEnum;
+
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
-import java.io.Serializable;
-import java.util.Date;
-
 /**
  * @Description: 活体验证记录
  * @Param:
@@ -28,9 +29,9 @@ public class TOeLivenessVerifyHistory implements Serializable {
     @TableField(value = "exam_record_id")
     private Long examRecordId;
 
-    @ApiModelProperty(value = "first:初次开考,recover:恢复开考,process:过程中")
+    @ApiModelProperty(value = "FIRST_START: 首次开考 RESUME_START: 断点恢复 IN_PROCESS: 过程中 WARNING_AUTO: 预警自动加入 INVIGILATE_MANUAL: 监考手工加入")
     @TableField(value = "type")
-    private ExamTypeEnum type;
+    private LivenessTypeEnum type;
 
     @ApiModelProperty(value = "随机动作与结果")
     @TableField(value = "actions")
@@ -72,11 +73,11 @@ public class TOeLivenessVerifyHistory implements Serializable {
         this.examRecordId = examRecordId;
     }
 
-    public ExamTypeEnum getType() {
+    public LivenessTypeEnum getType() {
         return type;
     }
 
-    public void setType(ExamTypeEnum type) {
+    public void setType(LivenessTypeEnum type) {
         this.type = type;
     }
 

+ 25 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/LivenessTypeEnum.java

@@ -0,0 +1,25 @@
+package com.qmth.themis.business.enums;
+
+/**
+ * 活体验证类型
+ * 
+ * @Description:
+ * @Author: xiatian
+ * @Date: 2020-07-31
+ */
+public enum LivenessTypeEnum {
+
+	FIRST_START("首次开考"),
+
+	RESUME_START("断点恢复"), IN_PROCESS("过程中"), WARNING_AUTO("预警自动加入"), INVIGILATE_MANUAL("监考手工加入");
+
+	private String title;
+
+	private LivenessTypeEnum(String title) {
+		this.title = title;
+	}
+
+	public String getTitle() {
+		return title;
+	}
+}

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

@@ -1,6 +1,7 @@
 package com.qmth.themis.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.bean.exam.LivenessVerifyBean;
 import com.qmth.themis.business.entity.TOeLivenessVerifyHistory;
 
 /**
@@ -12,4 +13,11 @@ import com.qmth.themis.business.entity.TOeLivenessVerifyHistory;
  */
 public interface TOeLivenessVerifyHistoryService extends IService<TOeLivenessVerifyHistory> {
 
+	LivenessVerifyBean verify(Long recordId, String type, String actions, Integer retry, Long startTime,
+			Long finishTime, Boolean pass);
+
+
+	void save(Long id, Long recordId, String type, String actions, Integer retry, Long startTime, Long finishTime,
+			Boolean pass);
+
 }

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

@@ -520,7 +520,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         ret.setReviewResult("");
         ExamRecordCacheUtil.setFinishTime(recordId, now);
         ExamRecordCacheUtil.setDurationSeconds(recordId, durationSeconds);
-        ExamRecordCacheUtil.setFinishType(recordId, FinishTypeEnum.valueOf(type.toLowerCase()));
+        ExamRecordCacheUtil.setFinishType(recordId, FinishTypeEnum.valueOf(type));
         ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.FINISHED);
         return ret;
     }

+ 51 - 1
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeLivenessVerifyHistoryServiceImpl.java

@@ -1,10 +1,22 @@
 package com.qmth.themis.business.service.impl;
 
+import java.util.Date;
+
+import javax.annotation.Resource;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.bean.exam.LivenessVerifyBean;
+import com.qmth.themis.business.cache.RedisKeyHelper;
+import com.qmth.themis.business.cache.bean.LivenessVerifyCacheBean;
 import com.qmth.themis.business.dao.TOeLivenessVerifyHistoryMapper;
 import com.qmth.themis.business.entity.TOeLivenessVerifyHistory;
+import com.qmth.themis.business.enums.LivenessTypeEnum;
 import com.qmth.themis.business.service.TOeLivenessVerifyHistoryService;
-import org.springframework.stereotype.Service;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.contanst.Constants;
 
 /**
  * @Description: 活体验证记录 服务实现类
@@ -16,4 +28,42 @@ import org.springframework.stereotype.Service;
 @Service
 public class TOeLivenessVerifyHistoryServiceImpl extends ServiceImpl<TOeLivenessVerifyHistoryMapper, TOeLivenessVerifyHistory> implements TOeLivenessVerifyHistoryService {
 
+	@Resource
+	RedisUtil redisUtil;
+	
+	@Override
+	public LivenessVerifyBean verify(Long recordId, String type, String actions, Integer retry, Long startTime,
+			Long finishTime, Boolean pass) {
+		LivenessVerifyCacheBean cache=new LivenessVerifyCacheBean();
+		cache.setId(Constants.idGen.next());
+		cache.setExamRecordId(recordId);
+		cache.setType(LivenessTypeEnum.valueOf(type));
+		cache.setActions(actions);
+		cache.setRetry(retry);
+		cache.setStartTime(new Date(startTime));
+		cache.setFinishTime(new Date(finishTime));
+		cache.setPass((pass?1:0));
+		redisUtil.set(RedisKeyHelper.livenessVerifyCacheKey(cache.getId()), cache);
+		LivenessVerifyBean ret=new LivenessVerifyBean();
+		ret.setId(cache.getId());
+		ret.setUpdateTime(new Date().getTime());
+		return ret;
+	}
+	
+	
+	@Transactional
+	@Override
+	public void save(Long id,Long recordId, String type, String actions, Integer retry, Long startTime,
+			Long finishTime, Boolean pass) {
+		TOeLivenessVerifyHistory entity=new TOeLivenessVerifyHistory();
+		entity.setId(id);
+		entity.setExamRecordId(recordId);
+		entity.setType(LivenessTypeEnum.valueOf(type));
+		entity.setActions(actions);
+		entity.setRetry(retry);
+		entity.setStartTime(new Date(startTime));
+		entity.setFinishTime(new Date(finishTime));
+		saveOrUpdate(entity);
+	}
+
 }

+ 2 - 3
themis-exam/src/main/java/com/qmth/themis/exam/api/TEFaceController.java

@@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import com.qmth.themis.business.bean.exam.FaceVerifyBean;
 import com.qmth.themis.business.enums.MqEnum;
-import com.qmth.themis.business.service.TEStudentService;
 import com.qmth.themis.business.service.TOeFaceVerifyHistoryService;
 import com.qmth.themis.mq.dto.MqDto;
 import com.qmth.themis.mq.enums.MqTagEnum;
@@ -49,13 +48,13 @@ public class TEFaceController {
 	@ApiResponses({ @ApiResponse(code = 200, message = "人脸验证信息") })
 	@Transactional
 	public FaceVerifyBean verify(@ApiParam(value = "考试记录ID", required = true) @RequestParam Long recordId,
-			@ApiParam(value = "first_start:首次开考, resume_start:断点恢复, in_process:过程中", required = true) @RequestParam String type,
+			@ApiParam(value = "FIRST_START:首次开考, RESUME_START:断点恢复, IN_PROCESS:过程中", required = true) @RequestParam String type,
 			@ApiParam(value = "照片文件URL", required = true) @RequestParam String photoUrl,
 			@ApiParam(value = "人脸数量", required = true) @RequestParam Integer faceCount,
 			@ApiParam(value = "相似度分数", required = true) @RequestParam Double similarity,
 			@ApiParam(value = "真实性结果", required = true) @RequestParam Double realness,
 			@ApiParam(value = "验证时间", required = true) @RequestParam Long time,
-			@ApiParam(value = "none: 无异常 face_count_error: 人脸数量异常 face_compare_error: 人脸比对异常 eye_close_error: 闭眼检测异常", required = true) @RequestParam String exception) {
+			@ApiParam(value = "NONE: 无异常 FACE_COUNT_ERROR: 人脸数量异常 FACE_COMPARE_ERROR: 人脸比对异常 EYE_CLOSE_ERROR: 闭眼检测异常", required = true) @RequestParam String exception) {
 		FaceVerifyBean ret=faceVerifyHistoryService.verify(recordId,type,photoUrl,faceCount,similarity,realness,time,exception);
 		Map<String, Object> transMap = new HashMap<String, Object>();
 		transMap.put("id", ret.getId());

+ 75 - 0
themis-exam/src/main/java/com/qmth/themis/exam/api/TELivenessController.java

@@ -0,0 +1,75 @@
+package com.qmth.themis.exam.api;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.qmth.themis.business.bean.exam.LivenessVerifyBean;
+import com.qmth.themis.business.enums.MqEnum;
+import com.qmth.themis.business.service.TOeLivenessVerifyHistoryService;
+import com.qmth.themis.mq.dto.MqDto;
+import com.qmth.themis.mq.enums.MqTagEnum;
+import com.qmth.themis.mq.enums.MqTopicEnum;
+import com.qmth.themis.mq.service.MqDtoService;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * 活体验证
+ * 
+ * @Description:
+ * @Author: xiatian
+ * @Date: 2020-08-03
+ */
+@Api(tags = "活体验证")
+@RestController
+@RequestMapping("/${prefix.url.exam}/liveness")
+public class TELivenessController {
+
+	@Resource
+	TOeLivenessVerifyHistoryService livenessVerifyHistoryService;
+
+	@Resource
+	MqDtoService mqDtoService;
+
+	@ApiOperation(value = "活体验证结果")
+	@RequestMapping(value = "/verify", method = RequestMethod.POST)
+	@ApiResponses({ @ApiResponse(code = 200, message = "活体验证信息") })
+	@Transactional
+	public LivenessVerifyBean verify(@ApiParam(value = "考试记录ID", required = true) @RequestParam Long recordId,
+			@ApiParam(value = "FIRST_START: 首次开考 RESUME_START: 断点恢复 IN_PROCESS: 过程中 WARNING_AUTO: 预警自动加入 INVIGILATE_MANUAL: 监考手工加入", required = true) @RequestParam String type,
+			@ApiParam(value = "动作详情", required = true) @RequestParam String actions,
+			@ApiParam(value = "整体第几次重试", required = true) @RequestParam Integer retry,
+			@ApiParam(value = "验证开始时间", required = true) @RequestParam Long startTime,
+			@ApiParam(value = "验证结束时间", required = true) @RequestParam Long finishTime,
+			@ApiParam(value = "本地验证是否通过", required = true) @RequestParam Boolean pass) {
+		LivenessVerifyBean ret = livenessVerifyHistoryService.verify(recordId, type, actions, retry, startTime,
+				finishTime, pass);
+		Map<String, Object> transMap = new HashMap<String, Object>();
+		transMap.put("id", ret.getId());
+		transMap.put("recordId", recordId);
+		transMap.put("type", type);
+		transMap.put("actions", actions);
+		transMap.put("retry", retry);
+		transMap.put("startTime", startTime);
+		transMap.put("finishTime", finishTime);
+		transMap.put("pass", pass);
+		// mq发送消息start
+		MqDto mqDto = new MqDto(MqTopicEnum.themisTopic.getCode(), MqTagEnum.livenessVerifySave.name(), transMap,
+				MqEnum.EXAM, null, null);
+		mqDtoService.assembleSendOneWayMsg(mqDto);
+		return ret;
+	}
+
+}

+ 4 - 1
themis-exam/src/main/java/com/qmth/themis/exam/start/StartRunning.java

@@ -85,11 +85,14 @@ public class StartRunning implements CommandLineRunner {
          * websocket mq end
          */
         //计算客观分
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.normalGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.calculateObjectiveScoreGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
         
         //人脸验证保存
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.faceVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.faceVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
         
+        //活体验证保存
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.livenessVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.livenessVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
+        
         
         SystemConstant.initTempFiles();
         log.info("服务器启动时执行 end");

+ 10 - 3
themis-mq/src/main/java/com/qmth/themis/mq/enums/MqGroupEnum.java

@@ -85,11 +85,18 @@ public enum MqGroupEnum {
     quartzConsumerExamActivityGroup("themis-group-exam-quartzExamActivity"),
 	
     /**
-     * 通用分组
+     * 计算客观分
      */
-    normalGroup("themis-group-exam-normal"),
+    calculateObjectiveScoreGroup("themis-group-exam-calculateObjectiveScore"),
 
-    faceVerifySaveGroup("themis-group-exam-faceVerifySave");
+    /**
+     * 人脸验证
+     */
+    faceVerifySaveGroup("themis-group-exam-faceVerifySave"),
+    /**
+     * 活体验证
+     */
+    livenessVerifySaveGroup("themis-group-exam-livenessVerifySave");
 
     private MqGroupEnum(String code) {
         this.code = code;

+ 2 - 1
themis-mq/src/main/java/com/qmth/themis/mq/enums/MqTagEnum.java

@@ -26,7 +26,8 @@ public enum MqTagEnum {
     examActivity("考场一次性延时任务标签"),
     quartz("quartz标签"),
     calculateObjectiveScore("计算客观分标签"),
-    faceVerifySave("人脸验证保存");
+    faceVerifySave("人脸验证保存"),
+    livenessVerifySave("活体验证保存");
 
     private MqTagEnum(String code) {
         this.code = code;

+ 6 - 0
themis-mq/src/main/java/com/qmth/themis/mq/service/MqLogicService.java

@@ -64,4 +64,10 @@ public interface MqLogicService {
 	 * @param key
 	 */
 	public void execMqFaceVerifySaveLogic(MqDto mqDto, String key);
+	
+	/**活体验证保存
+	 * @param mqDto
+	 * @param key
+	 */
+	public void execMqLivenessVerifySaveLogic(MqDto mqDto, String key);
 }

+ 49 - 11
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -1,5 +1,16 @@
 package com.qmth.themis.mq.service.impl;
 
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.annotation.Resource;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.google.gson.Gson;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.constant.SpringContextHolder;
@@ -8,8 +19,19 @@ import com.qmth.themis.business.entity.TBSession;
 import com.qmth.themis.business.entity.TMRocketMessage;
 import com.qmth.themis.business.entity.TOeExamBreakHistory;
 import com.qmth.themis.business.entity.TOeExamRecord;
-import com.qmth.themis.business.enums.*;
-import com.qmth.themis.business.service.*;
+import com.qmth.themis.business.enums.BreakReasonEnum;
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.MqEnum;
+import com.qmth.themis.business.enums.SystemOperationEnum;
+import com.qmth.themis.business.enums.WebsocketStatusEnum;
+import com.qmth.themis.business.service.TBSessionService;
+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.service.TOeExamBreakHistoryService;
+import com.qmth.themis.business.service.TOeExamRecordService;
+import com.qmth.themis.business.service.TOeFaceVerifyHistoryService;
+import com.qmth.themis.business.service.TOeLivenessVerifyHistoryService;
 import com.qmth.themis.business.templete.TaskExportTemplete;
 import com.qmth.themis.business.templete.TaskImportTemplete;
 import com.qmth.themis.business.templete.impl.TaskExamPaperImportTemplete;
@@ -21,15 +43,6 @@ import com.qmth.themis.business.util.JacksonUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.mq.dto.MqDto;
 import com.qmth.themis.mq.service.MqLogicService;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Resource;
-import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
 
 /**
  * @Description: mq执行逻辑 impl
@@ -70,6 +83,11 @@ public class MqLogicServiceImpl implements MqLogicService {
 
     @Resource
     TOeFaceVerifyHistoryService faceVerifyHistoryService;
+    
+    @Resource
+    TOeLivenessVerifyHistoryService livenessVerifyHistoryService;
+    
+    
 
     /**
      * mq最大重试次数逻辑
@@ -273,4 +291,24 @@ public class MqLogicServiceImpl implements MqLogicService {
         tmRocketMessageService.saveOrUpdate(tmRocketMessage);
         redisUtil.delete(key, mqDto.getId());
     }
+
+	@Override
+	public void execMqLivenessVerifySaveLogic(MqDto mqDto, String key) {
+		Gson gson = new Gson();
+        Map<String, Object> param = (Map<String, Object>) mqDto.getBody();
+        Long id = (Long) param.get("id");
+        Long recordId = (Long) param.get("recordId");
+        String type = (String) param.get("type");
+        String actions = (String) param.get("actions");
+        Integer retry = (Integer) param.get("retry");
+        Long startTime = (Long) param.get("startTime");
+        Long finishTime = (Long) param.get("finishTime");
+        Boolean pass = (Boolean) param.get("pass");
+        livenessVerifyHistoryService.save(id, recordId, type, actions, retry, startTime, finishTime, pass);
+        mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
+        TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
+        tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
+        tmRocketMessageService.saveOrUpdate(tmRocketMessage);
+        redisUtil.delete(key, mqDto.getId());
+	}
 }

+ 79 - 0
themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/LivenessVerifyConcurrentlyImpl.java

@@ -0,0 +1,79 @@
+package com.qmth.themis.mq.templete.impl;
+
+import java.util.List;
+import java.util.Objects;
+
+import javax.annotation.Resource;
+
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.util.JacksonUtil;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.contanst.Constants;
+import com.qmth.themis.mq.dto.MqDto;
+import com.qmth.themis.mq.service.MqLogicService;
+import com.qmth.themis.mq.templete.Concurrently;
+
+/**
+ * 活体验证保存
+ *
+ * @Description:
+ * @Author: xiatian
+ * @Date: 2020-07-30
+ */
+@Service
+public class LivenessVerifyConcurrentlyImpl implements Concurrently {
+    private final static Logger log = LoggerFactory.getLogger(LivenessVerifyConcurrentlyImpl.class);
+    
+	@Resource
+	RedisUtil redisUtil;
+	@Resource
+	MqLogicService mqLogicService;
+
+    @Override
+    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
+                                                    ConsumeConcurrentlyContext consumeConcurrentlyContext) {
+        MqDto mqDto = null;
+        try {
+            long threadId = Thread.currentThread().getId();
+            String threadName = Thread.currentThread().getName();
+            for (MessageExt messageExt : msgs) {
+                log.debug(":{}-:{} CalculateObjectiveScore 重试次数:{}", threadId, threadName,
+                        messageExt.getReconsumeTimes());
+                mqDto = JacksonUtil.readJson(new String(messageExt.getBody(), Constants.CHARSET), MqDto.class);
+                log.debug(":{}-:{} CalculateObjectiveScore 接收到的消息:{}", threadId, threadName,
+                        JacksonUtil.parseJson(mqDto));
+                int reconsumeTime = messageExt.getReconsumeTimes();
+                if (reconsumeTime >= SystemConstant.MAXRECONSUMETIMES) {
+                    mqLogicService.execMqWebsocketUnNormalLogic(mqDto, SystemConstant.MQ_TOPIC_BUFFER_LIST);
+                } else {
+                    if (Objects.nonNull(mqDto.getAck()) && mqDto.getAck().intValue() != SystemConstant.STANDARD_ACK_TYPE
+                            && Objects.nonNull(redisUtil.get(SystemConstant.MQ_TOPIC_BUFFER_LIST, mqDto.getId()))
+                            && redisUtil.lock(SystemConstant.REDIS_LOCK_MQ_PREFIX + mqDto.getId(),
+                            SystemConstant.REDIS_LOCK_MQ_TIME_OUT)) {
+                        log.debug(":{}-:{} 更新db", threadId, threadName);
+                        mqLogicService.execMqFaceVerifySaveLogic(mqDto, SystemConstant.MQ_TOPIC_BUFFER_LIST);
+                        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+                    } else {
+                        log.debug(":{}-:{} 消息ack未确认,重发", threadId, threadName);
+                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;// 重试
+                    }
+                }
+            }
+        } catch (Exception e) {
+        	log.error("人脸验证保存,消息消费出错",e);
+            return ConsumeConcurrentlyStatus.RECONSUME_LATER;//重试
+        } finally {
+            if (Objects.nonNull(mqDto)) {
+                redisUtil.releaseLock(SystemConstant.REDIS_LOCK_MQ_PREFIX + mqDto.getId());
+            }
+        }
+        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;// 成功
+    }
+}

+ 26 - 14
themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

@@ -1,26 +1,32 @@
 package com.qmth.themis.task.start;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.mq.enums.MqGroupEnum;
 import com.qmth.themis.mq.enums.MqTagEnum;
 import com.qmth.themis.mq.enums.MqTopicEnum;
 import com.qmth.themis.mq.listener.RocketMessageConsumer;
-import com.qmth.themis.mq.templete.impl.*;
-import com.qmth.themis.task.config.DictionaryConfig;
+import com.qmth.themis.mq.templete.impl.CalculateObjectiveScoreConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.FaceVerifyConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.SessionConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.TaskConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.UserLogConcurrentlyImpl;
+import com.qmth.themis.mq.templete.impl.WebsocketUnNormalConcurrentlyImpl;
 import com.qmth.themis.task.enums.QuartzTaskEnum;
 import com.qmth.themis.task.listener.QuartzOrderlyImpl;
 import com.qmth.themis.task.quartz.MqJob;
 import com.qmth.themis.task.service.QuartzService;
-import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * @Description: 服务启动时初始化运行,哪个微服务模块需要则拿此模版去用
@@ -93,8 +99,14 @@ public class StartRunning implements CommandLineRunner {
          * websocket mq end
          */
         //计算客观分
-        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.normalGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
-
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.calculateObjectiveScoreGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.calculateObjectiveScore.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(CalculateObjectiveScoreConcurrentlyImpl.class));
+        
+        //人脸验证保存
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.faceVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.faceVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
+        
+        //活体验证保存
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.livenessVerifySaveGroup.getCode(), MqTopicEnum.themisTopic.getCode(), MqTagEnum.livenessVerifySave.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(FaceVerifyConcurrentlyImpl.class));
+        
         /**
          * quartz mq start
          */