Browse Source

身份信息持久化
并行调用接口策略改变

FanQun 2 years ago
parent
commit
4a4eb904a8

+ 96 - 14
src/main/java/com/rshy/project/hy/manager/impl/RshyJkManagerImpl.java

@@ -13,6 +13,7 @@ import com.alibaba.fastjson.JSON;
 import com.rshy.project.hy.manager.RshyJkManager;
 import com.rshy.project.hy.model.constant.ItfwConstant;
 import com.rshy.project.hy.model.dto.NucleicAcidDTO;
+import com.rshy.project.hy.model.entity.Identity;
 import com.rshy.project.hy.model.enums.*;
 import com.rshy.project.hy.server.ItfwServer;
 import com.rshy.project.hy.server.VIIDServer;
@@ -23,13 +24,17 @@ import com.rshy.project.hy.server.param.RshyQuickParam;
 import com.rshy.project.hy.server.vo.RetrievaResultVO;
 import com.rshy.project.hy.server.vo.RetrievalRepositoryVO;
 import com.rshy.project.hy.server.vo.RshyVo;
+import com.rshy.project.hy.service.IdentityService;
 import com.rshy.project.hy.util.ObjectUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.context.annotation.DependsOn;
+import org.springframework.core.task.support.ExecutorServiceAdapter;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
@@ -37,6 +42,8 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -50,6 +57,7 @@ import java.util.stream.Collectors;
 @Component
 @Slf4j
 @DependsOn("itfwServer")
