From a75cfcfe870b41e9f65496d523955a248b6dbbc7 Mon Sep 17 00:00:00 2001 From: qyx <565485304@qq.com> Date: Thu, 6 Aug 2020 19:54:18 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 35 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5728d59..8fd2f24 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,10 +1,33 @@ -server: - port: 8090 - - - - spring: + profiles: + active: dev # 序列化忽略null的k-v配置 jackson: default-property-inclusion: non_null +--- +# 端口 +server: + port: 8090 +# 环境 +spring: + profiles: dev + # 数据库相关配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/push?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false + username: root + password: root +--- +# 端口 +server: + port: 8090 +# 环境 +spring: + profiles: prod + # 数据库相关配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/push?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false + username: root + password: Yuyou@2020 + From 3859e77c6c5827e544245a0ab84434280ba5230a Mon Sep 17 00:00:00 2001 From: qyx <565485304@qq.com> Date: Fri, 7 Aug 2020 12:38:07 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=BC=96=E5=86=99=E4=BA=86=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++ .../openapi/openapi/OpenapiApplication.java | 2 + .../openapi/model/dto/ABMessageDTO.java | 4 + .../model/dto/convert/ABMessageCovDTO.java | 40 +++++++ .../service/impl/ABClientServiceImpl.java | 17 +++ .../openapi/openapi/task/ABDownTask.java | 100 ++++++++++++++++++ src/main/resources/application.yml | 12 ++- 7 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/yuyou/openapi/openapi/model/dto/convert/ABMessageCovDTO.java create mode 100644 src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java diff --git a/pom.xml b/pom.xml index ef15f9c..b8ccfc2 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,12 @@ + + + cn.hutool + hutool-all + 5.3.10 + diff --git a/src/main/java/com/yuyou/openapi/openapi/OpenapiApplication.java b/src/main/java/com/yuyou/openapi/openapi/OpenapiApplication.java index a7a23be..1c8bd67 100644 --- a/src/main/java/com/yuyou/openapi/openapi/OpenapiApplication.java +++ b/src/main/java/com/yuyou/openapi/openapi/OpenapiApplication.java @@ -2,8 +2,10 @@ package com.yuyou.openapi.openapi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication +@EnableAsync public class OpenapiApplication { public static void main(String[] args) { diff --git a/src/main/java/com/yuyou/openapi/openapi/model/dto/ABMessageDTO.java b/src/main/java/com/yuyou/openapi/openapi/model/dto/ABMessageDTO.java index 7e5c5bd..52d38e7 100644 --- a/src/main/java/com/yuyou/openapi/openapi/model/dto/ABMessageDTO.java +++ b/src/main/java/com/yuyou/openapi/openapi/model/dto/ABMessageDTO.java @@ -1,6 +1,8 @@ package com.yuyou.openapi.openapi.model.dto; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; /** * Copyright (C), 2012 - 2018, qyx @@ -13,6 +15,8 @@ import lombok.Data; * x 2020/8/5 v1.0 创建此文件 */ @Data +@AllArgsConstructor +@NoArgsConstructor public class ABMessageDTO { } diff --git a/src/main/java/com/yuyou/openapi/openapi/model/dto/convert/ABMessageCovDTO.java b/src/main/java/com/yuyou/openapi/openapi/model/dto/convert/ABMessageCovDTO.java new file mode 100644 index 0000000..cfde29a --- /dev/null +++ b/src/main/java/com/yuyou/openapi/openapi/model/dto/convert/ABMessageCovDTO.java @@ -0,0 +1,40 @@ +package com.yuyou.openapi.openapi.model.dto.convert; + + +import com.yuyou.openapi.openapi.model.dto.ABMessageDTO; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + + +/** + * 用于发送请求的转换实体类 + * + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ABMessageCovDTO { + + /** + * 唯一标志,对接时提供 + */ + private String app_id; + + /** + * 请求时的时间戳(1970年1月1日距今的秒数,2分钟之内的会处理,超过2分钟会回复超时) + */ + private long nonce_str; + + /** + * 校验码: sha1(“app_id=AppId&nonce_str=time_stamp”) + */ + private String signature; + + /** + * 具体数据,每条为json格式 + */ + private List data; +} diff --git a/src/main/java/com/yuyou/openapi/openapi/service/impl/ABClientServiceImpl.java b/src/main/java/com/yuyou/openapi/openapi/service/impl/ABClientServiceImpl.java index b004d5d..519f8b6 100644 --- a/src/main/java/com/yuyou/openapi/openapi/service/impl/ABClientServiceImpl.java +++ b/src/main/java/com/yuyou/openapi/openapi/service/impl/ABClientServiceImpl.java @@ -2,8 +2,12 @@ package com.yuyou.openapi.openapi.service.impl; import com.yuyou.openapi.openapi.model.dto.ABMessageDTO; import com.yuyou.openapi.openapi.service.ABClientService; +import com.yuyou.openapi.openapi.task.ABDownTask; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.ArrayList; + /** * Copyright (C), 2012 - 2018, qyx * FileName: ABClientServiceImpl @@ -17,8 +21,21 @@ import org.springframework.stereotype.Service; @Service public class ABClientServiceImpl implements ABClientService { + + @Autowired + private ABDownTask abDownTask; + @Override public void recordAndSendABClientMsg(ABMessageDTO dto) { + // 调用异步任务进行转发AB单 - 这里是这有一条数据 + ArrayList dtoArrayList = new ArrayList<>(); + dtoArrayList.add(dto); + boolean handleResult = abDownTask.doRunTask(dtoArrayList); + // 处理数据模型转换 + + // 调用接口进行入库 + + // 返回处理结果 } } diff --git a/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java b/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java new file mode 100644 index 0000000..7271db0 --- /dev/null +++ b/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java @@ -0,0 +1,100 @@ +package com.yuyou.openapi.openapi.task; + + +import cn.hutool.crypto.SecureUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.yuyou.openapi.openapi.model.dto.ABMessageDTO; +import com.yuyou.openapi.openapi.model.dto.convert.ABMessageCovDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.List; + +/** + * 下游处理任务类 + */ +@Service +@Slf4j +public class ABDownTask { + + /** + * 配置文件中加载配置信息 + */ + @Value("${ab.customer.app_id}") + private String appId; + + @Value("${ab.customer.url}") + private String customerUrl; + + + /** + * 任务处理入口,主要用于时间记录 + * + * @return + */ + @Async + public boolean doRunTask(List messageDTOList){ + Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); + log.info("====== [ task start running, task name is {} ] ======", "ABDownTask"); + boolean resultTag = runTask(messageDTOList); + Long endMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); + log.info("====== [ task start end, task name is {},cost milliSecond is {} ] ======", "ABDownTask", (endMilliSecond-satrtMilliSecond)); + return resultTag; + } + + /** + * 真实的任务执行入口 + * + * @return + */ + private boolean runTask(List messageDTOList){ + int count = 0; // 设置请求失败计数 + // 数据实体进行映射转换 - 目前是只有一条给 + ABMessageCovDTO abMessageCovDTO = new ABMessageCovDTO(); + abMessageCovDTO.setData(messageDTOList); + // 补充其他的下游请求字段 + abMessageCovDTO.setNonce_str((System.currentTimeMillis()/1000)); + abMessageCovDTO.setApp_id(appId); + abMessageCovDTO.setSignature(SecureUtil.sha1("app_id="+abMessageCovDTO.getApp_id()+"&nonce_str="+abMessageCovDTO.getNonce_str())); + // 数据实体转成Json 不忽略空kv 有序 + JSONObject jsonObject = JSONUtil.parseObj(abMessageCovDTO, false, true); + // 请求的响应处理 + // todo 失败重发请求3次 + while (count <= 3){ + // 调用HTTP请求发送数据 + HttpResponse httpResponse = sendReq(jsonObject); + if (httpResponse.isOk() && httpResponse.body().contains("成功")){ + break; + }else{ + count ++; + log.info("========== [request fail, response is {} ] ==========", httpResponse.body()); + } + } + if (count > 4) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + /** + * 调用HTTP请求发送数据 + * + * @param jsonObject + * @return + */ + private HttpResponse sendReq(JSONObject jsonObject){ + HttpResponse httpResponse = HttpRequest + .post(customerUrl) + .body(jsonObject.toString()) + .execute(); + return httpResponse; + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8fd2f24..c076487 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,6 +4,7 @@ spring: # 序列化忽略null的k-v配置 jackson: default-property-inclusion: non_null + --- # 端口 server: @@ -17,6 +18,11 @@ spring: url: jdbc:mysql://localhost:3306/push?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false username: root password: root +# 下游请求配置信息 +ab: + customer: + url: https://sandbox.openapi.ppke.com.cn/ + app_id: app_id --- # 端口 server: @@ -30,4 +36,8 @@ spring: url: jdbc:mysql://localhost:3306/push?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false username: root password: Yuyou@2020 - +# 下游请求配置信息 +ab: + customer: + url: https://openapi.ppke.com.cn/ + app_id: app_id \ No newline at end of file From 5878d706a1c83bc5195c6ef5d0cfc73907e93d53 Mon Sep 17 00:00:00 2001 From: qyx <565485304@qq.com> Date: Mon, 10 Aug 2020 10:37:17 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E6=8D=95=E8=8E=B7=E5=92=8C?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=B1=A0=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../openapi/conf/ThreadPoolConfig.java | 50 +++++++++++++++++++ .../exception/GlobalExceptionHandle.java | 32 ++++++++++++ .../openapi/openapi/task/ABDownTask.java | 2 +- ...itional-spring-configuration-metadata.json | 8 +++ src/main/resources/application.yml | 6 +++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/yuyou/openapi/openapi/conf/ThreadPoolConfig.java create mode 100644 src/main/java/com/yuyou/openapi/openapi/exception/GlobalExceptionHandle.java create mode 100644 src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/src/main/java/com/yuyou/openapi/openapi/conf/ThreadPoolConfig.java b/src/main/java/com/yuyou/openapi/openapi/conf/ThreadPoolConfig.java new file mode 100644 index 0000000..63bc19a --- /dev/null +++ b/src/main/java/com/yuyou/openapi/openapi/conf/ThreadPoolConfig.java @@ -0,0 +1,50 @@ +package com.yuyou.openapi.openapi.conf; + +import org.apache.tomcat.util.threads.ThreadPoolExecutor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +/** + * 线程池配置总类,用于配置线程池 + */ +@Configuration +@EnableAsync +public class ThreadPoolConfig { + + /** + * 从配置文件中加载线程池相关的配置 + */ + @Value(value = "${ab.customer.thread_pool.corePoolSize}") + private int corePoolSize = 10; + @Value(value = "${ab.customer.thread_pool.maxPoolSize}") + private int maxPoolSize = 200; + @Value(value = "${ab.customer.thread_pool.queueCapacity}") + private int queueCapacity = 10; + @Value(value = "${ab.customer.thread_pool.ThreadNamePrefix}") + private String ThreadNamePrefix = "MyThreadPoolExecutor-"; + + + /** + * AB 单的异步线程池的配置类 + * @return + */ + @Bean + public Executor abTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(corePoolSize); + executor.setMaxPoolSize(maxPoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setThreadNamePrefix(ThreadNamePrefix); + // rejection-policy:当pool已经达到max size的时候,如何处理新任务 + // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } + +} diff --git a/src/main/java/com/yuyou/openapi/openapi/exception/GlobalExceptionHandle.java b/src/main/java/com/yuyou/openapi/openapi/exception/GlobalExceptionHandle.java new file mode 100644 index 0000000..a48611e --- /dev/null +++ b/src/main/java/com/yuyou/openapi/openapi/exception/GlobalExceptionHandle.java @@ -0,0 +1,32 @@ +package com.yuyou.openapi.openapi.exception; + +import com.yuyou.openapi.openapi.common.CommonResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * 全局异常处理类 + */ +@ControllerAdvice +@Slf4j +public class GlobalExceptionHandle { + + + /** + * 捕获异常级别是Exception级别的异常 + * + * @param exception 异常入参 + * @return + */ + @ExceptionHandler(Exception.class) + @ResponseBody + public CommonResponse customException(Exception exception) { + if (exception != null){ + log.error(" =============== [ request error, exception is {} , {}] ===============", exception.getMessage() ,exception); + return CommonResponse.createByErrorMessage(exception.getMessage()); + } + return CommonResponse.createByErrorMessage("未知异常错误发生"); + } +} diff --git a/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java b/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java index 7271db0..c4c56db 100644 --- a/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java +++ b/src/main/java/com/yuyou/openapi/openapi/task/ABDownTask.java @@ -39,7 +39,7 @@ public class ABDownTask { * * @return */ - @Async + @Async(value = "abTaskExecutor") public boolean doRunTask(List messageDTOList){ Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); log.info("====== [ task start running, task name is {} ] ======", "ABDownTask"); diff --git a/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 0000000..d9ff73b --- /dev/null +++ b/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,8 @@ +{ + "properties": [ + { + "name": "ab.customer.app_id", + "type": "java.lang.String", + "description": "Description for ab.customer.app_id." + } +] } \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c076487..6b35ee3 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -23,6 +23,12 @@ ab: customer: url: https://sandbox.openapi.ppke.com.cn/ app_id: app_id + thread_pool: + corePoolSize: + maxPoolSize: + queueCapacity: + ThreadNamePrefix: + --- # 端口 server: