diff --git a/README.md b/README.md index d15430ef3f6163aecb4011a6870cd9e38d275dd7..f6cbebe0def276c165e421452647c920f5cb7226 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,6 @@ REC(Rule Engine Component)规则引擎组件:提供统一的规则处理 | **字段名称** | **类型** | **备注** | | --- | --- | --- | | dataSourceName | String | 数据源名称 | -| dataSourceCode | String | 数据源Code | | dataSourceType | String | 数据源类型(脚本、HTTP、SQL) | | scriptInfo | Object | 数据源为脚本的执行数据集 | | httpInfo | Object | 数据源为HTTP的执行数据集 | diff --git a/pom.xml b/pom.xml index 0433361cd0a93101eca6db4250dc97acdb9e5cad..2c72dd098d1679c8f83a29bd18ad69e330306472 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,8 @@ 2.2.2.RELEASE 3.4 + 2.4 + 3.10.0 4.3 19.0 @@ -77,6 +79,17 @@ commons-lang3 ${commons.lang3.version} + + commons-io + commons-io + ${commons.io.version} + + + + com.squareup.okhttp3 + okhttp + ${ok-httpclient.version} + org.apache.commons commons-collections4 diff --git a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/BaseDataDebugResult.java b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/BaseDataDebugResult.java index d88ad8181752c43be520b6da53809192f141de90..00f1fe4052c662f3aceb005a884c35e114abe0a4 100644 --- a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/BaseDataDebugResult.java +++ b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/BaseDataDebugResult.java @@ -9,6 +9,7 @@ import java.io.Serializable; * @since 1.0 Created in 2022/11/13 14:47 */ public class BaseDataDebugResult implements Serializable { + private static final long serialVersionUID = 5879082736696321315L; /** * 是否执行成功 */ diff --git a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/DataSourceDebugResult.java b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/DataSourceDebugResult.java new file mode 100644 index 0000000000000000000000000000000000000000..9b7b0b2b5748f1633178b217ec30ab882e968643 --- /dev/null +++ b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/model/DataSourceDebugResult.java @@ -0,0 +1,75 @@ +package cn.icanci.rec.admin.biz.model; + +import java.io.Serializable; + +/** + * 数据源Debug返回结果 + * + * @author icanci + * @since 1.0 Created in 2022/11/13 14:47 + */ +public class DataSourceDebugResult implements Serializable { + private static final long serialVersionUID = -3567901817148802718L; + /** + * 是否执行成功 + */ + private boolean success; + /** + * 数据源类型 + */ + private String dataSourceType; + /** + * 脚本类型 + * + * 数据源类型为脚本的时候,scriptType 不为空 + */ + private String scriptType; + /** + * 实际执行结果 + */ + private Object realResult; + /** + * 执行过程中出现的异常 + */ + private String exceptionMessage; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getDataSourceType() { + return dataSourceType; + } + + public void setDataSourceType(String dataSourceType) { + this.dataSourceType = dataSourceType; + } + + public String getScriptType() { + return scriptType; + } + + public void setScriptType(String scriptType) { + this.scriptType = scriptType; + } + + public Object getRealResult() { + return realResult; + } + + public void setRealResult(Object realResult) { + this.realResult = realResult; + } + + public String getExceptionMessage() { + return exceptionMessage; + } + + public void setExceptionMessage(String exceptionMessage) { + this.exceptionMessage = exceptionMessage; + } +} diff --git a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/DataSourceService.java b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/DataSourceService.java index 10fe35055fe4d283b41027be315f1732d0bb6737..87a6f53167b4ecbb4d630ad345671239ec648f96 100644 --- a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/DataSourceService.java +++ b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/DataSourceService.java @@ -1,6 +1,8 @@ package cn.icanci.rec.admin.biz.service; +import cn.icanci.rec.admin.biz.model.DataSourceDebugResult; import cn.icanci.rec.admin.dal.mongodb.common.PageList; +import cn.icanci.rec.common.model.TextValue; import cn.icanci.rec.common.model.config.DataSourceVO; import java.util.List; @@ -21,4 +23,27 @@ public interface DataSourceService extends BaseService { @Override PageList queryPage(DataSourceVO dataSourceVO, int pageNum, int pageSize); + + /** + * 根据 dataSourceName 查询数据源 + * + * @param dataSourceName dataSourceName + * @return 返回 根据 dataSourceName 查询数据源 + */ + DataSourceVO queryByDataSourceName(String dataSourceName); + + /** + * 下拉框加载 + * + * @return 返回加载的数据 + */ + List loadSelector(); + + /** + * 对数据源进行预先执行 + * + * @param dataSource dataSource + * @return 返回执行结果 + */ + DataSourceDebugResult debug(DataSourceVO dataSource); } diff --git a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java index e67c996b85ec9573b77b5158044f450b39c53213..0352182a4247809928d9d36bf3bdc1cbe3317615 100644 --- a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java +++ b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java @@ -1,18 +1,23 @@ package cn.icanci.rec.admin.biz.service.impl; import cn.icanci.rec.admin.biz.mapper.DataSourceMapper; +import cn.icanci.rec.admin.biz.model.DataSourceDebugResult; import cn.icanci.rec.admin.biz.service.DataSourceService; import cn.icanci.rec.admin.dal.mongodb.common.PageList; import cn.icanci.rec.admin.dal.mongodb.daointerface.DataSourceDAO; import cn.icanci.rec.admin.dal.mongodb.dateobject.DataSourceDO; +import cn.icanci.rec.common.model.TextValue; import cn.icanci.rec.common.model.config.DataSourceVO; import java.util.List; import javax.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; +import com.google.common.collect.Lists; + /** * @author icanci * @since 1.0 Created in 2022/11/12 09:04 @@ -48,4 +53,35 @@ public class DataSourceServiceImpl implements DataSourceService { PageList pageQuery = dataSourceDAO.pageQuery(dataSourceMapper.vo2do(dataSource), pageNum, pageSize); return new PageList<>(dataSourceMapper.dos2vos(pageQuery.getData()), pageQuery.getPaginator()); } + + @Override + public DataSourceVO queryByDataSourceName(String dataSourceName) { + return dataSourceMapper.do2vo(dataSourceDAO.queryByDataSourceName(dataSourceName)); + } + + @Override + public List loadSelector() { + List dataSources = queryAll(); + if (CollectionUtils.isEmpty(dataSources)) { + return Lists.newArrayList(); + } + List textValues = Lists.newArrayList(); + for (DataSourceVO dataSource : dataSources) { + String label; + if (isDeleted(dataSource)) { + label = String.format(DELETED_FORMAT, dataSource.getDataSourceName()); + } else { + label = String.format(NOT_DELETED_FORMAT, dataSource.getDataSourceName()); + } + String value = dataSource.getUuid(); + textValues.add(new TextValue(label, value)); + } + return textValues; + } + + @Override + public DataSourceDebugResult debug(DataSourceVO dataSource) { + // TODO http 请求放哪里 + return null; + } } diff --git a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/DataSourceDAO.java b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/DataSourceDAO.java index 96706e9743aaad02aa4f705c0a056bad24d67d96..74f20f97e4c8001aa64812f2f09c35f3fcf69ac9 100644 --- a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/DataSourceDAO.java +++ b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/DataSourceDAO.java @@ -10,21 +10,19 @@ public interface DataSourceDAO extends BaseDAO { /** * 文档对应的名字 */ - String COLLECTION_NAME = "rec-dataSource"; + String COLLECTION_NAME = "rec-datasource"; /** * 文档对应的Class */ Class COLLECTION_CLASS = DataSourceDO.class; + DataSourceDO queryByDataSourceName(String dataSourceName); + interface DataSourceColumn extends BaseColumn { /** * 数据源名称 */ String dataSourceName = "dataSourceName"; - /** - * 数据源Code - */ - String dataSourceCode = "dataSourceCode"; /** * 数据源类型 */ diff --git a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/StrategyDAO.java b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/StrategyDAO.java index 2a4e4d0231407fd0fef3b01cca5482661c175cc4..7671a9ef522dd328a0695b5a0c4cb315257fee1c 100644 --- a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/StrategyDAO.java +++ b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/daointerface/StrategyDAO.java @@ -36,9 +36,9 @@ public interface StrategyDAO extends BaseDAO { */ String dataSourceType = "dataSourceType"; /** - * 数据源关联Code + * 数据源关联uuid */ - String dataSourceCode = "dataSourceCode"; + String dataSourceUuid = "dataSourceUuid"; /** * 规则配置类型(默认为List) */ diff --git a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/DataSourceDO.java b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/DataSourceDO.java index abc681d20a258da44c44331bc909d9a427eccf72..313e66d04074f2dd2484e28c9198305535c8cdcb 100644 --- a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/DataSourceDO.java +++ b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/DataSourceDO.java @@ -14,10 +14,6 @@ public class DataSourceDO extends BaseDO { * 数据源名称 */ private String dataSourceName; - /** - * 数据源Code - */ - private String dataSourceCode; /** * 数据源类型 * @see DataSourceTypeEnum@name() @@ -185,14 +181,6 @@ public class DataSourceDO extends BaseDO { this.dataSourceName = dataSourceName; } - public String getDataSourceCode() { - return dataSourceCode; - } - - public void setDataSourceCode(String dataSourceCode) { - this.dataSourceCode = dataSourceCode; - } - public String getDataSourceType() { return dataSourceType; } diff --git a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/StrategyDO.java b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/StrategyDO.java index 66c42915742ea638b415e6a8632b97f049ba7c58..e31ccb4e00a7c022192419cf3d1cd0b0213c3d07 100644 --- a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/StrategyDO.java +++ b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/dateobject/StrategyDO.java @@ -28,9 +28,9 @@ public class StrategyDO extends BaseDO { */ private String dataSourceType; /** - * 数据源关联Code + * 数据源关联uuid */ - private String dataSourceCode; + private String dataSourceUuid; /** * 规则配置类型(默认为List) * @@ -78,12 +78,12 @@ public class StrategyDO extends BaseDO { this.dataSourceType = dataSourceType; } - public String getDataSourceCode() { - return dataSourceCode; + public String getDataSourceUuid() { + return dataSourceUuid; } - public void setDataSourceCode(String dataSourceCode) { - this.dataSourceCode = dataSourceCode; + public void setDataSourceUuid(String dataSourceUuid) { + this.dataSourceUuid = dataSourceUuid; } public String getRuleType() { diff --git a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/mongo/MongoDataSourceDAO.java b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/mongo/MongoDataSourceDAO.java index 740e3df355c89542d9d84c0a31b75565eb09e9a6..ba23b892453b1ec1f3681f52dabc18988d1e06b1 100644 --- a/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/mongo/MongoDataSourceDAO.java +++ b/rec-admin/rec-admin-dal/src/main/java/cn/icanci/rec/admin/dal/mongodb/mongo/MongoDataSourceDAO.java @@ -1,9 +1,5 @@ package cn.icanci.rec.admin.dal.mongodb.mongo; -import cn.icanci.rec.admin.dal.mongodb.common.PageList; -import cn.icanci.rec.admin.dal.mongodb.daointerface.DataSourceDAO; -import cn.icanci.rec.admin.dal.mongodb.dateobject.DataSourceDO; - import java.util.List; import org.apache.commons.lang3.StringUtils; @@ -12,6 +8,10 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; +import cn.icanci.rec.admin.dal.mongodb.common.PageList; +import cn.icanci.rec.admin.dal.mongodb.daointerface.DataSourceDAO; +import cn.icanci.rec.admin.dal.mongodb.dateobject.DataSourceDO; + /** * @author icanci * @since 1.0 Created in 2022/11/11 15:52 @@ -42,10 +42,6 @@ public class MongoDataSourceDAO extends AbstractBaseDAO implements @Override public PageList pageQuery(DataSourceDO dataSourceDO, int pageNum, int pageSize) { Criteria criteria = Criteria.where(DataSourceColumn.env).is(DEFAULT_ENV); - if (StringUtils.isNotBlank(dataSourceDO.getDataSourceCode())) { - // 不分区大小写查询,其中操作符"i":表示不分区大小写 - criteria.and(DataSourceColumn.dataSourceCode).regex("^.*" + dataSourceDO.getDataSourceCode() + ".*$", "i"); - } if (StringUtils.isNotBlank(dataSourceDO.getDataSourceName())) { // 不分区大小写查询,其中操作符"i":表示不分区大小写 criteria.and(DataSourceColumn.dataSourceName).regex("^.*" + dataSourceDO.getDataSourceName() + ".*$", "i"); @@ -66,6 +62,13 @@ public class MongoDataSourceDAO extends AbstractBaseDAO implements criteria.and(DataSourceColumn.env).is(DEFAULT_ENV); Query query = new Query(criteria); return mongoTemplate.findOne(query, COLLECTION_CLASS, COLLECTION_NAME); + } + @Override + public DataSourceDO queryByDataSourceName(String dataSourceName) { + Criteria criteria = Criteria.where(DataSourceColumn.dataSourceName).is(dataSourceName); + criteria.and(DataSourceColumn.env).is(DEFAULT_ENV); + Query query = new Query(criteria); + return mongoTemplate.findOne(query, COLLECTION_CLASS, COLLECTION_NAME); } } diff --git a/rec-admin/rec-admin-views/src/main/resources/vueboot/src/api/dataSourceApi.js b/rec-admin/rec-admin-views/src/main/resources/vueboot/src/api/dataSourceApi.js new file mode 100644 index 0000000000000000000000000000000000000000..e3f5474bb19ea28ac86e926f65da3a53b1bf667c --- /dev/null +++ b/rec-admin/rec-admin-views/src/main/resources/vueboot/src/api/dataSourceApi.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +/** + * 验证 dataSourceName + * + * @param dataSourceName dataSourceName + * @returns {*} + */ +export async function remoteValidateDataSourceName(dataSourceName) { + return await request({ + url: '/rec/dataSource/validateDataSourceName/' + dataSourceName, + method: 'get', + }) +} + +/** + * 保存 + * + * @param dataSource dataSource + * @returns {*} + */ +export async function saveDataSource(dataSource) { + return await request({ + url: '/rec/dataSource/save', + method: 'post', + data: dataSource + }) +} + +/** + * 分页查询 + * + * @param baseData baseData + * @param paginator paginator + * @returns {*} + */ +export async function dataSourcePageQuery(dataSource, paginator) { + return await request({ + url: '/rec/dataSource/query', + method: 'post', + data: { + 'dataSource': dataSource, + 'paginator': paginator + } + }) +} + +/** + * 测试 + * + * @param dataSource dataSource + * @returns {*} + */ +export async function dataSourceDebug(dataSource) { + return await request({ + url: '/rec/dataSource/debug', + method: 'post', + data: dataSource + }) +} diff --git a/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/controller/config/DataSourceController.java b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/controller/config/DataSourceController.java new file mode 100644 index 0000000000000000000000000000000000000000..ebd7191ca5794e5553c181d619af5088a95bd1cb --- /dev/null +++ b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/controller/config/DataSourceController.java @@ -0,0 +1,62 @@ +package cn.icanci.rec.admin.web.controller.config; + +import cn.icanci.rec.admin.biz.model.DataSourceDebugResult; +import cn.icanci.rec.admin.biz.service.DataSourceService; +import cn.icanci.rec.admin.web.form.DataSourceQueryForm; +import cn.icanci.rec.admin.web.mapper.DataSourceWebMapper; +import cn.icanci.rec.admin.web.model.DataSource; +import cn.icanci.rec.common.model.TextValue; +import cn.icanci.rec.common.model.config.DataSourceVO; +import cn.icanci.rec.common.result.R; + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.web.bind.annotation.*; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 08:35 + */ +@RestController +@RequestMapping("/rec/dataSource") +public class DataSourceController { + @Resource + private DataSourceService dataSourceService; + @Resource + private DataSourceWebMapper dataSourceWebMapper; + + // ================================ CRUD ================================ + @PostMapping("query") + public R query(@RequestBody DataSourceQueryForm form) { + return R.builderOk().data("queryPage", + dataSourceService.queryPage(dataSourceWebMapper.web2vo(form.getDataSource()), form.getPaginator().getCurrentPage(), form.getPaginator().getPageSize())).build(); + } + + @PostMapping("save") + public R save(@RequestBody DataSource dataSource) { + dataSourceService.save(dataSourceWebMapper.web2vo(dataSource)); + return R.builderOk().build(); + } + + @GetMapping("validateDataSourceName/{dataSourceName}") + public R validateDataSourceName(@PathVariable("dataSourceName") String dataSourceName) { + DataSourceVO dataSource = dataSourceService.queryByDataSourceName(dataSourceName); + return R.builderOk().data("result", dataSource == null).build(); + } + // ================================ Load Selectors ================================ + + @GetMapping("loadSelector") + public R loadSelector() { + List textValues = dataSourceService.loadSelector(); + return R.builderOk().data("textValues", textValues).build(); + } + // ================================ Debug ================================ + + @PostMapping("debug") + public R debug(@RequestBody DataSource dataSource) { + DataSourceDebugResult result = dataSourceService.debug(dataSourceWebMapper.web2vo(dataSource)); + return R.builderOk().data("result", result).build(); + } +} diff --git a/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/form/DataSourceQueryForm.java b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/form/DataSourceQueryForm.java new file mode 100644 index 0000000000000000000000000000000000000000..f7bcce57ce5ddd4889e00b1dd6e4d611f569b1c2 --- /dev/null +++ b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/form/DataSourceQueryForm.java @@ -0,0 +1,22 @@ +package cn.icanci.rec.admin.web.form; + +import cn.icanci.rec.admin.web.model.DataSource; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 08:40 + */ +public class DataSourceQueryForm extends BaseQueryForm { + + private static final long serialVersionUID = -5707057820546333067L; + + private DataSource dataSource; + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } +} diff --git a/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/DataSource.java b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/DataSource.java index ca662bdb31f83df6dfd7495064aece1a9d91ab7a..2dddeb12fc53350d014fa8575837f7fbd72daa64 100644 --- a/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/DataSource.java +++ b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/DataSource.java @@ -15,10 +15,6 @@ public class DataSource extends Base { * 数据源名称 */ private String dataSourceName; - /** - * 数据源Code - */ - private String dataSourceCode; /** * 数据源类型 * @see DataSourceTypeEnum@name() @@ -186,14 +182,6 @@ public class DataSource extends Base { this.dataSourceName = dataSourceName; } - public String getDataSourceCode() { - return dataSourceCode; - } - - public void setDataSourceCode(String dataSourceCode) { - this.dataSourceCode = dataSourceCode; - } - public String getDataSourceType() { return dataSourceType; } diff --git a/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/Strategy.java b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/Strategy.java index e48b697a919f186b138ee9455729108c107202f6..4d4d3b946a1b9116f271c9b48dfe717ce33cd7fd 100644 --- a/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/Strategy.java +++ b/rec-admin/rec-admin-web/src/main/java/cn/icanci/rec/admin/web/model/Strategy.java @@ -29,9 +29,9 @@ public class Strategy extends Base { */ private String dataSourceType; /** - * 数据源关联Code + * 数据源关联uuid */ - private String dataSourceCode; + private String dataSourceUuid; /** * 规则配置类型(默认为List) * @@ -79,12 +79,12 @@ public class Strategy extends Base { this.dataSourceType = dataSourceType; } - public String getDataSourceCode() { - return dataSourceCode; + public String getDataSourceUuid() { + return dataSourceUuid; } - public void setDataSourceCode(String dataSourceCode) { - this.dataSourceCode = dataSourceCode; + public void setDataSourceUuid(String dataSourceUuid) { + this.dataSourceUuid = dataSourceUuid; } public String getRuleType() { diff --git a/rec-common/src/main/java/cn/icanci/rec/common/model/config/DataSourceVO.java b/rec-common/src/main/java/cn/icanci/rec/common/model/config/DataSourceVO.java index 8a74664e5d1f2777eacc052e9919f4f08eba6578..ac3975f7629df62a28034f55f06db7e3f0dde3f9 100644 --- a/rec-common/src/main/java/cn/icanci/rec/common/model/config/DataSourceVO.java +++ b/rec-common/src/main/java/cn/icanci/rec/common/model/config/DataSourceVO.java @@ -16,10 +16,6 @@ public class DataSourceVO extends BaseVO { * 数据源名称 */ private String dataSourceName; - /** - * 数据源Code - */ - private String dataSourceCode; /** * 数据源类型 */ @@ -45,14 +41,6 @@ public class DataSourceVO extends BaseVO { this.dataSourceName = dataSourceName; } - public String getDataSourceCode() { - return dataSourceCode; - } - - public void setDataSourceCode(String dataSourceCode) { - this.dataSourceCode = dataSourceCode; - } - public DataSourceTypeEnum getDataSourceType() { return dataSourceType; } diff --git a/rec-common/src/main/java/cn/icanci/rec/common/model/config/StrategyVO.java b/rec-common/src/main/java/cn/icanci/rec/common/model/config/StrategyVO.java index ec5e21d04d01578819e1cd5a41cd57e6e20b4f7c..4e6cccfc4475d4de2ea892bc6f0931b2cb17c67f 100644 --- a/rec-common/src/main/java/cn/icanci/rec/common/model/config/StrategyVO.java +++ b/rec-common/src/main/java/cn/icanci/rec/common/model/config/StrategyVO.java @@ -28,9 +28,9 @@ public class StrategyVO extends BaseVO { */ private DataSourceTypeEnum dataSourceType; /** - * 数据源关联Code + * 数据源关联uuid */ - private String dataSourceCode; + private String dataSourceUuid; /** * 规则配置类型(默认为List) */ @@ -76,12 +76,12 @@ public class StrategyVO extends BaseVO { this.dataSourceType = dataSourceType; } - public String getDataSourceCode() { - return dataSourceCode; + public String getDataSourceUuid() { + return dataSourceUuid; } - public void setDataSourceCode(String dataSourceCode) { - this.dataSourceCode = dataSourceCode; + public void setDataSourceUuid(String dataSourceUuid) { + this.dataSourceUuid = dataSourceUuid; } public RuleTypeEnum getRuleType() { diff --git a/rec-common/src/main/java/cn/icanci/rec/common/utils/FastJsonUtils.java b/rec-common/src/main/java/cn/icanci/rec/common/utils/FastJsonUtils.java index c21e505518ff7255826d07db7d784c3fce130e30..5e87775aeacb86bbb92338e8a8863eb51b0c41d2 100644 --- a/rec-common/src/main/java/cn/icanci/rec/common/utils/FastJsonUtils.java +++ b/rec-common/src/main/java/cn/icanci/rec/common/utils/FastJsonUtils.java @@ -6,6 +6,7 @@ import java.util.Date; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; @@ -254,4 +255,32 @@ public class FastJsonUtils { buff.append(json.substring(1)); return buff.toString(); } + + /** + * 判断字符串是否是JSON + * Tip: 会出现数字返回ture的情况,此处如果是数字,返回false + * 会出现 boolean 值返回true的情况,需要处理 + * + * @param str str + * @return 返回字符串是否是JSON + */ + public static boolean isJson(String str) { + if (StringUtils.isBlank(str)) { + return false; + } + str = str.trim(); + + if (NumberUtils.isNumber(str)) { + return false; + } + if (StringUtils.equals(Boolean.TRUE.toString(), str)) { + return false; + } + try { + JSON.parse(str); + return true; + } catch (Exception e) { + return false; + } + } } diff --git a/rec-engine/rec-engine-script/pom.xml b/rec-engine/rec-engine-script/pom.xml index e3da15767d05bc4b7bef130bb487b800aa99ddd1..1aaab1db97a54d5d07a01fc6b51e5c9bb4f14ba1 100644 --- a/rec-engine/rec-engine-script/pom.xml +++ b/rec-engine/rec-engine-script/pom.xml @@ -36,6 +36,14 @@ org.apache.commons commons-lang3 + + commons-io + commons-io + + + com.squareup.okhttp3 + okhttp + org.apache.commons commons-collections4 diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/RecScriptEngine.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/RecScriptEngine.java index 00319f63e1d85998b90fec762b2326c6ff7c18b5..141574c030a8c429ed5653c4c8d1d6bf3c1b6615 100644 --- a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/RecScriptEngine.java +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/RecScriptEngine.java @@ -1,7 +1,9 @@ package cn.icanci.rec.engine.script; +import cn.icanci.rec.common.enums.HttpRequestTypeEnum; import cn.icanci.rec.common.enums.ScriptTypeEnum; import cn.icanci.rec.engine.script.context.RecScriptEngineContext; +import cn.icanci.rec.engine.script.wrapper.HttpResponseWrapper; import javax.script.Bindings; @@ -12,6 +14,7 @@ import javax.script.Bindings; * @since 1.0 Created in 2022/11/12 22:12 */ public interface RecScriptEngine { + // ================================ 脚本执行 ================================ /** * 执行脚本 * @@ -54,4 +57,15 @@ public interface RecScriptEngine { */ RecScriptEngineContext eval(ScriptTypeEnum scriptType, Bindings bindings, String script, Class clazz); + // ================================ HTTP 请求执行 ================================ + /** + * 执行HTTP请求 + * + * @param requestType 请求类型 + * @param reqUrl 请求路径 + * @param reqParam 请求类型为POST的请求参数 + * @param timeout 请求超时时间 + * @return 返回请求执行结果 + */ + HttpResponseWrapper httpEval(HttpRequestTypeEnum requestType, String reqUrl, String reqParam, int timeout); } diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/AbstractRetryClient.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/AbstractRetryClient.java new file mode 100644 index 0000000000000000000000000000000000000000..ea27eac27bb5853f6d225917df18b29481f1075f --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/AbstractRetryClient.java @@ -0,0 +1,60 @@ +package cn.icanci.rec.engine.script.client; + +import java.io.IOException; + +/** + * 自动重试客户端 + * + * @author icanci + * @since 1.0 Created in 2022/11/14 22:16 + */ +public abstract class AbstractRetryClient implements Client { + + /** + * 远程调用 + * + * @param request http 请求 + * @param clazz 应答类型 + * @return 应答数据 + * @throws RemoteException 远程调用异常 + */ + @Override + public V call(RpcRequest request, Class clazz) throws RemoteException { + return retry(request, clazz, 0, request.getRetry()); + } + + /** + * 重试 + * + * @param request 请求 + * @param clazz 序列化类 + * @param retryCount 第几次重试 + * @param retry 重试次数 + * @param 类型 + * @return 结果 + * @throws RemoteException + */ + private V retry(RpcRequest request, Class clazz, int retryCount, int retry) throws RemoteException { + try { + return doExecute(request, clazz); + } catch (RemoteException e) { + throw e; + } catch (IOException e) { + while (retryCount < retry) { + retryCount++; + return retry(request, clazz, retry, retryCount); + } + throw new RemoteException(e.getMessage(), e); + } + } + + /** + * Do execute v. + * + * @param the type parameter + * @param request the request + * @param clazz the clazz + * @return the v + */ + protected abstract V doExecute(RpcRequest request, Class clazz) throws IOException; +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/Client.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/Client.java new file mode 100644 index 0000000000000000000000000000000000000000..e1df4779a25fe78824e37e448472f1f1b66fa6a2 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/Client.java @@ -0,0 +1,323 @@ +package cn.icanci.rec.engine.script.client; + +import cn.icanci.rec.engine.script.client.serializer.SerializerEnum; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public interface Client { + /** + * 远程调用 + * + * @param request http 请求 + * @param clazz 应答类型 + * @param 应答类型 + * @return 应答数据 + * @throws RemoteException 远程调用异常 + */ + V call(RpcRequest request, Class clazz) throws RemoteException; + + /** + * The type Http request. + */ + class RpcRequest { + private Object body; + private String mediaType; + private Map headers = new HashMap<>(); + private String url; + private String method; + private long readTimeOut; + private TimeUnit timeUnit; + private int retry; + private SerializerEnum reqSerializer; + private SerializerEnum repSerializer; + + // 用于get请求 + private boolean isEncode; + + // Content-Type: application/x-www-form-urlencoded 专用 + private String key; + + /** + * Instantiates a new Http request. + */ + RpcRequest() { + } + + /** + * Instantiates a new Http request. + * + * @param body the body + * @param mediaType the type + * @param headers the headers + * @param url the url + * @param method the method + * @param isEncode the encode + * @param readTimeOut the read timeout + * @param timeUnit the time unit + * @param retry the retry + * @param reqSerializer the request serializer type + * @param repSerializer the response serializer type + */ + public RpcRequest(Object body, String mediaType, Map headers, String url, String method, boolean isEncode, long readTimeOut, TimeUnit timeUnit, int retry, + SerializerEnum reqSerializer, SerializerEnum repSerializer) { + this.body = body; + this.mediaType = mediaType; + this.headers = headers; + this.url = url; + this.method = method; + this.isEncode = isEncode; + this.timeUnit = timeUnit; + this.readTimeOut = readTimeOut; + this.retry = retry; + this.reqSerializer = reqSerializer; + this.repSerializer = repSerializer; + } + + /** + * Gets the value of body. + * + * @return the value of body + */ + public Object getBody() { + return body; + } + + /** + * Gets the value of mediaType. + * + * @return the value of mediaType + */ + public String getMediaType() { + return mediaType; + } + + /** + * Gets the value of headers. + * + * @return the value of headers + */ + public Map getHeaders() { + return headers; + } + + /** + * Gets the value of url. + * + * @return the value of url + */ + public String getUrl() { + return url; + } + + /** + * Gets the value of method. + * + * @return the value of method + */ + public String getMethod() { + return method; + } + + /** + * Gets the value of isEncode. + * + * @return the value of isEncode + */ + public boolean isEncode() { + return isEncode; + } + + /** + * Gets the value of readTimeOut. + * + * @return the value of readTimeOut + */ + public long getReadTimeOut() { + return readTimeOut; + } + + /** + * Gets the value of timeUnit. + * + * @return the value of timeUnit + */ + public TimeUnit getTimeUnit() { + return timeUnit; + } + + /** + * Gets the value of retry. + * + * @return the value of retry + */ + public int getRetry() { + return retry; + } + + /** + * Gets the value of reqSerializer. + * + * @return the value of reqSerializer + */ + public SerializerEnum getReqSerializer() { + return reqSerializer; + } + + /** + * Gets the value of repSerializer. + * + * @return the value of repSerializer + */ + public SerializerEnum getRepSerializer() { + return repSerializer; + } + + /** + * Gets the value of key. + * + * @return the value of key + */ + public String getKey() { + return key; + } + + /** + * Sets the key. + *

You can use getKey() to get the value of key

+ * + * @param key key + */ + public void setKey(String key) { + this.key = key; + } + + /** + * Sets the body. + *

You can use getBody() to get the value of body

+ * + * @param body body + */ + public void setBody(Object body) { + this.body = body; + } + + /** + * Sets the mediaType. + *

You can use getMediaType() to get the value of mediaType

+ * + * @param mediaType mediaType + */ + public void setMediaType(String mediaType) { + this.mediaType = mediaType; + } + + /** + * Sets the headers. + *

You can use getHeaders() to get the value of headers

+ * + * @param headers headers + */ + public void setHeaders(Map headers) { + this.headers = headers; + } + + /** + * Sets the url. + *

You can use getUrl() to get the value of url

+ * + * @param url url + */ + public void setUrl(String url) { + this.url = url; + } + + /** + * Sets the method. + *

You can use getMethod() to get the value of method

+ * + * @param method method + */ + public void setMethod(String method) { + this.method = method; + } + + /** + * Sets the readTimeOut. + *

You can use getReadTimeOut() to get the value of readTimeOut

+ * + * @param readTimeOut readTimeOut + */ + public void setReadTimeOut(long readTimeOut) { + this.readTimeOut = readTimeOut; + } + + /** + * Sets the timeUnit. + *

You can use getTimeUnit() to get the value of timeUnit

+ * + * @param timeUnit timeUnit + */ + public void setTimeUnit(TimeUnit timeUnit) { + this.timeUnit = timeUnit; + } + + /** + * Sets the retry. + *

You can use getRetry() to get the value of retry

+ * + * @param retry retry + */ + public void setRetry(int retry) { + this.retry = retry; + } + + /** + * Sets the reqSerializer. + *

You can use getReqSerializer() to get the value of reqSerializer

+ * + * @param reqSerializer reqSerializer + */ + public void setReqSerializer(SerializerEnum reqSerializer) { + this.reqSerializer = reqSerializer; + } + + /** + * Sets the repSerializer. + *

You can use getRepSerializer() to get the value of repSerializer

+ * + * @param repSerializer repSerializer + */ + public void setRepSerializer(SerializerEnum repSerializer) { + this.repSerializer = repSerializer; + } + + /** + * Sets the isEncode. + *

You can use getEncode() to get the value of isEncode

+ * + * @param encode encode + */ + public void setEncode(boolean encode) { + isEncode = encode; + } + + /** + * Get the body content as byte array + * + * @return the byte array + */ + public byte[] getBodyAsBytes() { + byte[] dataBytes = new byte[0]; + if (null != this.getBody()) { + dataBytes = this.getReqSerializer().getSerializer().serialize(this.getBody()).getBytes(); + } + return dataBytes; + } + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/RemoteException.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/RemoteException.java new file mode 100644 index 0000000000000000000000000000000000000000..bd78aef50cd3f5ad94b5f02c1abc0069e372089d --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/RemoteException.java @@ -0,0 +1,116 @@ +package cn.icanci.rec.engine.script.client; + +import java.io.IOException; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:15 + */ +public class RemoteException extends IOException { + /** 序列化版本 */ + private static final long serialVersionUID = -850230685842125442L; + + private int code = -1; + + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param code error code + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public RemoteException(int code, String message) { + super(message); + this.code = code; + } + + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public RemoteException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and + * cause.

Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this exception's detail message. + * + * @param code error code + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public RemoteException(int code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + /** + * Constructs a new exception with the specified detail message and + * cause.

Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public RemoteException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new exception with the specified cause and a detail + * message of (cause==null ? null : cause.toString()) (which + * typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than + * wrappers for other throwables (for example, {@link + * PrivilegedActionException}). + * + * @param code error code + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public RemoteException(int code, Throwable cause) { + super(cause); + this.code = code; + } + + /** + * Constructs a new exception with the specified cause and a detail + * message of (cause==null ? null : cause.toString()) (which + * typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than + * wrappers for other throwables (for example, {@link + * PrivilegedActionException}). + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public RemoteException(Throwable cause) { + super(cause); + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/ByteArrayMessageConverter.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/ByteArrayMessageConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..492ccaba187470bbee0e02d0d1b67be6d9f54eb7 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/ByteArrayMessageConverter.java @@ -0,0 +1,33 @@ +package cn.icanci.rec.engine.script.client.http; + +import okhttp3.Response; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.apache.commons.io.IOUtils; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +class ByteArrayMessageConverter implements MessageConverter { + /** + * Read internal t + * + * @param response the response + * @return the de-serialized data + */ + @Override + public byte[] readInternal(Response response) { + long contentLength = response.body().contentLength(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(contentLength >= 0L ? (int) contentLength : 4096); + try { + IOUtils.copy(response.body().byteStream(), bos); + return bos.toByteArray(); + } catch (IOException ignore) { + // no op + } + return null; + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/HttpMethod.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/HttpMethod.java new file mode 100644 index 0000000000000000000000000000000000000000..ecc5cc0e9efca6aa27de525a9ce7af9e11255fd2 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/HttpMethod.java @@ -0,0 +1,43 @@ +package cn.icanci.rec.engine.script.client.http; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:28 + */ +public enum HttpMethod { + + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; + + private static final Map mappings = new HashMap<>(16); + + static { + for (HttpMethod httpMethod : values()) { + mappings.put(httpMethod.name(), httpMethod); + } + } + + /** + * Resolve the given method value to an {@code HttpMethod}. + * @param method the method value as a String + * @return the corresponding {@code HttpMethod}, or {@code null} if not found + * @since 4.2.4 + */ + public static HttpMethod resolve(String method) { + return (method != null ? mappings.get(method) : null); + } + + /** + * Determine whether this {@code HttpMethod} matches the given + * method value. + * @param method the method value as a String + * @return {@code true} if it matches, {@code false} otherwise + * @since 4.2.4 + */ + public boolean matches(String method) { + return (this == resolve(method)); + } + +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/MessageConverter.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/MessageConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..52755a5f9c7d612e9633202610297b4d9bf9e3a0 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/MessageConverter.java @@ -0,0 +1,18 @@ +package cn.icanci.rec.engine.script.client.http; + +import okhttp3.Response; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public interface MessageConverter { + + /** + * Read internal t + * + * @param response the response + * @return the de-serialized data + */ + T readInternal(Response response); +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/OkHttpClientImpl.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/OkHttpClientImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..415604d038e3f09b7149cfc062a202ce403dabbb --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/OkHttpClientImpl.java @@ -0,0 +1,240 @@ +package cn.icanci.rec.engine.script.client.http; + +import cn.icanci.rec.engine.script.client.AbstractRetryClient; +import cn.icanci.rec.engine.script.client.Client; +import cn.icanci.rec.engine.script.client.http.interceptor.HttpCodeInterceptor; +import cn.icanci.rec.engine.script.client.http.interceptor.NetworkInterceptor; +import cn.icanci.rec.engine.script.client.serializer.Serializer; +import cn.icanci.rec.engine.script.client.serializer.SerializerEnum; +import okhttp3.*; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +@SuppressWarnings("all") +public class OkHttpClientImpl extends AbstractRetryClient { + private static final long DEFAULT_TIMEOUT = 3; + private static final TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS; + private static final OkHttpClient CLIENT = new OkHttpClient(); + private static final Map CLIENTS = new ConcurrentHashMap<>(); + private static final Map CONVERTER_MAP = new HashMap<>(); + private static final Interceptor NETWORK_INTERCEPTOR = new NetworkInterceptor(); + private static final Interceptor HTTP_CODE_INTERCEPTOR = new HttpCodeInterceptor(); + + static { + CONVERTER_MAP.put(String.class, new StringMessageConverter()); + CONVERTER_MAP.put(byte[].class, new ByteArrayMessageConverter()); + } + + /** + * Get the instance of client + * + * @return the instance of client + */ + public static Client getInstance() { + return OkHttpClientImplHolder.CLIENT_IMPL; + } + + /** + * Do execute v. + * + * @param request the request + * @param clazz the clazz + * @return the v + */ + @Override + protected V doExecute(RpcRequest request, Class clazz) throws IOException { + Request.Builder builder = new Request.Builder(); + addHeaders(request, builder); + + try { + switch (request.getMethod()) { + case "GET": + String url = buildGetInfo(request); + builder.url(url).get(); + return doExecute(request, builder.build(), clazz); + + case "POST": + RequestBody content = buildPostInfo(request); + builder.url(request.getUrl()).post(content); + return doExecute(request, builder.build(), clazz); + + case "PUT": + case "DELETE": + default: + throw new UnsupportedOperationException("HTTP method: " + request.getMethod()); + + } + } catch (IOException e) { + throw e; + } + } + + /** + * 构建 POST 方法请求参数 + * + * @param request http 请求 + * @return http 请求数据 + */ + protected RequestBody buildPostInfo(RpcRequest request) { + MediaType mediaType = MediaType.parse(request.getMediaType()); + Object param = request.getBody(); + if (param == null) { + return RequestBody.create(mediaType, StringUtils.EMPTY); + } + if (String.class.isAssignableFrom(param.getClass())) { + return RequestBody.create(mediaType, String.class.cast(param)); + } + + if (request.getReqSerializer() == null) { + throw new IllegalArgumentException("The serializer is required for type " + param.getClass()); + } + Serializer serializer = request.getReqSerializer().getSerializer(); + String dataString = serializer.serialize(param); + return RequestBody.create(mediaType, dataString); + } + + /** + * 构建 GET 方法请求参数 + * + * @param request http 请求 + * @return GET 方法请求参数 + * @throws UnsupportedEncodingException 异常 + */ + protected String buildGetInfo(RpcRequest request) throws UnsupportedEncodingException { + String url = request.getUrl(); + if (StringUtils.isBlank(request.getBody().toString())) { + return url; + } + Map params = (Map) request.getBody(); + boolean encoded = request.isEncode(); + + if (MapUtils.isNotEmpty(params)) { + StringBuilder sb = new StringBuilder(); + if (encoded) { + for (Map.Entry param : params.entrySet()) { + sb.append(param.getKey()).append("=").append(URLEncoder.encode(param.getValue(), StandardCharsets.UTF_8.name())); + sb.append("&"); + } + } else { + for (Map.Entry param : params.entrySet()) { + sb.append(param.getKey()).append("=").append(param.getValue()); + sb.append("&"); + } + } + String paramStr = StringUtils.stripEnd(sb.toString(), "&"); + url = url + "?" + paramStr; + } + return url; + } + + /** + * http calling + * + * @param rpcRequest rpc request + * @param request http request + * @param clazz response class + * @param the response type + * @return response object + * @throws IOException io 异常 + */ + private V doExecute(RpcRequest rpcRequest, Request request, Class clazz) throws IOException { + OkHttpClient client = getClient(rpcRequest.getReadTimeOut(), rpcRequest.getTimeUnit()); + Response response = client.newCall(request).execute(); + if (clazz != String.class || clazz != byte[].class) { + String metaData = (String) CONVERTER_MAP.get(String.class).readInternal(response); + SerializerEnum serializerEnum = rpcRequest.getRepSerializer(); + return serializerEnum == null ? (V) metaData : serializerEnum.getSerializer().deserialize(metaData, clazz); + } + return (V) CONVERTER_MAP.get(clazz).readInternal(response); + } + + /** + * 构建 HTTP 头信息 + * + * @param request http request + * @param builder request builder + */ + private void addHeaders(RpcRequest request, Request.Builder builder) { + Map headers = request.getHeaders(); + if (MapUtils.isEmpty(headers)) { + return; + } + for (Map.Entry item : request.getHeaders().entrySet()) { + builder.addHeader(item.getKey(), item.getValue()); + } + } + + /** + * 获取客户端连接 + * + * @return okhttp client + */ + private OkHttpClient getClient(long timeout, TimeUnit timeUnit) { + if (timeout == 0) { + timeout = DEFAULT_TIMEOUT; + timeUnit = DEFAULT_TIMEUNIT; + } + + String key = buildClientKey(timeout, timeUnit); + + OkHttpClient client = CLIENTS.get(key); + if (client == null) { + client = newClient(timeout, timeUnit); + } + return client; + } + + /** + * 创建新客户端 + * + * @param timeout the timeout + * @param timeUnit the unit of timeout + * @return the okhttp client instance + */ + private OkHttpClient newClient(long timeout, TimeUnit timeUnit) { + OkHttpClient.Builder builder = CLIENT.newBuilder(); + builder.connectTimeout(timeout, timeUnit); + builder.readTimeout(timeout, timeUnit); + builder.writeTimeout(timeout, timeUnit); + builder.connectionPool(new ConnectionPool(64, 180, TimeUnit.SECONDS)); + builder.addInterceptor(HTTP_CODE_INTERCEPTOR); + builder.addNetworkInterceptor(NETWORK_INTERCEPTOR); + OkHttpClient client = builder.build(); + String key = buildClientKey(timeout, timeUnit); + CLIENTS.putIfAbsent(key, client); + return client; + } + + /** + * Build client key + * timeout + timeout unit + * + * @param timeout 超时时间 + * @param timeUnit 超时时间单位 + * @return key + */ + private static String buildClientKey(long timeout, TimeUnit timeUnit) { + return timeout + timeUnit.toString(); + } + + /** + * Ok http client holder + */ + private static final class OkHttpClientImplHolder { + private static final OkHttpClientImpl CLIENT_IMPL = new OkHttpClientImpl(); + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/StringMessageConverter.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/StringMessageConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..bbab9c9fdbbb3afc9a51632faabb45a285372733 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/StringMessageConverter.java @@ -0,0 +1,30 @@ +package cn.icanci.rec.engine.script.client.http; + +import okhttp3.Response; +import okhttp3.ResponseBody; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +class StringMessageConverter implements MessageConverter { + /** + * Read internal t + * + * @param response the response + * @return the de-serialized data + */ + @Override + public String readInternal(Response response) { + ResponseBody body = response.body(); + try { + return body.string(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + if (body != null) { + body.close(); + } + } + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/interceptor/HttpCodeInterceptor.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/interceptor/HttpCodeInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..e4841eee77d5da5134fccba1721a7580a64f4edb --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/interceptor/HttpCodeInterceptor.java @@ -0,0 +1,45 @@ +package cn.icanci.rec.engine.script.client.http.interceptor; + +import cn.icanci.rec.engine.script.client.RemoteException; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +import org.apache.commons.lang3.StringUtils; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:28 + */ +public class HttpCodeInterceptor implements Interceptor { + private static final String FORMAT = "[%s] %s: %s"; + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = chain.proceed(request); + int code = response.code(); + boolean success = isSuccess(code); + if (success) { + return response; + } + + String errMsg = response.message(); + String body = response.body().string(); + String error = String.format(FORMAT, code, errMsg, body); + throw new RemoteException(code, error); + } + + /** + * 判断 http 调用是否成功 + * + * @param code http 编码 + * @return http 调用是否成功 + */ + private boolean isSuccess(int code) { + String httpCode = String.valueOf(code); + return StringUtils.startsWith(httpCode, "2") || StringUtils.startsWith(httpCode, "3"); + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/interceptor/NetworkInterceptor.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/interceptor/NetworkInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..82d5f5eab9e84f4fd775afdff878c39216809642 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/http/interceptor/NetworkInterceptor.java @@ -0,0 +1,54 @@ +package cn.icanci.rec.engine.script.client.http.interceptor; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:28 + */ +public class NetworkInterceptor implements Interceptor { + /** Client network log */ + private static final Logger LOG = LoggerFactory.getLogger("MERCHANT-CLIENT-LOGGER"); + + @Override + public Response intercept(Chain chain) throws IOException { + long start = System.currentTimeMillis(); + Request request = chain.request(); + + // process request + String url = null; + String method = null; + + try { + url = request.url().toString(); + method = request.method(); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } finally { + LOG.info("[REQUEST] URL={}, METHOD={}", url, method); + } + + // delegate the request to okhttp + Response response = chain.proceed(request); + + // process response + String code = null; + try { + code = String.valueOf(response.code()); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } finally { + long end = System.currentTimeMillis(); + String duration = String.valueOf(end - start); + LOG.info("[RESPONSE] URL={}, RT={}, CODE={}", url, duration, code); + } + return response; + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/FastJsonSerializer.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/FastJsonSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..7471d0310627dcaba90935ae1794ff39bb92f2f9 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/FastJsonSerializer.java @@ -0,0 +1,32 @@ +package cn.icanci.rec.engine.script.client.serializer; + +import cn.icanci.rec.common.utils.FastJsonUtils; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public class FastJsonSerializer implements Serializer { + /** + * 反序列化 + * + * @param json JSON 结构数据 + * @param clazz 待反序列化类结构 + * @return 反序列化实例 + */ + @Override + public T deserialize(String json, Class clazz) { + return FastJsonUtils.fromJSONString(json, clazz); + } + + /** + * 序列化 + * + * @param t 待序列化数据 + * @return JSON 结构数据 + */ + @Override + public String serialize(T t) { + return FastJsonUtils.toJSONString(t); + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/NativeFastJsonSerializer.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/NativeFastJsonSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..9009d4a84779ec075dbcb5f1f633d55a65d401c3 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/NativeFastJsonSerializer.java @@ -0,0 +1,32 @@ +package cn.icanci.rec.engine.script.client.serializer; + +import com.alibaba.fastjson.JSON; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public class NativeFastJsonSerializer implements Serializer { + /** + * 反序列化 + * + * @param json JSON 结构数据 + * @param clazz 待反序列化类结构 + * @return 反序列化实例 + */ + @Override + public T deserialize(String json, Class clazz) { + return JSON.parseObject(json, clazz); + } + + /** + * 序列化 + * + * @param t 待序列化数据 + * @return JSON 结构数据 + */ + @Override + public String serialize(T t) { + return JSON.toJSONString(t); + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/Serializer.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/Serializer.java new file mode 100644 index 0000000000000000000000000000000000000000..ce579b5e93373459b2c6fa918b2134bfda6a3e0c --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/Serializer.java @@ -0,0 +1,27 @@ +package cn.icanci.rec.engine.script.client.serializer; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public interface Serializer { + + /** + * 反序列化 + * + * @param json JSON 结构数据 + * @param clazz 待反序列化类结构 + * @param 待反序列化类型 + * @return 反序列化实例 + */ + T deserialize(String json, Class clazz); + + /** + * 序列化 + * + * @param t 待序列化数据 + * @param 待序列化数据类型 + * @return JSON 结构数据 + */ + String serialize(T t); +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/SerializerEnum.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/SerializerEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..a90ebc7010640222ceafe9b77e6bd477f6f6ff4a --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/SerializerEnum.java @@ -0,0 +1,91 @@ +package cn.icanci.rec.engine.script.client.serializer; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public enum SerializerEnum { + /** + * FASTJSON + */ + FASTJSON("FASTJSON", new FastJsonSerializer()), + /** + * NATIVE-FASTJSON + */ + NATIVE_FASTJSON("NATIVE-FASTJSON", new NativeFastJsonSerializer()), + /** + * STRING + */ + STRING("STRING", new StringSerializer()), + + ; + + /** + * 序列化方式 + */ + private String code; + + /** + * 序列化器 + */ + private Serializer serializer; + + /** + * 私有构造方法 + * + * @param code 序列化方式 + * @param serializer 序列化器 + */ + SerializerEnum(String code, Serializer serializer) { + this.code = code; + this.serializer = serializer; + } + + /** + * 根据序列化方式获取序列化器 + * + * @param code 序列化方式 + * @return 序列化器 + */ + public static Serializer getByCode(String code) { + for (SerializerEnum e : SerializerEnum.values()) { + if (e.getCode().equals(code)) { + return e.getSerializer(); + } + } + throw new IllegalArgumentException("The serializer code [" + code + "] is not supported."); + } + + /** + * 根据序列化方式获取序列化器 + * + * @param code 序列化方式 + * @return 序列化器 + */ + public static SerializerEnum toEnum(String code) { + for (SerializerEnum e : SerializerEnum.values()) { + if (e.getCode().equals(code)) { + return e; + } + } + throw new IllegalArgumentException("The serializer code [" + code + "] is not supported."); + } + + /** + * 获取序列化方式 + * + * @return 序列化方式 + */ + public String getCode() { + return code; + } + + /** + * 获取序列化器 + * + * @return 序列化器 + */ + public Serializer getSerializer() { + return serializer; + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/StringSerializer.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/StringSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..0bd76169c3aae74bd19ca552864add572abb5ae9 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/client/serializer/StringSerializer.java @@ -0,0 +1,30 @@ +package cn.icanci.rec.engine.script.client.serializer; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/14 22:14 + */ +public class StringSerializer implements Serializer { + /** + * 反序列化 + * + * @param json JSON 结构数据 + * @param clazz 待反序列化类结构 + * @return 反序列化实例 + */ + @Override + public T deserialize(String json, Class clazz) { + return (T) json; + } + + /** + * 序列化 + * + * @param t 待序列化数据 + * @return JSON 结构数据 + */ + @Override + public String serialize(T t) { + return (String) t; + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/impl/RecScriptEngineImpl.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/impl/RecScriptEngineImpl.java index 89c9933ce2b86bb341c477a1d9b29cf748c35e8b..d7ac6591fd4285f9c789763c77f0c5f05bb2b93e 100644 --- a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/impl/RecScriptEngineImpl.java +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/impl/RecScriptEngineImpl.java @@ -1,17 +1,34 @@ package cn.icanci.rec.engine.script.impl; +import cn.icanci.rec.common.enums.HttpRequestTypeEnum; import cn.icanci.rec.common.enums.ScriptTypeEnum; +import cn.icanci.rec.common.utils.FastJsonUtils; import cn.icanci.rec.engine.script.RecScriptEngine; +import cn.icanci.rec.engine.script.client.Client; +import cn.icanci.rec.engine.script.client.http.HttpMethod; +import cn.icanci.rec.engine.script.client.http.OkHttpClientImpl; +import cn.icanci.rec.engine.script.client.serializer.SerializerEnum; import cn.icanci.rec.engine.script.context.RecScriptEngineContext; import cn.icanci.rec.engine.script.factory.ScriptEngineFactory; +import cn.icanci.rec.engine.script.wrapper.HttpResponseWrapper; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.script.*; +import com.google.common.collect.Maps; + /** * @author icanci * @since 1.0 Created in 2022/11/12 22:46 */ public class RecScriptEngineImpl implements RecScriptEngine { + /** http实例 */ + private static final Client CLIENT = OkHttpClientImpl.getInstance(); + /** DEFAULT_APPLICATION_JSON_VALUE */ + public static final String DEFAULT_APPLICATION_JSON_VALUE = "application/json"; /** * 执行脚本 @@ -111,4 +128,42 @@ public class RecScriptEngineImpl implements RecScriptEngine { return context; } + @Override + public HttpResponseWrapper httpEval(HttpRequestTypeEnum requestType, String reqUrl, String reqParam, int timeout) { + + HttpMethod httpMethod = null; + + switch (requestType) { + case GET: + httpMethod = HttpMethod.GET; + break; + case POST: + httpMethod = HttpMethod.POST; + break; + default: + // no op + } + + if (httpMethod == null) { + throw new NullPointerException("HttpMethod is Null !"); + } + + if (timeout <= 0) { + throw new IllegalArgumentException("Http Request Timeout is Less than 0!"); + } + + HashMap headers = Maps.newHashMap(); + Map reqMap = FastJsonUtils.fromJSONString(reqParam, Map.class); + Client.RpcRequest rpcRequest = new Client.RpcRequest(reqMap, DEFAULT_APPLICATION_JSON_VALUE, headers, reqUrl, httpMethod.name(), false, timeout, TimeUnit.SECONDS, 0, + SerializerEnum.FASTJSON, SerializerEnum.FASTJSON); + + HttpResponseWrapper wrapper = new HttpResponseWrapper(); + try { + wrapper.setResponse(CLIENT.call(rpcRequest, String.class)); + } catch (Throwable e) { + wrapper.setException(e); + } + return wrapper; + } + } diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/wrapper/HttpResponseWrapper.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/wrapper/HttpResponseWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5297c4c101ba22a3b91d413a2fd9b2edab6e1b12 --- /dev/null +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/wrapper/HttpResponseWrapper.java @@ -0,0 +1,77 @@ +package cn.icanci.rec.engine.script.wrapper; + +import cn.icanci.rec.common.utils.FastJsonUtils; + +import java.util.Map; +import java.util.StringJoiner; + +import com.google.common.collect.Maps; + +/** + * Http请求结果Wrapper + * + * @author icanci + * @since 1.0 Created in 2022/11/14 22:36 + */ +public class HttpResponseWrapper { + /** + * 执行结果 + */ + private String response; + /** + * 执行异常 + */ + private Throwable exception; + + /** + * 判断返回是否是JSON + * + * @return 判断返回是否是JSON + */ + public boolean isJson() { + return FastJsonUtils.isJson(response); + } + + /** + * 获取返回结果的Map + * + * @return 返回Map + */ + public Map getResponseForMap() { + if (response == null) { + return Maps.newHashMap(); + } + return FastJsonUtils.fromJSONString(response, Map.class); + } + + /** + * 是否执行成功 + * + * @return 返回是否执行成功 + */ + public boolean isSuccess() { + return response != null || exception == null; + } + + public String getResponse() { + return response; + } + + public void setResponse(String response) { + this.response = response; + } + + public Throwable getException() { + return exception; + } + + public void setException(Throwable exception) { + this.exception = exception; + } + + @Override + public String toString() { + return new StringJoiner(",").add("response=" + response).add("exception=" + exception).toString(); + } + +} diff --git a/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java b/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java index 1f711ede90f8312ad9b5bfb17e9a8d9139a1e3fd..bc303ce337239172e03e58415b10abec889ef36d 100644 --- a/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java +++ b/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java @@ -1,9 +1,14 @@ package cn.icanci.rec.engine.script.test; +import cn.icanci.rec.common.enums.HttpRequestTypeEnum; import cn.icanci.rec.common.enums.ScriptTypeEnum; +import cn.icanci.rec.common.utils.FastJsonUtils; import cn.icanci.rec.engine.script.RecScriptEngine; import cn.icanci.rec.engine.script.RecScriptEngineManager; import cn.icanci.rec.engine.script.context.RecScriptEngineContext; +import cn.icanci.rec.engine.script.wrapper.HttpResponseWrapper; + +import java.io.Serializable; import org.junit.Test; @@ -21,4 +26,72 @@ public class RecScriptEngineManagerTest { System.out.println(retVal); System.out.println(context); } + + @Test + public void testRecScriptEngineManagerHttp() { + RecScriptEngine recScriptEngine = RecScriptEngineManager.getRecScriptEngine(); + String reqUrl = "http://localhost:9110/dijiang/sys/config/query"; + ConfigRequest request = new ConfigRequest(); + request.setUk("xxx"); + request.setEnv("test"); + request.setFileName("hello"); + + HttpResponseWrapper eval = recScriptEngine.httpEval(HttpRequestTypeEnum.POST, reqUrl, FastJsonUtils.toJSONString(request), 3); + if (eval.isSuccess()) { + System.out.println(eval.isJson()); + System.out.println(eval.getResponseForMap()); + } + System.out.println(eval); + } + + @Test + public void fastjsonIsJson() { +// System.out.println(FastJsonUtils.isJson("「9999")); + System.out.println(FastJsonUtils.isJson("TRUE")); + System.out.println(FastJsonUtils.isJson("false ")); +// System.out.println(FastJsonUtils.isJson("11.1")); + System.out.println(Boolean.parseBoolean("true")); + System.out.println(Boolean.parseBoolean("false")); + } + + private static class ConfigRequest implements Serializable { + + private static final long serialVersionUID = 2380811183737977291L; + /** + * 项目唯一id + */ + private String uk; + /** + * 环境 + */ + private String env; + /** + * 配置文件名字 + */ + private String fileName; + + public String getUk() { + return uk; + } + + public void setUk(String uk) { + this.uk = uk; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + } }