每次对接第三方接口时候,都需要进行报文转换,把第三方的报文转换成我方接口报文,或者我方接口报文转换为第三方的报文。转换工作比较繁琐,如果可以做成配置化的,就方便了开发,所以写了个demo进行测试了下
首先,设计了表结构:
CREATE TABLE `thirdparty_param` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) NOT NULL COMMENT '父id',
`plat_model` varchar(255) NOT NULL COMMENT '平台id',
`param_name` varchar(255) DEFAULT NULL COMMENT '三方参数名',
`param_desc` text COMMENT '参数描述',
`param_type` varchar(255) DEFAULT NULL COMMENT '参数类型',
`param_data_type` varchar(255) DEFAULT NULL COMMENT '参数数据类型',
`value_type` varchar(255) DEFAULT NULL COMMENT '取值类型 1默认值 2取入参属性 3其他个性化',
`value` varchar(255) DEFAULT NULL COMMENT '转换报文参数取值',
`value_text` text,
`value_path` varchar(255) DEFAULT NULL,
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
`update_time` datetime DEFAULT NULL COMMENT '更新日期',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
/**
* 转换报文对象
* @param reqObj 转换后对象
* @param requestObj 转换前入参对象
* @param platModel 平台名
* @param pid 父id
* @return
*/
public JSONObject traverseParams(JSONObject reqObj,JSONObject requestObj, String platModel, int pid) {
List<ThirdpartyParam> roots = iThirdpartyParamService.getParamsByPlatAndPid(platModel, pid);
if (!roots.isEmpty()) {
for (ThirdpartyParam root : roots) {
List<ThirdpartyParam> roots2 = iThirdpartyParamService.getParamsByPlatAndPid(platModel, root.getId());
if (!roots2.isEmpty()) {
JSONObject object = new JSONObject();
if("array".equals(root.getParamDataType())){
//TODO 当前仅仅支持数组个数为1个元素,不支持多个
JSONArray array = new JSONArray();
array.add(traverseParams(object,requestObj,platModel,root.getId()));
reqObj.put(root.getParamName(),array);
} else{
reqObj.put(root.getParamName(),traverseParams(object,requestObj,platModel,root.getId()));
}
}else {
if ("1".equals(root.getValueType())) {//默认值
reqObj.put(root.getParamName(), root.getValue());
} else if ("2".equals(root.getValueType())) {
//TODO 取入参属性 个性化转换
List<Object> jsonFieldValue = getJsonFieldValue(requestObj, root.getValuePath());
if(jsonFieldValue.isEmpty()){
reqObj.put(root.getParamName(), null);
}else {
reqObj.put(root.getParamName(), jsonFieldValue.get(0));
}
} else if ("3".equals(root.getValueType())) {
//TODO 其他
} else {
reqObj.put(root.getParamName(), null);
}
}
}
}
return reqObj;
}
/**
* 根据path 路径 获取jsonObject节点的值 如: request.test
* @param jsonObject
* @param path
* @return
*/
public static List<Object> getJsonFieldValue(JSONObject jsonObject, String path) {
List<String> keyWordList = new ArrayList(Arrays.asList(path.split("\\.")));
List<Object> list = new ArrayList<>();
String key = keyWordList.get(0);
Object object = jsonObject.get(key);
keyWordList.remove(0);
if (keyWordList.isEmpty()) {
if (null != object) {
list.add(object);
}
return list;
}
String subPath = StringUtils.join(keyWordList, ".");
if (object instanceof JSONArray) {
JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(object));
if (jsonArray.isEmpty()) {
return new ArrayList<>();
}
jsonArray.forEach(e -> list.addAll(getJsonFieldValue(JSON.parseObject(JSON.toJSONString(e)), subPath)));
}else if(object instanceof JSONObject){
JSONObject subJsonObject = JSONObject.parseObject(JSON.toJSONString(object));
list.addAll(getJsonFieldValue(JSON.parseObject(JSON.toJSONString(subJsonObject)), subPath));
}
return list;
}
@Cacheable(cacheNames = "pb:IThirdpartyParamService:getParamsByPlatAndPid", key = "#platModel+#pid")
@Override
public List<ThirdpartyParam> getParamsByPlatAndPid(String platModel, int pid) {
return baseMapper.getParamsByPlatAndPid(platModel,pid);
}
<select id="getParamsByPlatAndPid" resultType="ThirdpartyParam">
select * from thirdparty_param where plat_model = #{platModel} and pid = #{pid}
</select>
经过测试,转换是可以正常转换的,但耗时还得再继续优化,当前一个报文转换得1600多ms,显然对于接口时效性是不太满足的。