Commit 44486afd957633f789f66bcd7cd612619dc10fb7

Authored by jason
1 parent f8d6f1e2

【代码评审修复】 Http 触发器返回值处理修改

yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java
@@ -199,4 +199,11 @@ public class JsonUtils { @@ -199,4 +199,11 @@ public class JsonUtils {
199 return JSONUtil.isTypeJSON(text); 199 return JSONUtil.isTypeJSON(text);
200 } 200 }
201 201
  202 + /**
  203 + * 判断字符串是否为 JSON 类型的字符串
  204 + * @param str 字符串
  205 + */
  206 + public static boolean isJsonObject(String str) {
  207 + return JSONUtil.isTypeJSONObject(str);
  208 + }
202 } 209 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmHttpRequestTrigger.java
@@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.bpm.service.task.trigger; @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.bpm.service.task.trigger;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 -import cn.hutool.json.JSONObject;  
6 -import cn.hutool.json.JSONUtil;  
7 import cn.iocoder.yudao.framework.common.core.KeyValue; 5 import cn.iocoder.yudao.framework.common.core.KeyValue;
  6 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting; 8 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting;
10 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; 9 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
11 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; 10 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
12 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 11 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  12 +import com.fasterxml.jackson.core.type.TypeReference;
13 import jakarta.annotation.Resource; 13 import jakarta.annotation.Resource;
14 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
15 import org.flowable.engine.runtime.ProcessInstance; 15 import org.flowable.engine.runtime.ProcessInstance;
@@ -37,8 +37,6 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_ @@ -37,8 +37,6 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_
37 @Slf4j 37 @Slf4j
38 public class BpmHttpRequestTrigger implements BpmTrigger { 38 public class BpmHttpRequestTrigger implements BpmTrigger {
39 39
40 - private static final String PARSE_RESPONSE_FIELD = "data";  
41 -  
42 @Resource 40 @Resource
43 private BpmProcessInstanceService processInstanceService; 41 private BpmProcessInstanceService processInstanceService;
44 42
@@ -72,54 +70,53 @@ public class BpmHttpRequestTrigger implements BpmTrigger { @@ -72,54 +70,53 @@ public class BpmHttpRequestTrigger implements BpmTrigger {
72 // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢? 70 // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢?
73 // 3. 发起请求 71 // 3. 发起请求
74 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); 72 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
  73 + ResponseEntity<String> responseEntity;
75 try { 74 try {
76 - ResponseEntity<String> responseEntity = restTemplate.exchange(setting.getUrl(), HttpMethod.POST, 75 + responseEntity = restTemplate.exchange(setting.getUrl(), HttpMethod.POST,
77 requestEntity, String.class); 76 requestEntity, String.class);
78 log.info("[execute][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); 77 log.info("[execute][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
79 -  
80 - // TODO @jason:建议把请求和失败,放在两个 try catch 里处理。  
81 - // 4. 处理请求返回  
82 - // TODO @jason:返回结果,要不统一用 CommonResult,符合这个规范。这样,就可以验证 code 为 0 了。必须符合这个规范~~  
83 - if (CollUtil.isNotEmpty(setting.getResponse()) && responseEntity.getStatusCode().is2xxSuccessful()  
84 - && StrUtil.isNotEmpty(responseEntity.getBody())) {  
85 - // 4.1 获取需要更新的流程变量  
86 - Map<String, Object> updateVariables = getNeedUpdatedVariablesFromResponse(responseEntity.getBody(), setting.getResponse());  
87 - // 4.2 更新流程变量  
88 - if (CollUtil.isNotEmpty(updateVariables)) {  
89 - processInstanceService.updateProcessInstanceVariables(processInstanceId, updateVariables);  
90 - }  
91 - }  
92 } catch (RestClientException e) { 78 } catch (RestClientException e) {
93 log.error("[execute][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); 79 log.error("[execute][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
  80 + return;
  81 + }
  82 +
  83 + // 4.1 判断是否需要解析返回值
  84 + if (StrUtil.isEmpty(responseEntity.getBody()) || !responseEntity.getStatusCode().is2xxSuccessful()
  85 + || CollUtil.isEmpty(setting.getResponse())) {
  86 + return;
  87 + }
  88 + // 4.2 解析返回值, 返回值必须符合 CommonResult 规范。
  89 + CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly(responseEntity.getBody(),
  90 + new TypeReference<>() {});
  91 + if (respResult == null || !respResult.isSuccess()){
  92 + return;
  93 + }
  94 + // 4.3 获取需要更新的流程变量
  95 + Map<String, Object> updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), setting.getResponse());
  96 + // 4.4 更新流程变量
  97 + if (CollUtil.isNotEmpty(updateVariables)) {
  98 + processInstanceService.updateProcessInstanceVariables(processInstanceId, updateVariables);
94 } 99 }
95 } 100 }
96 101
97 /** 102 /**
98 * 从请求返回值获取需要更新的流程变量 103 * 从请求返回值获取需要更新的流程变量
99 * 104 *
100 - * 优先从 data 字段获取,如果 data 字段不存在,从根节点获取  
101 - *  
102 - * @param responseBody 请求返回报文体 105 + * @param result 请求返回结果
103 * @param responseSettings 返回设置 106 * @param responseSettings 返回设置
104 * @return 需要更新的流程变量 107 * @return 需要更新的流程变量
105 */ 108 */
106 - private Map<String, Object> getNeedUpdatedVariablesFromResponse(String responseBody, 109 + private Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String,Object> result,
107 List<KeyValue<String, String>> responseSettings) { 110 List<KeyValue<String, String>> responseSettings) {
108 Map<String, Object> updateVariables = new HashMap<>(); 111 Map<String, Object> updateVariables = new HashMap<>();
109 - // TODO @jason:这里 if return 更简洁一点;  
110 - // TODO @jason:JSONUtil => JsonUtils,尽量包一层  
111 - if (JSONUtil.isTypeJSONObject(responseBody)) {  
112 - JSONObject dataObj = null;  
113 - if (JSONUtil.parseObj(responseBody).getObj(PARSE_RESPONSE_FIELD) instanceof JSONObject) {  
114 - dataObj = (JSONObject) JSONUtil.parseObj(responseBody).getObj(PARSE_RESPONSE_FIELD);  
115 - }  
116 - JSONObject updateObj = dataObj == null ? JSONUtil.parseObj(responseBody) : dataObj;  
117 - responseSettings.forEach(responseSetting -> {  
118 - if (StrUtil.isNotEmpty(responseSetting.getKey()) && updateObj.containsKey(responseSetting.getValue())) {  
119 - updateVariables.put(responseSetting.getKey(), updateObj.get(responseSetting.getValue()));  
120 - }  
121 - }); 112 + if (CollUtil.isEmpty(result)) {
  113 + return updateVariables;
122 } 114 }
  115 + responseSettings.forEach(responseSetting -> {
  116 + if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) {
  117 + updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue()));
  118 + }
  119 + });
123 return updateVariables; 120 return updateVariables;
124 } 121 }
125 122