From 3b5a3bff24253d17434c85bcebb792804f1cc78f Mon Sep 17 00:00:00 2001 From: wxz Date: Thu, 7 Sep 2023 19:08:49 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=96=B0=E5=A2=9E=E5=AF=B9epmet-governance-c?= =?UTF-8?q?lient=E7=9A=84=E4=BE=9D=E8=B5=96=E3=80=82=202.=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0url=E5=90=8E=E7=BD=AE=E5=A4=84=E7=90=86=E5=99=A8EpmetF?= =?UTF-8?q?eignClientsBeanPostProcessor.java=203.=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=EF=BC=9A=E9=97=AE=E5=8D=B7=E6=8F=90=E4=BA=A4=E6=97=B6=E5=80=99?= =?UTF-8?q?=EF=BC=8C=E7=9B=B8epmet-governance=E6=9C=8D=E5=8A=A1=E6=8E=A8?= =?UTF-8?q?=E9=80=81=E7=BB=93=E6=9E=9C=E6=95=B0=E6=8D=AE=E7=9A=84=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 3 + tduck-api/pom.xml | 42 +++++ .../tduck/cloud/api/TduckApiApplication.java | 4 +- .../EpmetFeignClientsBeanPostProcessor.java | 146 ++++++++++++++++++ .../api/exception/BaseExceptionHandler.java | 6 + ...stionnaireSubmitSatisfactionProcessor.java | 57 ++++++- .../UserProjectResultController.java | 2 + tduck-clients/pom.xml | 40 +++++ .../entity/UserProjectResultEntity.java | 2 + 9 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 tduck-api/src/main/java/com/tduck/cloud/api/config/EpmetFeignClientsBeanPostProcessor.java create mode 100644 tduck-clients/pom.xml diff --git a/pom.xml b/pom.xml index b34356f..dc7ebd1 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,9 @@ tduck-account tduck-project tduck-wx-mp + + tduck-clients + diff --git a/tduck-api/pom.xml b/tduck-api/pom.xml index 517c1bb..089b0f2 100644 --- a/tduck-api/pom.xml +++ b/tduck-api/pom.xml @@ -73,8 +73,50 @@ com.github.answerail dinger-spring-boot-starter + + com.epmet + epmet-governance-client + 2.0.0 + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + epmet + maven-releases + https://nexus.elinkservice.cn/repository/maven-releases/ + + + + + + public + aliyun nexus + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + + + + epmet + https://nexus.elinkservice.cn/repository/maven-releases/ + + + ${project.name} diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/TduckApiApplication.java b/tduck-api/src/main/java/com/tduck/cloud/api/TduckApiApplication.java index 6a5d0d2..40c1d1a 100644 --- a/tduck-api/src/main/java/com/tduck/cloud/api/TduckApiApplication.java +++ b/tduck-api/src/main/java/com/tduck/cloud/api/TduckApiApplication.java @@ -3,6 +3,7 @@ package com.tduck.cloud.api; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; @@ -12,7 +13,8 @@ import org.springframework.scheduling.annotation.EnableAsync; @EnableDiscoveryClient @SpringBootApplication @EnableAsync -@ComponentScan("com.tduck.cloud.*") +@EnableFeignClients(basePackages = { "com.epmet.governance.service.feign" }) +@ComponentScan(basePackages = { "com.tduck.cloud.*", "com.epmet.governance.service.feign" }) public class TduckApiApplication { public static void main(String[] args) { diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/config/EpmetFeignClientsBeanPostProcessor.java b/tduck-api/src/main/java/com/tduck/cloud/api/config/EpmetFeignClientsBeanPostProcessor.java new file mode 100644 index 0000000..589d2b8 --- /dev/null +++ b/tduck-api/src/main/java/com/tduck/cloud/api/config/EpmetFeignClientsBeanPostProcessor.java @@ -0,0 +1,146 @@ +package com.tduck.cloud.api.config; + +import com.epmet.commons.tools.exception.ExceptionUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @Description FeignClient修饰BeanPostProcessor + * 1.处理url:在spring.profiles.active=local的情况下,读取~/epmet_files/epmet_hosts.properties文件中的行,在生成OpenFeignClient的时候 + * 将文件中读取到的地址替换进去,而不通过注册中心。如果文件中没设置,那使用注册中心,通过负载均衡器选择实例。 + * properties实例: + * epmet-user-server=http://localhost:8087 + * gov-org-server=http://localhost:8092 + * # epmet-actual-base=http://localhost:8118 + * @Author wxz + * @Date 2023/7/28 13:18 + */ +@Slf4j +@Component +@ConditionalOnProperty(matchIfMissing = false, prefix = "spring.profiles", name = "active", havingValue = "local") +public class EpmetFeignClientsBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware, EnvironmentAware { + + public static final String FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME = "org.springframework.cloud.openfeign.FeignClientFactoryBean"; + public static final String URL_FIELD_NAME = "url"; + + private ApplicationContext applicationContext; + + private Environment environment; + + private AtomicInteger atomicInteger = new AtomicInteger(); + + /** + * epmet-user-server=localhost:8087 + * gov-org-server=localhost:8092 + * ... + */ + private Properties localServerAndUrlProps = new Properties(); + + public EpmetFeignClientsBeanPostProcessor() { + // 获取home目录下。unix系统:~/ windows系统:C:\Users\xxx + Path epmetHostsConfigPath = Paths.get(System.getProperty("user.home")).resolve("epmet_files").resolve("epmet_hosts.properties"); + if (Files.notExists(epmetHostsConfigPath)) { + return; + } + + try (FileInputStream is = new FileInputStream(epmetHostsConfigPath.toFile())) { + // 读取本地配置文件,加载到缓存 + localServerAndUrlProps.load(is); + } catch ( + FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + + if (atomicInteger.getAndIncrement() == 0) { + + Class beanNameClz = null; + try { + beanNameClz = Class.forName(FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME); + } catch ( + ClassNotFoundException e) { + log.info("没有{}相关实例", FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME); + } + + final Class fbeanNameClz = beanNameClz; + applicationContext.getBeansOfType(fbeanNameClz).forEach((feignBeanName, beanOfFeignClientFactoryBean) -> { + try { + setUrlField(fbeanNameClz, beanOfFeignClientFactoryBean); + } catch ( + Exception e) { + String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); + log.error("bean\"{}\"设置url失败,错误信息:{}", feignBeanName, errorStackTrace); + } + }); + } + + return null; + } + + /** + * @param clazz: 丢想的class文件 + * @param obj: 对象 + * @return + * @description: 为指定bean设置指定属性 + * @author: WangXianZhang + * @date: 2023/7/28 13:23 + */ + private void setUrlField(Class clazz, Object obj) throws Exception { + // 1.先获取对端服务名 + Field serverNameField = ReflectionUtils.findField(clazz, "name"); + serverNameField.setAccessible(true); + String serverNames = (String) serverNameField.get(obj); + + if (StringUtils.isBlank(serverNames)) { + log.info("服务\"{}\"的\"{}\"字段为空,不设置url", clazz.getName(), URL_FIELD_NAME); + return; + } + + Field urlField = ReflectionUtils.findField(clazz, URL_FIELD_NAME); + + String currentServiceUrl; + + if (Objects.nonNull(urlField) + && StringUtils.isNotBlank(currentServiceUrl = (String) localServerAndUrlProps.get(serverNames))) { + + ReflectionUtils.makeAccessible(urlField); + ReflectionUtils.setField(urlField, obj, currentServiceUrl); + } + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } +} \ No newline at end of file diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/exception/BaseExceptionHandler.java b/tduck-api/src/main/java/com/tduck/cloud/api/exception/BaseExceptionHandler.java index a6e2893..d2f5dc2 100644 --- a/tduck-api/src/main/java/com/tduck/cloud/api/exception/BaseExceptionHandler.java +++ b/tduck-api/src/main/java/com/tduck/cloud/api/exception/BaseExceptionHandler.java @@ -1,6 +1,7 @@ package com.tduck.cloud.api.exception; import cn.hutool.core.exceptions.ValidateException; +import com.epmet.commons.tools.exception.EpmetException; import com.tduck.cloud.common.constant.ResponseCodeConstants; import com.tduck.cloud.common.util.Result; import lombok.extern.slf4j.Slf4j; @@ -21,6 +22,11 @@ import org.springframework.web.servlet.NoHandlerFoundException; @Slf4j public class BaseExceptionHandler { + @ExceptionHandler(EpmetException.class) + public Result handlerEpmetException(EpmetException e) { + log.error(e.getMsg(), e); + return Result.failed(ResponseCodeConstants.FAIL, e.getMsg()); + } @ExceptionHandler(NoHandlerFoundException.class) public Result handlerNoFoundException(NoHandlerFoundException e) { diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/handler/QuestionnaireSubmitSatisfactionProcessor.java b/tduck-api/src/main/java/com/tduck/cloud/api/handler/QuestionnaireSubmitSatisfactionProcessor.java index 195c29a..f540ae6 100644 --- a/tduck-api/src/main/java/com/tduck/cloud/api/handler/QuestionnaireSubmitSatisfactionProcessor.java +++ b/tduck-api/src/main/java/com/tduck/cloud/api/handler/QuestionnaireSubmitSatisfactionProcessor.java @@ -1,8 +1,14 @@ package com.tduck.cloud.api.handler; +import com.epmet.commons.tools.exception.EpmetErrorCode; +import com.epmet.commons.tools.exception.EpmetException; +import com.epmet.commons.tools.utils.Result; +import com.epmet.governance.satisfaction.dto.form.SubmitQuestionnaireResultFormDTO; +import com.epmet.governance.service.feign.GovernanceServiceOpenFeignClient; import com.tduck.cloud.project.entity.UserProjectResultEntity; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.Map; @@ -13,15 +19,60 @@ import java.util.Map; */ @Component public class QuestionnaireSubmitSatisfactionProcessor extends AbstractQuestionnaireSubmitProcessor{ + + @Resource + private GovernanceServiceOpenFeignClient governanceServiceOpenFeignClient; + @Override public void process(UserProjectResultEntity result, String userId, HttpServletRequest request) { - Map resultMap = result.getProcessData(); + String projectKey = result.getProjectKey(); + String agencyId = result.getAgencyId(); - // 先判断此人是否填写过该问卷 + Map resultMap = result.getProcessData(); + String reporterName = (String) resultMap.get("field129");// 姓名 + String reporterMobile = (String) resultMap.get("field130");// 电话 + String followUpStatus = (String) resultMap.get("field131");// 是否接受回访 + String expectFollowUpWay = (String) resultMap.get("field132");// 回访方式 + String addressDetail = (String) resultMap.get("field134");// 详细地址 // 将结果通知governance服务,进行持久化 + SubmitQuestionnaireResultFormDTO form = new SubmitQuestionnaireResultFormDTO(); + form.setAgencyId(agencyId); + form.setQuestionnaireProjectKey(projectKey); + form.setCultureFacilityEva((String) resultMap.get("field101")); + form.setCultureAspect((String) resultMap.get("field102")); + form.setCultureReason((String) resultMap.get("field103")); + form.setSportsFacilityEva((String) resultMap.get("field104")); + form.setSportsAspect((String) resultMap.get("field105")); + form.setSportsReason((String) resultMap.get("field106")); + form.setBasicEducationEva( (String) resultMap.get("field107")); + form.setMedicalEva((String) resultMap.get("field109")); + form.setMedicalAspect((String) resultMap.get("field114")); + form.setMedicalReason((String) resultMap.get("field116")); + form.setOldPeopleProvideEva((String) resultMap.get("field118")); + form.setOldPeopleProvideAspect((String) resultMap.get("field117")); + form.setOldPeopleProvideReason((String) resultMap.get("field119")); + form.setSocialAssistanceEva((String) resultMap.get("field120")); + form.setSocialAssistanceAspect((String) resultMap.get("field121")); + form.setSocialAssistanceReason((String) resultMap.get("field122")); + form.setEcologicalEnvironmenEva((String) resultMap.get("field123")); + form.setEcologicalEnvironmenAspect((String) resultMap.get("field124")); + form.setEcologicalEnvironmenReason((String) resultMap.get("field125")); + form.setSocialSecurityEva((String) resultMap.get("field126")); + form.setSocialSecurityAspect((String) resultMap.get("field127")); + form.setSocialSecurityReason((String) resultMap.get("field128")); + form.setReporterName(reporterName); + form.setReporterMobile(reporterMobile); + form.setFollowUpStatus(followUpStatus); + form.setExpectFollowUpWay(expectFollowUpWay); + form.setAddressDetail(addressDetail); - System.out.println(result); + Result rst = governanceServiceOpenFeignClient.submitQuestionnaireRst(form); + if (rst.getCode() > 8000) { + throw new EpmetException(rst.getCode(), null, rst.getMsg()); + } else if (rst.getCode() != 0) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), null, "提交失败"); + } } } diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/UserProjectResultController.java b/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/UserProjectResultController.java index 0cb2239..61264ed 100644 --- a/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/UserProjectResultController.java +++ b/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/UserProjectResultController.java @@ -29,6 +29,7 @@ import com.tduck.cloud.wx.mp.service.WxMpUserMsgService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -120,6 +121,7 @@ public class UserProjectResultController { * @date: 2023/9/6 09:01 */ @NoRepeatSubmit + @Transactional(rollbackFor = Exception.class) @PostMapping("/createAnonymously") public Result createProjectResultAnonymously(@RequestBody UserProjectResultEntity entity, @RequestAttribute(required = false) String userId, HttpServletRequest request) { diff --git a/tduck-clients/pom.xml b/tduck-clients/pom.xml new file mode 100644 index 0000000..079be3c --- /dev/null +++ b/tduck-clients/pom.xml @@ -0,0 +1,40 @@ + + + + 4.0.0 + + + + com.tduck + + + tduck-platform + + + 0.0.1-SNAPSHOT + + + + + org.example + + + tduck-clients + + + + + 17 + + + 17 + + + UTF-8 + + + + \ No newline at end of file diff --git a/tduck-project/src/main/java/com/tduck/cloud/project/entity/UserProjectResultEntity.java b/tduck-project/src/main/java/com/tduck/cloud/project/entity/UserProjectResultEntity.java index 9c9bf22..9e0f516 100644 --- a/tduck-project/src/main/java/com/tduck/cloud/project/entity/UserProjectResultEntity.java +++ b/tduck-project/src/main/java/com/tduck/cloud/project/entity/UserProjectResultEntity.java @@ -108,4 +108,6 @@ public class UserProjectResultEntity extends BaseEntity private transient String orgName = ""; //工作人员添加入口类型(组织:agency;部门:dept;网格:gridId) private transient String orgType = ""; + + private transient String agencyId; }