+@EnableAsync
 public class RshyJkManagerImpl implements RshyJkManager {
     @Resource
     private YituFaceServer yituFaceServer;
@@ -59,13 +67,17 @@ public class RshyJkManagerImpl implements RshyJkManager {
     private VIIDServer viidServer;
     @Resource
     private StringRedisTemplate stringRedisTemplate;
+    @Resource
+    private ThreadPoolTaskExecutor poolTaskExecutor;
+    @Resource
+    private IdentityService identityService;
 
     @Override
     @Async("hstTaskExecutor")
     public Future<RshyVo> getRshyInfo(RshyParam rshyParam) {
         // timeout 转成毫秒 这里考虑到网络传输延时等原因,减去300ms
-        rshyParam.setTimeout((int) TimeUnit.MILLISECONDS.convert(rshyParam.getTimeout(), TimeUnit.SECONDS) - 300);
-        int jkmTimeout = rshyParam.getTimeout();
+        rshyParam.setTimeout((int) TimeUnit.MILLISECONDS.convert(rshyParam.getTimeout(), TimeUnit.SECONDS));
+        int jkmTimeout = rshyParam.getTimeout() - 300;
         RshyVo rshyVo = new RshyVo();
         PctgkryDTO gkryDTO = new PctgkryDTO();
         ResultDTO resultDTO = new ResultDTO();
@@ -73,7 +85,8 @@ public class RshyJkManagerImpl implements RshyJkManager {
         DateTime beginDate = DateTime.now();
         PctjkmInfoDTO jkmInfo = null;
 
-        if (StringUtils.isNotBlank(rshyParam.getBarCode()) || StringUtils.isNotBlank(rshyParam.getSfzh())) {
+        // 刷健康码或场所码
+        if (StringUtils.isNotBlank(rshyParam.getBarCode()) && StringUtils.isBlank(rshyParam.getSfzh())) {
             try {
                 //查询健康码信息
                 jkmInfo = itfwServer.getPctjkm(rshyParam.getBarCode(), rshyParam.getSfzh(), jkmTimeout);
@@ -90,21 +103,31 @@ public class RshyJkManagerImpl implements RshyJkManager {
         if (jkmInfo != null) {
             rshyParam.setSfzh(jkmInfo.getId_num());
             rshyVo.setSfzh(jkmInfo.getId_num()).setXm(jkmInfo.getUser_name()).setHealthCode(jkmInfo.getColor_code_label()).setPhone(jkmInfo.getPn());
+            saveIdentity(rshyParam.getBarCode(), rshyVo);
         } else {
             rshyVo.setSfzh(rshyParam.getSfzh());
+            if (rshyParam.getIdentity() != null) {
+                rshyVo.setXm(rshyParam.getIdentity().getName());
+                rshyVo.setPhone(rshyParam.getIdentity().getPhone());
+            }
         }
         int jkmUsedTime = (int) DateUtil.between(beginDate, DateTime.now(), DateUnit.MS);
         System.out.println("健康码接口用时: " + jkmUsedTime + "毫秒");
 
-        rshyParam.setTimeout(rshyParam.getTimeout() - jkmUsedTime - 300);
-        //剩余时间不到10ms,直接返回
-        if (rshyParam.getTimeout() <= 10) {
+        rshyParam.setTimeout(rshyParam.getTimeout() - jkmUsedTime - 400);
+        //剩余时间不到50ms,直接返回
+        if (rshyParam.getTimeout() <= 50) {
             return new AsyncResult<>(rshyVo);
         }
 
+        log.info(rshyParam.toString());
+
         AtomicReference<RshyVo> quickRshyVo = new AtomicReference<>(new RshyVo());
         List<Runnable> taskList = new ArrayList<Runnable>() {
             {
+                if (StrUtil.isBlank(rshyParam.getBarCode())) {
+                    add(() -> resultDTO.setPctjkmInfoDTO(itfwServer.getPctjkm("", rshyParam.getSfzh(), rshyParam.getTimeout())));
+                }
                 add(() -> resultDTO.setPctsfzResult(itfwServer.getPctsfz(rshyParam.getSfzh(), rshyParam.getTimeout())));
                 add(() -> resultDTO.setPctymDataDTOS(itfwServer.getPctym(rshyParam.getSfzh(), rshyParam.getTimeout())));
                 add(() -> resultDTO.setPcthsResultDTO(itfwServer.getPcths(rshyParam.getSfzh(), rshyParam.getTimeout())));
@@ -134,16 +157,28 @@ public class RshyJkManagerImpl implements RshyJkManager {
         //}
 
         //异步流并发处理
-        taskList.parallelStream().forEach(v -> {
-            try {
-                v.run();
-            } catch (Exception e) {
-                log.error("异常信息:{}", e.getMessage());
-                e.printStackTrace();
-            }
-        });
+//        taskList.parallelStream().forEach(v -> {
+//            try {
+//                v.run();
+//            } catch (Exception e) {
+//                log.error("异常信息:{}", e.getMessage());
+//                e.printStackTrace();
+//            }
+//        });
+
+        try {
+            log.info("{}个任务, 用时 {}毫秒", taskList.size(), startTaskAllInOnce(taskList, rshyParam.getTimeout() + 100));
+        } catch (InterruptedException e) {
+            log.error("异常信息:{}", e.getMessage());
+            e.printStackTrace();
+        }
 
         log.info("IT服务平台接口调用完成");
+        //用身份证号码获取到健康码信息
+        if (resultDTO.getPctjkmInfoDTO() != null) {
+            jkmInfo = resultDTO.getPctjkmInfoDTO();
+            rshyVo.setXm(resultDTO.getPctjkmInfoDTO().getUser_name()).setHealthCode(resultDTO.getPctjkmInfoDTO().getColor_code_label()).setPhone(resultDTO.getPctjkmInfoDTO().getPn());
+        }
         //今日进站次数
         rshyVo.setTimes(times(rshyVo.getSfzh()));
         //疫苗
@@ -221,9 +256,56 @@ public class RshyJkManagerImpl implements RshyJkManager {
         }
 
         //System.out.println(JSONObject.toJSONString(resultDTO));
+        saveIdentity(StrUtil.EMPTY, rshyVo);
+
         return new AsyncResult<>(rshyVo);
     }
 
+
+    /**
+     * 并行执行任务
+     *
+     * @param task 任务列表
+     * @return 用时,毫秒
+     * @throws InterruptedException
+     */
+    protected long startTaskAllInOnce(List<Runnable> task, long timeout) throws InterruptedException {
+        long startTime = System.currentTimeMillis();
+        System.out.println(startTime + " [" + Thread.currentThread() + "] All thread is ready, concurrent going...");
+        final CountDownLatch latch = new CountDownLatch(task.size());
+        ExecutorService executorService = new ExecutorServiceAdapter(poolTaskExecutor);
+        for (Runnable r : task) {
+            executorService.submit(() -> {
+                try {
+                    r.run();
+                } finally {
+                    latch.countDown();
+                }
+            });
+        }
+
+        latch.await(timeout, TimeUnit.MILLISECONDS);
+        long endTime = System.currentTimeMillis();
+        System.out.println(endTime + " [" + Thread.currentThread() + "] All thread is completed.");
+        return endTime - startTime;
+    }
+
+
+    @Async
+    protected void saveIdentity(String barCode, RshyVo rshyVo) {
+        log.info("save identity ");
+        Identity identity = new Identity();
+        if (StrUtil.isNotBlank(barCode)) {
+            identity.setBarCode(barCode);
+        }
+        identity.setIdNum(rshyVo.getSfzh());
+        identity.setName(rshyVo.getXm());
+        identity.setAddress(rshyVo.getAddress());
+        identity.setPhone(rshyVo.getPhone());
+        identity.setPhoto(rshyVo.getPhoto());
+        identityService.saveOrUpdate(identity);
+    }
+
     /**
      * 组装返回的核酸信息
      *

+ 16 - 0
src/main/java/com/rshy/project/hy/mapper/IdentityMapper.java

@@ -0,0 +1,16 @@
+package com.rshy.project.hy.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.rshy.project.hy.model.entity.Identity;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author fanqun
+ * @since 2022-06-11
+ */
+public interface IdentityMapper extends BaseMapper<Identity> {
+
+}

+ 5 - 0
src/main/java/com/rshy/project/hy/model/constant/WebConstant.java

@@ -20,4 +20,9 @@ public class WebConstant {
      * 公安接口访问异常次数,达到这个次数后一定时间内不去调用
      */
     public static final Integer TIMEOUT_TIMES = 3;
+
+    /**
+     * 接口响应内容过长时,最长显示的字符长度
+     */
+    public static final Integer DISPLAY_MAX_LENGTH = 80;
 }

+ 48 - 0
src/main/java/com/rshy/project/hy/model/entity/Identity.java

@@ -0,0 +1,48 @@
+package com.rshy.project.hy.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 身份信息
+ * </p>
+ *
+ * @author fanqun
+ * @since 2022-06-11
+ */
+@Data
+@Accessors(chain = true)
+public class Identity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String barCode;
+
+    @TableId(value = "id_num", type = IdType.INPUT)
+    private String idNum;
+
+    private String name;
+
+    private String address;
+
+    private String phone;
+
+    private String photo;
+
+
+    @Override
+    public String toString() {
+        return "Identity{" +
+                "barCode=" + barCode +
+                ", idNum=" + idNum +
+                ", name=" + name +
+                ", address=" + address +
+                ", phone=" + phone +
+                "}";
+    }
+}

+ 5 - 5
src/main/java/com/rshy/project/hy/server/ItfwServer.java

@@ -645,7 +645,7 @@ public class ItfwServer {
         String cacheKey = idNumber + ':' + ItfwConstant.PCTYM_KEY;
         String cacheValue = stringRedisTemplate.opsForValue().get(cacheKey);
         if (StrUtil.isNotEmpty(cacheValue)) {
-            log.info("浙江省疫苗注射数据服务走缓存读取,响应内容: {}", cacheValue);
+            log.info("浙江省疫苗注射数据服务走缓存读取,响应内容: {}", StrUtil.brief(cacheValue, WebConstant.DISPLAY_MAX_LENGTH));
             return JSON.parseArray(cacheValue, PctymDataDTO.class);
         }
 
@@ -673,7 +673,7 @@ public class ItfwServer {
             return null;
         }
 
-        log.info("浙江省疫苗注射数据服务响应信息:{}", body);
+        log.info("浙江省疫苗注射数据服务响应信息:{}", StrUtil.brief(body, WebConstant.DISPLAY_MAX_LENGTH));
         deleteKeys(cacheStatusKey);
         //Set<String> keys = stringRedisTemplate.keys(cacheStatusKey + "*");
         //stringRedisTemplate.delete(keys);
@@ -719,7 +719,7 @@ public class ItfwServer {
             return null;
         }
 
-        log.info("核酸接口数据服务响应信息:{}", body);
+        log.info("核酸接口数据服务响应信息:{}", StrUtil.brief(body, WebConstant.DISPLAY_MAX_LENGTH));
 
         if (StrUtil.isEmpty(body) || !StrUtil.containsAnyIgnoreCase(body, "data")) {
             return null;
@@ -872,7 +872,7 @@ public class ItfwServer {
         String cacheKey = idNumber + ':' + ItfwConstant.PCTXCM_KEY;
         String cacheValue = stringRedisTemplate.opsForValue().get(cacheKey);
         if (StrUtil.isNotEmpty(cacheValue)) {
-            log.info("查询扫行程码记录接口服务走缓存读取,响应内容: {}", cacheValue);
+            log.info("查询扫行程码记录接口服务走缓存读取,响应内容: {}", StrUtil.brief(cacheValue, WebConstant.DISPLAY_MAX_LENGTH));
             return JSON.parseObject(cacheValue, PctxcmResultDTO.class);
         }
 
@@ -900,7 +900,7 @@ public class ItfwServer {
             return null;
         }
 
-        log.info("查询扫行程码记录接口数据服务响应信息:{}", body);
+        log.info("查询扫行程码记录接口数据服务响应信息:{}", StrUtil.brief(body, WebConstant.DISPLAY_MAX_LENGTH));
         deleteKeys(cacheStatusKey);
         if (StrUtil.isEmpty(body) || !StrUtil.containsAnyIgnoreCase(body, "data")) {
             return null;

+ 5 - 0
src/main/java/com/rshy/project/hy/server/param/RshyParam.java

@@ -1,6 +1,8 @@
 package com.rshy.project.hy.server.param;
 
+import com.alibaba.fastjson.annotation.JSONField;
 import com.rshy.project.hy.model.constant.WebConstant;
+import com.rshy.project.hy.model.entity.Identity;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -37,6 +39,9 @@ public class RshyParam {
     @ApiModelProperty("锁屏状态")
     private Integer screenLocked;
 
+    @JSONField(serialize = false, deserialize = false)
+    private Identity identity;
+
     @Override
     public String toString() {
         return "RshyParam{" +

+ 16 - 0
src/main/java/com/rshy/project/hy/service/IdentityService.java

@@ -0,0 +1,16 @@
+package com.rshy.project.hy.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.rshy.project.hy.model.entity.Identity;
+
+/**
+ * <p>
+ * 服务类
+ * </p>
+ *
+ * @author fanqun
+ * @since 2022-06-11
+ */
+public interface IdentityService extends IService<Identity> {
+
+}

+ 22 - 0
src/main/java/com/rshy/project/hy/service/impl/IdentityServiceImpl.java

@@ -0,0 +1,22 @@
+package com.rshy.project.hy.service.impl;
+
+
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.rshy.project.hy.mapper.IdentityMapper;
+import com.rshy.project.hy.model.entity.Identity;
+import com.rshy.project.hy.service.IdentityService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ *
+ * @author fanqun
+ * @since 2022-06-11
+ */
+@Service
+public class IdentityServiceImpl extends ServiceImpl<IdentityMapper, Identity> implements IdentityService {
+
+}

+ 21 - 2
src/main/java/com/rshy/project/hy/web/controller/RshyController.java

@@ -6,10 +6,13 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.IdcardUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.rshy.project.hy.baseRe.BaseException;
 import com.rshy.project.hy.baseRe.ResultCode;
 import com.rshy.project.hy.baseRe.Ret;
 import com.rshy.project.hy.manager.RshyJkManager;
+import com.rshy.project.hy.mapper.IdentityMapper;
+import com.rshy.project.hy.model.entity.Identity;
 import com.rshy.project.hy.model.enums.PassStatusEnum;
 import com.rshy.project.hy.server.param.RshyParam;
 import com.rshy.project.hy.server.param.RshyQuickParam;
@@ -43,6 +46,8 @@ import java.util.concurrent.TimeoutException;
 public class RshyController {
     @Resource
     private RshyJkManager rshyJkManager;
+    @Resource
+    private IdentityMapper identityMapper;
 
     @GetMapping(value = "/version")
     public String version() {
@@ -70,11 +75,26 @@ public class RshyController {
         DateTime time1 = DateTime.now();
 
         log.info("普通核验接口请求参数:{}", JSON.toJSONString(rshyParam));
+        LambdaQueryWrapper<Identity> wrapper = new LambdaQueryWrapper<>();
+        if (StrUtil.isNotBlank(rshyParam.getSfzh())) {
+            wrapper.eq(Identity::getIdNum, rshyParam.getSfzh());
+        } else if (StrUtil.isNotBlank(rshyParam.getBarCode())) {
+            wrapper.eq(Identity::getBarCode, rshyParam.getBarCode());
+        } else {
+            throw new BaseException(ResultCode.VALIDATE_FAILED);
+        }
+        Identity identity = identityMapper.selectOne(wrapper);
+
         RshyVo rshyVo = new RshyVo().setPassStatus(PassStatusEnum.NORMAL_TRAFFIC);
+        if (identity != null) {
+            rshyVo.setXm(identity.getName()).setSfzh(identity.getIdNum()).setPhone(identity.getPhone());
+            rshyParam.setSfzh(identity.getIdNum());
+            rshyParam.setIdentity(identity);
+        }
         try {
             //RshyVo rshyVo = rshyJkManager.getRshyInfo(rshyParam);
             Future<RshyVo> future = rshyJkManager.getRshyInfo(rshyParam);
-            rshyVo = future.get(rshyParam.getTimeout() * 1000, TimeUnit.MILLISECONDS);
+            rshyVo = future.get(rshyParam.getTimeout() * 1000 - 100, TimeUnit.MILLISECONDS);
         } catch (InterruptedException | ExecutionException e) {
             log.error("普通核验接口异常: {}", e.getMessage());
             //e.printStackTrace();
@@ -84,7 +104,6 @@ public class RshyController {
             throw new BaseException();
         }
         log.info("普通核验响应内容:{}", JSON.toJSONString(rshyVo));
-
         System.out.println("普通核验接口用时: " + DateUtil.between(time1, DateTime.now(), DateUnit.MS) + "毫秒\n");
         return Ret.success(rshyVo);
     }

+ 1 - 1
src/main/resources/application-local.yml

@@ -1,6 +1,6 @@
 spring:
   datasource:
-    url: jdbc:mysql://127.0.0.1:3306/rshy?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&pinGlobalTxToPhysicalConnection=true&serverTimezone=UTC
+    url: jdbc:mysql://127.0.0.1:3306/metro_hy?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&pinGlobalTxToPhysicalConnection=true&serverTimezone=UTC
     username: root
     password: root1234
     driver-class-name: com.mysql.cj.jdbc.Driver

+ 15 - 0
src/main/resources/mapper/IdentityMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.rshy.project.hy.mapper.IdentityMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.rshy.project.hy.model.entity.Identity">
+        <id column="id_num" property="idNum" />
+        <result column="bar_code" property="barCode" />
+        <result column="name" property="name" />
+        <result column="address" property="address" />
+        <result column="phone" property="phone" />
+        <result column="photo" property="photo" />
+    </resultMap>
+
+</mapper>