lideyin 5 rokov pred
rodič
commit
ebfa28bdcd

+ 12 - 13
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/ExamCaptureQueueService.java

@@ -1,6 +1,5 @@
 package cn.com.qmth.examcloud.core.oe.student.face.service;
 
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
 import cn.com.qmth.examcloud.core.oe.common.enums.ExamCaptureQueueStatus;
 import cn.com.qmth.examcloud.core.oe.student.face.service.bean.SaveExamCaptureQueueInfo;
 
@@ -12,12 +11,20 @@ import cn.com.qmth.examcloud.core.oe.student.face.service.bean.SaveExamCaptureQu
  */
 public interface ExamCaptureQueueService {
 
+    /**
+     * 处理失败时,保存队列信息
+     * @param captureQueueId
+     * @param errorMsg
+     * @param examCaptureQueueStatus
+     */
+    boolean saveExamCaptureQueueEntityByFailed(Long captureQueueId, String errorMsg,
+                                               ExamCaptureQueueStatus examCaptureQueueStatus);
+
     /**
      * 保存考试抓拍照片队列
-     * @param examRecordDataId
-     * @param baseFaceToken
-     * @param fileUrl
-     * @param fileName
+     * @param saveExamCaptureQueueInfo
+     * @param studentId
+     * @return
      */
     String saveExamCaptureQueue(SaveExamCaptureQueueInfo saveExamCaptureQueueInfo, Long studentId);
     /**
@@ -30,12 +37,4 @@ public interface ExamCaptureQueueService {
      */
     void changeExamCaptureQueueStatus();
     
-    /**
-     * 处理失败时,保存队列信息
-     * @param examCaptureQueueEntity
-     * @param errorMsg
-     */
-    void saveExamCaptureQueueEntityByFailed(ExamCaptureQueueEntity examCaptureQueueEntity,
-                                            String errorMsg, ExamCaptureQueueStatus examCaptureQueueStatus);
-
 }

+ 11 - 20
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/ExamCaptureService.java

@@ -1,14 +1,12 @@
 package cn.com.qmth.examcloud.core.oe.student.face.service;
 
+import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureEntity;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.CompareFaceSyncInfo;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.ExamCaptureQueueInfo;
 import org.json.JSONException;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureEntity;
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
-import cn.com.qmth.examcloud.core.oe.student.face.service.bean.CallType;
-import cn.com.qmth.examcloud.core.oe.student.face.service.bean.CompareFaceSyncInfo;
-
 /**
  * 
  * @author  	chenken
@@ -17,17 +15,10 @@ import cn.com.qmth.examcloud.core.oe.student.face.service.bean.CompareFaceSyncIn
  * @description 考试抓拍服务接口 
  */
 public interface ExamCaptureService {
-
-    //face++人脸比对失败时,需要将状态置为失败,并清空批次号
-    void disposeFaceCompareFaild(ExamCaptureQueueEntity examCaptureQueue);
-
-	//百度活体检测失败时,需要将状态置为失败,并清空批次号
-	void disposeBaiDuFaceLivenessFaild(ExamCaptureQueueEntity examCaptureQueue);
-
-	void disposeBaiDuFaceLiveness(ExamCaptureQueueEntity examCaptureQueue) throws JSONException;
+	void disposeBaiDuFaceLiveness(ExamCaptureQueueInfo examCaptureQueue) throws JSONException;
 
     @Transactional
-    void saveExamCaptureAndDeleteQueue(ExamCaptureQueueEntity examCaptureQueue);
+    void saveExamCaptureAndDeleteQueue(ExamCaptureQueueInfo examCaptureQueue);
 
     /**
 	 * 同步比较人脸:用于进入考试
@@ -36,8 +27,8 @@ public interface ExamCaptureService {
 	 * @param file				抓拍照片 File
 	 * @return
 	 */
-	public CompareFaceSyncInfo compareFaceSyncByFile(Long studentId,String baseFaceToken,CommonsMultipartFile file);
-	
+	public CompareFaceSyncInfo compareFaceSyncByFile(Long studentId, String baseFaceToken, CommonsMultipartFile file);
+
 	/**
 	 * 同步比较人脸:用于进入考试
 	 * @param studentId			学生ID
@@ -45,17 +36,17 @@ public interface ExamCaptureService {
 	 * @param fileUrl				抓拍照片Url
 	 * @return
 	 */
-	public CompareFaceSyncInfo compareFaceSyncByFileUrl(Long studentId,String baseFaceToken,String fileUrl);
+	public CompareFaceSyncInfo compareFaceSyncByFileUrl(Long studentId, String baseFaceToken, String fileUrl);
 
 	/**
 	 * 获取考试抓拍结果
 	 * @param examRecordDataId
 	 * @return
 	 */
-	public ExamCaptureEntity getExamCaptureResult(Long examRecordDataId,String fileName);
+	public ExamCaptureEntity getExamCaptureResult(Long examRecordDataId, String fileName);
 	/**
 	 * 处理单个考试抓拍照片数据
-	 * @param examCaptureQueueEntity
+	 * @param examCaptureQueueInfo
 	 */
-	void disposeFaceCompare(ExamCaptureQueueEntity examCaptureQueueEntity) throws JSONException;
+	void disposeFaceCompare(ExamCaptureQueueInfo examCaptureQueueInfo) throws JSONException;
 }

+ 290 - 0
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/bean/ExamCaptureQueueInfo.java

@@ -0,0 +1,290 @@
+package cn.com.qmth.examcloud.core.oe.student.face.service.bean;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+import cn.com.qmth.examcloud.core.oe.common.enums.ExamCaptureQueueStatus;
+
+import java.util.Date;
+
+/**
+ * @Description 照片抓拍队列bean
+ * @Author lideyin
+ * @Date 2019/9/26 14:24
+ * @Version 1.0
+ */
+public class ExamCaptureQueueInfo implements JsonSerializable {
+    /**
+     *
+     */
+    private static final long serialVersionUID = 4094671807731989565L;
+
+    private Long id;
+
+    private Long studentId;
+
+    /**
+     * ec_oe_exam_record_data  ID
+     */
+    private Long examRecordDataId;
+
+
+    /**
+     * 底照Token
+     */
+    private String baseFaceToken;
+
+    /**
+     * 文件URL
+     */
+    private String fileUrl;
+
+    /**
+     * 文件名称
+     */
+    private String fileName;
+
+    /**
+     * 状态
+     */
+    private ExamCaptureQueueStatus status;
+
+    /**
+     * 错误信息
+     */
+    private String errorMsg;
+
+    /**
+     * 错误次数
+     */
+    private Integer errorNum;
+
+    /**
+     * 是否存在虚拟摄像头
+     */
+    private Boolean hasVirtualCamera;
+
+    /**
+     * 摄像头信息  json字符串数组
+     */
+    private String cameraInfos;
+
+    /**
+     * 其他信息
+     * Json格式
+     * {
+     * "":""
+     * }
+     */
+    private String extMsg;
+
+    /**
+     * 队列处理批次号(用户判断某一条数据处理状态)
+     */
+    private String processBatchNum;
+
+    /**
+     * 队列处理的优先级,默认值为0
+     */
+    private int priority = 0;
+
+    /**
+     * 是否有陌生人
+     * 就是摄像头拍到不止考生一人
+     */
+    private Boolean isStranger;
+    /**
+     * 比较是否通过
+     */
+    private Boolean isPass;
+
+    /**
+     * 人脸比较返回信息
+     */
+    private String faceCompareResult;
+    /**
+     * 人脸比对开始时间
+     */
+    private Long faceCompareStartTime;
+
+    /**
+     * 百度在线活体检测结果
+     */
+    private String facelivenessResult;
+
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+
+    /**
+     * 创建时间
+     */
+    private Date creationTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Long studentId) {
+        this.studentId = studentId;
+    }
+
+    public Long getExamRecordDataId() {
+        return examRecordDataId;
+    }
+
+    public void setExamRecordDataId(Long examRecordDataId) {
+        this.examRecordDataId = examRecordDataId;
+    }
+
+    public String getBaseFaceToken() {
+        return baseFaceToken;
+    }
+
+    public void setBaseFaceToken(String baseFaceToken) {
+        this.baseFaceToken = baseFaceToken;
+    }
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public ExamCaptureQueueStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ExamCaptureQueueStatus status) {
+        this.status = status;
+    }
+
+    public String getErrorMsg() {
+        return errorMsg;
+    }
+
+    public void setErrorMsg(String errorMsg) {
+        this.errorMsg = errorMsg;
+    }
+
+    public Integer getErrorNum() {
+        return errorNum;
+    }
+
+    public void setErrorNum(Integer errorNum) {
+        this.errorNum = errorNum;
+    }
+
+    public Boolean getHasVirtualCamera() {
+        return hasVirtualCamera;
+    }
+
+    public void setHasVirtualCamera(Boolean hasVirtualCamera) {
+        this.hasVirtualCamera = hasVirtualCamera;
+    }
+
+    public String getCameraInfos() {
+        return cameraInfos;
+    }
+
+    public void setCameraInfos(String cameraInfos) {
+        this.cameraInfos = cameraInfos;
+    }
+
+    public String getExtMsg() {
+        return extMsg;
+    }
+
+    public void setExtMsg(String extMsg) {
+        this.extMsg = extMsg;
+    }
+
+    public String getProcessBatchNum() {
+        return processBatchNum;
+    }
+
+    public void setProcessBatchNum(String processBatchNum) {
+        this.processBatchNum = processBatchNum;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public Boolean getStranger() {
+        return isStranger;
+    }
+
+    public void setStranger(Boolean stranger) {
+        isStranger = stranger;
+    }
+
+    public Boolean getPass() {
+        return isPass;
+    }
+
+    public void setPass(Boolean pass) {
+        isPass = pass;
+    }
+
+    public String getFaceCompareResult() {
+        return faceCompareResult;
+    }
+
+    public void setFaceCompareResult(String faceCompareResult) {
+        this.faceCompareResult = faceCompareResult;
+    }
+
+    public Long getFaceCompareStartTime() {
+        return faceCompareStartTime;
+    }
+
+    public void setFaceCompareStartTime(Long faceCompareStartTime) {
+        this.faceCompareStartTime = faceCompareStartTime;
+    }
+
+    public String getFacelivenessResult() {
+        return facelivenessResult;
+    }
+
+    public void setFacelivenessResult(String facelivenessResult) {
+        this.facelivenessResult = facelivenessResult;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Date getCreationTime() {
+        return creationTime;
+    }
+
+    public void setCreationTime(Date creationTime) {
+        this.creationTime = creationTime;
+    }
+}

+ 24 - 10
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/impl/BaiduFaceLivenessWorker.java

@@ -5,8 +5,10 @@ import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.Worker;
 import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.WorkerController;
 import cn.com.qmth.examcloud.commons.util.Util;
 import cn.com.qmth.examcloud.core.oe.common.base.Constants;
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
+import cn.com.qmth.examcloud.core.oe.common.enums.ExamCaptureQueueStatus;
+import cn.com.qmth.examcloud.core.oe.student.face.service.ExamCaptureQueueService;
 import cn.com.qmth.examcloud.core.oe.student.face.service.ExamCaptureService;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.ExamCaptureQueueInfo;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -19,11 +21,11 @@ import java.util.concurrent.TimeUnit;
  *
  * @author lideyin 20190620
  */
-public class BaiduFaceLivenessWorker implements Worker<ExamCaptureQueueEntity> {
+public class BaiduFaceLivenessWorker implements Worker<ExamCaptureQueueInfo> {
 	private final Log captureLog = LogFactory.getLog("PROCESS_EXAM_CAPTURE_TASK_LOGGER");
 
 	@Override
-	public void process(WorkerController controller, ExamCaptureQueueEntity element) {
+	public void process(WorkerController controller, ExamCaptureQueueInfo element) {
 		ThreadContext.put("TRACE_ID", "Q_" + element.getId());
 		ThreadContext.put("CALLER", "BAIDU_WORKER");
 		ExamCaptureProcessStatisticController.increaseFaceLivenessDetectCount();
@@ -33,16 +35,23 @@ public class BaiduFaceLivenessWorker implements Worker<ExamCaptureQueueEntity> {
 		}
 		ExamCaptureService examCaptureService = SpringContextHolder
 				.getBean(ExamCaptureService.class);
+		ExamCaptureQueueService examCaptureQueueService = SpringContextHolder
+				.getBean(ExamCaptureQueueService.class);
 		try {
 			examCaptureService.disposeBaiDuFaceLiveness(element);
 		} catch (StatusException e) {
-
-			// 异常处理
-			element.setErrorMsg(e.getDesc());
-			examCaptureService.disposeBaiDuFaceLivenessFaild(element);
+			while (true){
+				// 异常处理
+				if(examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(),e.getDesc(),
+						ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED)){
+					break;
+				};
+				Util.sleep(TimeUnit.MILLISECONDS,500);
+			}
 			if ((e.getCode().equals(Constants.BAIDU_FACELIVENESS_QPS_LIMIT_EXCEEDED_CODE))) {
 				// 如果超过并发次数,则添加异常次数
 				controller.addConcurrencyWarn();
+				captureLog.error("[BAIDU_FACELIVENESS_WORKER.] 超过并发次数 " , e);
 			} else {
 				ExamCaptureProcessStatisticController.increaseFaceLivenessDetectCount();
 				captureLog.error("[BAIDU_FACELIVENESS_WORKER.] 自定义异常 " + e.getDesc(), e);
@@ -50,9 +59,14 @@ public class BaiduFaceLivenessWorker implements Worker<ExamCaptureQueueEntity> {
 			Util.sleep(TimeUnit.MICROSECONDS, 50);
 		} catch (Exception e) {
 			ExamCaptureProcessStatisticController.increaseFaceLivenessDetectCount();
-			// 异常处理
-			element.setErrorMsg(e.getMessage());
-			examCaptureService.disposeBaiDuFaceLivenessFaild(element);
+			while (true){
+				// 异常处理
+				if(examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(),e.getMessage(),
+						ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED)){
+					break;
+				};
+				Util.sleep(TimeUnit.MILLISECONDS,500);
+			}
 			captureLog.error("[BAIDU_FACELIVENESS_WORKER.] 系统异常 " + e.getMessage(), e);
 			Util.sleep(TimeUnit.MICROSECONDS, 50);
 		}finally {

+ 13 - 16
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/impl/ExamCaptureQueueServiceImpl.java

@@ -4,9 +4,6 @@ import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.AES;
 import cn.com.qmth.examcloud.commons.util.StringUtil;
 import cn.com.qmth.examcloud.commons.util.UrlUtil;
-import cn.com.qmth.examcloud.core.basic.api.FaceCloudService;
-import cn.com.qmth.examcloud.core.basic.api.request.GetStudentFaceReq;
-import cn.com.qmth.examcloud.core.basic.api.response.GetStudentFaceResp;
 import cn.com.qmth.examcloud.core.oe.common.base.utils.Check;
 import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
 import cn.com.qmth.examcloud.core.oe.common.enums.ExamCaptureQueueStatus;
@@ -16,6 +13,8 @@ import cn.com.qmth.examcloud.core.oe.student.face.service.bean.SaveExamCaptureQu
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.StudentCacheBean;
 import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,13 +33,10 @@ import java.util.*;
 public class ExamCaptureQueueServiceImpl implements ExamCaptureQueueService {
 
     private static final Logger log = LoggerFactory.getLogger(ExamCaptureQueueServiceImpl.class);
+    private final Log captureLog = LogFactory.getLog("PROCESS_EXAM_CAPTURE_TASK_LOGGER");
 
     @Autowired
     private ExamCaptureQueueRepo examCaptureQueueRepo;
-
-    @Autowired
-    private FaceCloudService faceCloudService;
-
     /**
      * 一次启动的线程个数
      */
@@ -91,15 +87,16 @@ public class ExamCaptureQueueServiceImpl implements ExamCaptureQueueService {
     }
 
     @Override
-    public void saveExamCaptureQueueEntityByFailed(ExamCaptureQueueEntity examCaptureQueueEntity,
-                                                   String errorMsg, ExamCaptureQueueStatus examCaptureQueueStatus) {
-        examCaptureQueueEntity.setErrorMsg(errorMsg);
-        examCaptureQueueEntity.setStatus(examCaptureQueueStatus);
-        examCaptureQueueEntity.setUpdateTime(new Date());
-        int errorNum = examCaptureQueueEntity.getErrorNum() == null ? 0 : examCaptureQueueEntity.getErrorNum();
-        examCaptureQueueEntity.setErrorNum(errorNum + 1);
-        examCaptureQueueEntity.setProcessBatchNum("000000");
-        examCaptureQueueRepo.save(examCaptureQueueEntity);
+    public boolean saveExamCaptureQueueEntityByFailed(Long captureQueueId, String errorMsg,
+                                                      ExamCaptureQueueStatus examCaptureQueueStatus) {
+        try {
+            examCaptureQueueRepo.saveExamCaptureQueueEntityByFailed(captureQueueId, errorMsg, examCaptureQueueStatus.toString(),
+                    "000000", new Date());
+            return true;
+        } catch (Exception e) {
+            captureLog.error("[UPDATE_FAILED_CAPTURE_QUEUE] 保存照片队列处理失败数据时出现异常",e);
+            return false;
+        }
     }
 
     @Override

+ 35 - 36
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/impl/ExamCaptureServiceImpl.java

@@ -4,7 +4,6 @@ import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.helpers.JsonHttpResponseHolder;
 import cn.com.qmth.examcloud.core.oe.common.base.Constants;
 import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureEntity;
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
 import cn.com.qmth.examcloud.core.oe.common.enums.ExamCaptureQueueStatus;
 import cn.com.qmth.examcloud.core.oe.common.enums.ExamProperties;
 import cn.com.qmth.examcloud.core.oe.common.repository.ExamCaptureQueueRepo;
@@ -15,6 +14,7 @@ import cn.com.qmth.examcloud.core.oe.student.face.service.ExamCaptureQueueServic
 import cn.com.qmth.examcloud.core.oe.student.face.service.ExamCaptureService;
 import cn.com.qmth.examcloud.core.oe.student.face.service.FaceCompareService;
 import cn.com.qmth.examcloud.core.oe.student.face.service.bean.CompareFaceSyncInfo;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.ExamCaptureQueueInfo;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.ExamRecordPropertyCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
@@ -37,6 +37,7 @@ import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
 import java.io.*;
+import java.util.Date;
 
 /**
  * @author chenken
@@ -80,7 +81,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
      */
     @Override
     @Transactional
-    public void disposeFaceCompare(ExamCaptureQueueEntity examCaptureQueue) {
+    public void disposeFaceCompare(ExamCaptureQueueInfo examCaptureQueue) {
         //将队列记录修改为处理中
         examCaptureQueueRepo.updateExamCaptureQueueStatusWithProcessing(examCaptureQueue.getId());
         examCaptureQueue.setFaceCompareStartTime(System.currentTimeMillis());
@@ -130,13 +131,15 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
             }
             examCaptureQueue.setFaceCompareResult(faceCompareResult.toString());
 
+            //人脸比对出错的处理
             if (faceCompareResult.containsKey(Constants.ERROR_MSG)) {
                 String errMsg = faceCompareResult.getString(Constants.ERROR_MSG);
 
                 //如果API并发次数超过上限,则保存错误信息到队列,并抛出异常,用于协调满载队列线程
                 if (errMsg.contains(Constants.FACE_COMPARE_CONCURRENCY_LIMIT_EXCEEDED)) {
-                    examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue,
-                            "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceCompareResult.toString(), ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
+                    examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
+                            "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceCompareResult.toString(),
+                            ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
 
                     captureLog.debug("[DISPOSE_FACE_COMPARE] face++人脸比对接口超过最大并发次数");
 
@@ -181,27 +184,30 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
 
                 captureLog.debug("[DISPOSE_FACE_COMPARE] face++人脸比对出现错误,即将重试,errMsg:" + errMsg);
                 // 其它错误类型,保存错误信息到队列中,待自动重新服务处理
-                examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue,
-                        "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceCompareResult.toString(), ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
+                examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
+                        "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceCompareResult.toString(),
+                        ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
                 ExamCaptureProcessStatisticController.increaseFaceCompareFailedCount();//增加错误次数
                 captureLog.debug("[DISPOSE_FACE_COMPARE] face++人脸比对出现错误,增加错误次数后failedCount:" +
-                        ExamCaptureProcessStatisticController.getFaceCompareFailedCount()+",totalCount="+
+                        ExamCaptureProcessStatisticController.getFaceCompareFailedCount() + ",totalCount=" +
                         ExamCaptureProcessStatisticController.getFaceCompareCount());
-            } else {
+            }
+            //人脸比对没有出错的情况
+            else {
                 //face++的结果检测到人脸,才执行百度活体检测
                 if (faceCompareResult.containsKey("confidence")) {
-                    examCaptureQueue.setIsPass(calculateFaceCompareIsPass(faceCompareResult));
-                    examCaptureQueue.setIsStranger(calculateFaceCompareIsStranger(examCaptureQueue.getExamRecordDataId(), faceCompareResult));
+                    examCaptureQueue.setPass(calculateFaceCompareIsPass(faceCompareResult));
+                    examCaptureQueue.setStranger(calculateFaceCompareIsStranger(examCaptureQueue.getExamRecordDataId(), faceCompareResult));
                     //更新队列状态为face++比对完成
                     examCaptureQueue.setStatus(ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_COMPLETE);
-                    examCaptureQueueRepo.save(examCaptureQueue);
+                    disposeFaceCompareSuccessful(examCaptureQueue);
 
                     captureLog.debug("[DISPOSE_FACE_COMPARE] face++人脸比对完成,即将进行百度活体检测,耗时:" + (System.currentTimeMillis() - startTime) + " ms");
                 }
                 //face++ 没有检测到人脸,直接保存人脸检测最终结果并删除队列
                 else {
-                    examCaptureQueue.setIsPass(false);
-                    examCaptureQueue.setIsStranger(false);
+                    examCaptureQueue.setPass(false);
+                    examCaptureQueue.setStranger(false);
                     saveExamCaptureAndDeleteQueue(examCaptureQueue);
 
                     captureLog.debug("[DISPOSE_FACE_COMPARE] face++人脸比对完成,且未检测到人脸,耗时:" + (System.currentTimeMillis() - startTime) + " ms");
@@ -210,20 +216,12 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
         } while (retry);
     }
 
-    @Override
-    //face++人脸比对失败时,需要将状态置为失败,并清空批次号
-    public void disposeFaceCompareFaild(ExamCaptureQueueEntity examCaptureQueue) {
-        examCaptureQueue.setStatus(ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
-        examCaptureQueue.setProcessBatchNum("000000");
-        examCaptureQueueRepo.save(examCaptureQueue);
-    }
-
-    @Override
-    //百度活体检测失败时,需要将状态置为失败,并清空批次号
-    public void disposeBaiDuFaceLivenessFaild(ExamCaptureQueueEntity examCaptureQueue) {
-        examCaptureQueue.setStatus(ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
-        examCaptureQueue.setProcessBatchNum("000000");
-        examCaptureQueueRepo.save(examCaptureQueue);
+    //人脸比较成功时的处理
+    public void disposeFaceCompareSuccessful(ExamCaptureQueueInfo examCaptureQueueInfo) {
+        examCaptureQueueRepo.saveExamCaptureQueueEntityBySuccessful(examCaptureQueueInfo.getId(),
+                examCaptureQueueInfo.getPass(), examCaptureQueueInfo.getStranger(),
+                examCaptureQueueInfo.getStatus().toString(), examCaptureQueueInfo.getFaceCompareResult(),
+                examCaptureQueueInfo.getFaceCompareStartTime(), new Date());
     }
 
     /**
@@ -233,7 +231,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
      * @param examCaptureQueue 抓拍照片队列表
      */
     @Override
-    public void disposeBaiDuFaceLiveness(ExamCaptureQueueEntity examCaptureQueue) {
+    public void disposeBaiDuFaceLiveness(ExamCaptureQueueInfo examCaptureQueue) {
         //活体检测超时次数
         int facelivenessTimeOutTimes = 0;
         //百度活检超时最大重试次数
@@ -275,8 +273,9 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
 
                 //如果API并发次数超过上限,则保存错误信息到队列,并抛出异常,用于协调满载队列线程
                 if (errCode.equals(Constants.BAIDU_FACELIVENESS_QPS_LIMIT_EXCEEDED_CODE)) {
-                    examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue,
-                            "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceLivenessResultJson.toString(), ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
+                    examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
+                            "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceLivenessResultJson.toString(),
+                            ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
 
                     captureLog.debug("[DISPOSE_BAIDUFACELIVENESS] 百度在线活体API接口超过最大并发次数");
 
@@ -321,7 +320,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
 
                 captureLog.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测出现错误,即将重试,错误码:" + errCode);
                 // 其它错误类型,保存错误信息到队列中,待自动重新服务处理
-                examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue,
+                examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
                         "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceLivenessResultJson.toString(), ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
                 ExamCaptureProcessStatisticController.increaseFaceLivenessDetectFailedCount();//增加错误次数
                 captureLog.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测出现错误,增加错误次数后failedCount:" + ExamCaptureProcessStatisticController.getFaceLivenessDetectFailedCount());
@@ -344,7 +343,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
      */
     @Override
     @Transactional
-    public void saveExamCaptureAndDeleteQueue(ExamCaptureQueueEntity examCaptureQueue) {
+    public void saveExamCaptureAndDeleteQueue(ExamCaptureQueueInfo examCaptureQueue) {
         ExamCaptureEntity examCapture = getExamCaptureFromQueue(examCaptureQueue);
 
         //同一考试记录下如果有重复的照片,则直接跳过
@@ -357,10 +356,10 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
             examCaptureRepo.save(examCapture);
         }
         //删除队列中的记录
-        examCaptureQueueRepo.delete(examCaptureQueue);
+        examCaptureQueueRepo.deleteById(examCaptureQueue.getId());
     }
 
-    private ExamCaptureEntity getExamCaptureFromQueue(ExamCaptureQueueEntity queue) {
+    private ExamCaptureEntity getExamCaptureFromQueue(ExamCaptureQueueInfo queue) {
         long currentTimeMillis = System.currentTimeMillis();
         long createTimeMillis = queue.getCreationTime().getTime();
         long faceCompareStartTimeMillis = queue.getFaceCompareStartTime();
@@ -374,8 +373,8 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
         resultEntity.setFileName(queue.getFileName());
         resultEntity.setFileUrl(queue.getFileUrl());
         resultEntity.setHasVirtualCamera(queue.getHasVirtualCamera());
-        resultEntity.setIsStranger(queue.getIsStranger());
-        resultEntity.setIsPass(queue.getIsPass());
+        resultEntity.setIsStranger(queue.getStranger());
+        resultEntity.setIsPass(queue.getPass());
         resultEntity.setProcessTime(currentTimeMillis - createTimeMillis);//从进队列到处理完毕的时间
         resultEntity.setUsedTime(currentTimeMillis - faceCompareStartTimeMillis);//从开始处理到处理完毕的时间
         return resultEntity;

+ 27 - 10
examcloud-core-oe-face-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/service/impl/FacePPCompareWorker.java

@@ -5,8 +5,10 @@ import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.Worker;
 import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.WorkerController;
 import cn.com.qmth.examcloud.commons.util.Util;
 import cn.com.qmth.examcloud.core.oe.common.base.Constants;
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
+import cn.com.qmth.examcloud.core.oe.common.enums.ExamCaptureQueueStatus;
+import cn.com.qmth.examcloud.core.oe.student.face.service.ExamCaptureQueueService;
 import cn.com.qmth.examcloud.core.oe.student.face.service.ExamCaptureService;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.ExamCaptureQueueInfo;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -19,11 +21,11 @@ import java.util.concurrent.TimeUnit;
  *
  * @author lideyin 20190620
  */
-public class FacePPCompareWorker implements Worker<ExamCaptureQueueEntity> {
+public class FacePPCompareWorker implements Worker<ExamCaptureQueueInfo> {
     private final Log captureLog = LogFactory.getLog("PROCESS_EXAM_CAPTURE_TASK_LOGGER");
 
     @Override
-    public void process(WorkerController controller, ExamCaptureQueueEntity element) {
+    public void process(WorkerController controller, ExamCaptureQueueInfo element) {
 
         ThreadContext.put("TRACE_ID", "Q_" + element.getId());
         ThreadContext.put("CALLER", "FACEPP_WORKER");
@@ -35,18 +37,27 @@ public class FacePPCompareWorker implements Worker<ExamCaptureQueueEntity> {
         }
         ExamCaptureService examCaptureService = SpringContextHolder
                 .getBean(ExamCaptureService.class);
+        ExamCaptureQueueService examCaptureQueueService = SpringContextHolder
+                .getBean(ExamCaptureQueueService.class);
         try {
             examCaptureService.disposeFaceCompare(element);
         } catch (StatusException e) {
-            // 异常处理
-            element.setErrorMsg(e.getDesc());
-            examCaptureService.disposeFaceCompareFaild(element);
+            while (true){
+                // 异常处理
+                if(examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(),e.getDesc(),
+                        ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED)){
+                    break;
+                };
+                Util.sleep(TimeUnit.MILLISECONDS,500);
+            }
+
             if ((e.getCode().equals(Constants.FACE_COMPARE_CONCURRENCY_LIMIT_EXCEEDED))) {
                 // 如果超过并发次数,则添加异常次数
                 controller.addConcurrencyWarn();
+                captureLog.error("[FACEPP_COMPARE_WORKER.] 超过并发次数 " , e);
             } else {
                 ExamCaptureProcessStatisticController.increaseFaceCompareFailedCount();
-                captureLog.error("[FACEPP_COMPARE_WORKER.] 自定义异常 " + e.getDesc() +
+                captureLog.error("[FACEPP_COMPARE_WORKER.] 自定义异常 " +
                         ",failedCount=" + ExamCaptureProcessStatisticController.getFaceCompareFailedCount(), e);
             }
 
@@ -54,9 +65,15 @@ public class FacePPCompareWorker implements Worker<ExamCaptureQueueEntity> {
         } catch (Exception e) {
             ExamCaptureProcessStatisticController.increaseFaceCompareFailedCount();
             // 异常处理
-            element.setErrorMsg(e.getMessage());
-            examCaptureService.disposeFaceCompareFaild(element);
-            captureLog.error("[FACEPP_COMPARE_WORKER.] 系统异常 " + e.getMessage() +
+            while (true){
+                // 异常处理
+                if(examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(),e.getMessage(),
+                        ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED)){
+                    break;
+                }
+                Util.sleep(TimeUnit.MILLISECONDS,500);
+            }
+            captureLog.error("[FACEPP_COMPARE_WORKER.] 系统异常 "  +
                     ",failedCount=" + ExamCaptureProcessStatisticController.getFaceCompareFailedCount(), e);
             Util.sleep(TimeUnit.MICROSECONDS, 50);
         } finally {

+ 39 - 16
examcloud-core-oe-face-starter/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/starter/config/ProcessBaiduFacelivenessTask.java

@@ -1,22 +1,22 @@
 package cn.com.qmth.examcloud.core.oe.student.face.starter.config;
 
-import java.util.List;
-
-import org.apache.logging.log4j.ThreadContext;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
 import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.ConcurrentTask;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.commons.util.Util;
 import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
 import cn.com.qmth.examcloud.core.oe.common.repository.ExamCaptureQueueRepo;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.ExamCaptureQueueInfo;
 import cn.com.qmth.examcloud.core.oe.student.face.service.impl.BaiduFaceLivenessWorker;
 import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+import org.apache.logging.log4j.ThreadContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
 
 /**
  * 启动百度活体检测任务
@@ -31,7 +31,7 @@ public class ProcessBaiduFacelivenessTask implements ApplicationRunner {
     @Autowired
     ExamCaptureQueueRepo examCaptureQueueRepo;
 
-    private int process(ConcurrentTask<ExamCaptureQueueEntity> concurrentTask,
+    private int process(ConcurrentTask<ExamCaptureQueueInfo> concurrentTask,
                         String processBatchNum, Integer limit) {
 
         // 如果队列没满,则从数据库中查数据并插入
@@ -52,11 +52,10 @@ public class ProcessBaiduFacelivenessTask implements ApplicationRunner {
                 try{
                     ThreadContext.put("TRACE_ID", "Q_" + offeredQueueEntity.getId());
                     ThreadContext.put("CALLER", "BAIDU_TASK");
-                    boolean offerSuccess = concurrentTask.offerElement(offeredQueueEntity);
-                    if (offerSuccess) {
-                        offeredQueueEntity.setProcessBatchNum(processBatchNum);
-                        examCaptureQueueRepo.save(offeredQueueEntity);
 
+                    examCaptureQueueRepo.updateProcessBatchNum(offeredQueueEntity.getId(), processBatchNum);
+                    boolean offerSuccess = concurrentTask.offerElement(copyExamCaptureQueueInfoFrom(offeredQueueEntity));
+                    if (offerSuccess) {
                         captureLog.debug("[PROCESS_BAIDUFACELIVENESS." + processBatchNum
                                 + "] 向工作队列中添加数据成功:fileUrl=" + offeredQueueEntity.getFileUrl());
                         break;
@@ -78,7 +77,7 @@ public class ProcessBaiduFacelivenessTask implements ApplicationRunner {
     @Override
     public void run(ApplicationArguments args) {
 
-        ConcurrentTask<ExamCaptureQueueEntity> concurrentTask = new ConcurrentTask<ExamCaptureQueueEntity>();
+        ConcurrentTask<ExamCaptureQueueInfo> concurrentTask = new ConcurrentTask<ExamCaptureQueueInfo>();
         concurrentTask.setMaxActiveThreadSize(
                 PropertyHolder.getInt("$capture.thread.maxActiveThreadSize", 100));
         concurrentTask.setMinThreadSize(PropertyHolder.getInt("$capture.thread.minThreadSize", 2));
@@ -116,5 +115,29 @@ public class ProcessBaiduFacelivenessTask implements ApplicationRunner {
         thread.setDaemon(true);
         thread.start();
     }
-
+    private ExamCaptureQueueInfo copyExamCaptureQueueInfoFrom(ExamCaptureQueueEntity entity){
+        ExamCaptureQueueInfo info =new ExamCaptureQueueInfo();
+        info.setFaceCompareResult(entity.getFaceCompareResult());
+        info.setFacelivenessResult(entity.getFacelivenessResult());
+        info.setPass(entity.getIsPass());
+        info.setStranger(entity.getIsStranger());
+        info.setFaceCompareStartTime(entity.getFaceCompareStartTime());
+        info.setStatus(entity.getStatus());
+        info.setBaseFaceToken(entity.getBaseFaceToken());
+        info.setCameraInfos(entity.getCameraInfos());
+        info.setCreationTime(entity.getCreationTime());
+        info.setErrorMsg(entity.getErrorMsg());
+        info.setErrorNum(entity.getErrorNum());
+        info.setExamRecordDataId(entity.getExamRecordDataId());
+        info.setExtMsg(entity.getExtMsg());
+        info.setFileName(entity.getFileName());
+        info.setFileUrl(entity.getFileUrl());
+        info.setHasVirtualCamera(entity.getHasVirtualCamera());
+        info.setId(entity.getId());
+        info.setPriority(entity.getPriority());
+        info.setProcessBatchNum(entity.getProcessBatchNum());
+        info.setStudentId(entity.getStudentId());
+        info.setUpdateTime(entity.getUpdateTime());
+        return info;
+    }
 }

+ 42 - 17
examcloud-core-oe-face-starter/src/main/java/cn/com/qmth/examcloud/core/oe/student/face/starter/config/ProcessFaceCompareQueueTask.java

@@ -1,23 +1,23 @@
 package cn.com.qmth.examcloud.core.oe.student.face.starter.config;
 
-import java.util.List;
-
-import org.apache.logging.log4j.ThreadContext;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
 import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.ConcurrentTask;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.commons.util.Util;
 import cn.com.qmth.examcloud.core.oe.common.entity.ExamCaptureQueueEntity;
 import cn.com.qmth.examcloud.core.oe.common.repository.ExamCaptureQueueRepo;
+import cn.com.qmth.examcloud.core.oe.student.face.service.bean.ExamCaptureQueueInfo;
 import cn.com.qmth.examcloud.core.oe.student.face.service.impl.FacePPCompareWorker;
 import cn.com.qmth.examcloud.exchange.inner.api.SmsCloudService;
 import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+import org.apache.logging.log4j.ThreadContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
 
 /**
  * 启动人脸比对任务
@@ -35,7 +35,7 @@ public class ProcessFaceCompareQueueTask implements ApplicationRunner {
     @Autowired
     SmsCloudService smsCloudService;
 
-    private int process(ConcurrentTask<ExamCaptureQueueEntity> concurrentTask,
+    private int process(ConcurrentTask<ExamCaptureQueueInfo> concurrentTask,
                         String processBatchNum, Integer limit) {
         // 如果队列没满,则从数据库中查数据并插入
         List<ExamCaptureQueueEntity> examCaptureQueueList = examCaptureQueueRepo
@@ -51,15 +51,14 @@ public class ProcessFaceCompareQueueTask implements ApplicationRunner {
 
         for (ExamCaptureQueueEntity offeredQueueEntity : examCaptureQueueList) {
             while (true) {
-                try{
+                try {
                     ThreadContext.put("TRACE_ID", "Q_" + offeredQueueEntity.getId());
                     ThreadContext.put("CALLER", "FACEPP_TASK");
-                    boolean offerSuccess = concurrentTask.offerElement(offeredQueueEntity);
+
+                    examCaptureQueueRepo.updateProcessBatchNum(offeredQueueEntity.getId(), processBatchNum);
+                    boolean offerSuccess = concurrentTask.offerElement(copyExamCaptureQueueInfoFrom(offeredQueueEntity));
                     // 如果向队列中添加数据成功,则更新标识
                     if (offerSuccess) {
-                        offeredQueueEntity.setProcessBatchNum(processBatchNum);
-                        examCaptureQueueRepo.save(offeredQueueEntity);
-
                         captureLog.debug("[PROCESS_FACEPP." + processBatchNum
                                 + "] 向工作队列中添加数据成功:fileUrl=" + offeredQueueEntity.getFileUrl());
                         break;
@@ -69,7 +68,7 @@ public class ProcessFaceCompareQueueTask implements ApplicationRunner {
                             + "] 向工作队列中添加数据失败,30秒后重试:fileUrl=" + offeredQueueEntity.getFileUrl());
 
                     Util.sleep(PropertyHolder.getInt("$capture.queue.offer.sleepSeconds.", 30));
-                }finally {
+                } finally {
                     ThreadContext.clearAll();
                 }
 
@@ -81,7 +80,7 @@ public class ProcessFaceCompareQueueTask implements ApplicationRunner {
     @Override
     public void run(ApplicationArguments args) {
 
-        ConcurrentTask<ExamCaptureQueueEntity> concurrentTask = new ConcurrentTask<ExamCaptureQueueEntity>();
+        ConcurrentTask<ExamCaptureQueueInfo> concurrentTask = new ConcurrentTask<ExamCaptureQueueInfo>();
         concurrentTask.setMaxActiveThreadSize(
                 PropertyHolder.getInt("$capture.thread.maxActiveThreadSize", 100));
         concurrentTask.setWorker(new FacePPCompareWorker());
@@ -118,4 +117,30 @@ public class ProcessFaceCompareQueueTask implements ApplicationRunner {
         thread.setDaemon(true);
         thread.start();
     }
+
+    private ExamCaptureQueueInfo copyExamCaptureQueueInfoFrom(ExamCaptureQueueEntity entity) {
+        ExamCaptureQueueInfo info = new ExamCaptureQueueInfo();
+        info.setFaceCompareResult(entity.getFaceCompareResult());
+        info.setFacelivenessResult(entity.getFacelivenessResult());
+        info.setPass(entity.getIsPass());
+        info.setStranger(entity.getIsStranger());
+        info.setFaceCompareStartTime(entity.getFaceCompareStartTime());
+        info.setStatus(entity.getStatus());
+        info.setBaseFaceToken(entity.getBaseFaceToken());
+        info.setCameraInfos(entity.getCameraInfos());
+        info.setCreationTime(entity.getCreationTime());
+        info.setErrorMsg(entity.getErrorMsg());
+        info.setErrorNum(entity.getErrorNum());
+        info.setExamRecordDataId(entity.getExamRecordDataId());
+        info.setExtMsg(entity.getExtMsg());
+        info.setFileName(entity.getFileName());
+        info.setFileUrl(entity.getFileUrl());
+        info.setHasVirtualCamera(entity.getHasVirtualCamera());
+        info.setId(entity.getId());
+        info.setPriority(entity.getPriority());
+        info.setProcessBatchNum(entity.getProcessBatchNum());
+        info.setStudentId(entity.getStudentId());
+        info.setUpdateTime(entity.getUpdateTime());
+        return info;
+    }
 }