GITZYY vor 1 Jahr
Ursprung
Commit
148649dcbe
32 geänderte Dateien mit 1248 neuen und 1 gelöschten Zeilen
  1. 14 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/Api.java
  2. 16 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiConfig.java
  3. 31 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiContext.java
  4. 45 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiFactory.java
  5. 10 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiGateway.java
  6. 39 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/FunctionObject.java
  7. 25 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/FunctionParam.java
  8. 132 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/HttpApi.java
  9. 50 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/HttpApiConfig.java
  10. 29 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/KeyValueObject.java
  11. 64 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ValueObject.java
  12. 32 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/common/ApiPayloadTypeEnum.java
  13. 31 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/common/ApiTypeEnums.java
  14. 33 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/common/ValueObjectTypeEnum.java
  15. 48 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/func/EncryptionFunction.java
  16. 66 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/func/ValueObjectFunctionManager.java
  17. 1 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/package-info.java
  18. 91 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/payload/ApiJsonPayloadResolver.java
  19. 17 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/payload/ApiPayloadResolver.java
  20. 56 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/payload/ApiPayloadResolverManage.java
  21. 26 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/BasicTypeValueObjectResolver.java
  22. 36 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/SpelValueObjectResolver.java
  23. 19 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/ValueObjectResolver.java
  24. 75 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/ValueObjectResolverManager.java
  25. 0 1
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/utils/GsonUtil.java
  26. 4 0
      egress-gateway-service-infrastructure/pom.xml
  27. 40 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/ApiGateWayImpl/ApiGatewayImpl.java
  28. 40 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/HttpClient.java
  29. 5 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/config/DiamondConfig.java
  30. 108 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/utils/HessianUtils.java
  31. 18 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/utils/HttpConfiguration.java
  32. 47 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/entity/BaseDo.java

+ 14 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/Api.java

@@ -0,0 +1,14 @@
+package com.hrsk.cloud.eg.domain.api;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-26 17:58
+ * @description: API基类
+ **/
+public interface Api {
+    /**
+     * 获取类型
+     * @return 类型
+     */
+    String getType();
+}

+ 16 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiConfig.java

@@ -0,0 +1,16 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import lombok.Data;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 15:59
+ * @description: API配置
+ **/
+@Data
+public class ApiConfig {
+    /**
+     * 类型
+     */
+    private String type;
+}

+ 31 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiContext.java

@@ -0,0 +1,31 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import lombok.Getter;
+import lombok.experimental.Accessors;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 11:48
+ * @description: API上下文
+ **/
+@Getter
+@Accessors(chain = true)
+public class ApiContext {
+    /**
+     * 入参
+     */
+    private final Object input;
+    /**
+     * spel context
+     */
+    private final StandardEvaluationContext spelContext = new StandardEvaluationContext();
+    /**
+     * 构造函数
+     * @param input 入参
+     */
+    public ApiContext(Object input) {
+        this.input = input;
+        spelContext.setVariable("param",input);
+    }
+}

+ 45 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiFactory.java

@@ -0,0 +1,45 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.alibaba.cola.domain.DomainFactory;
+import com.hrsk.cloud.op.eg.domain.api.common.ApiTypeEnums;
+import com.hrsk.cloud.op.eg.domain.common.BizPreconditions;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-26 17:57
+ * @description: API领域对象工厂
+ **/
+@Component
+@Slf4j
+public class ApiFactory {
+    /**
+     * 创建API对象
+     * @param apiConfig api配置
+     * @param input 入参
+     * @return API
+     */
+    public Api createApi(ApiConfig apiConfig,Object input){
+        BizPreconditions.checkArgument(apiConfig!=null,"API配置不能为空!");
+        BizPreconditions.checkArgument(StringUtils.isNotBlank(apiConfig.getType()),"API配置类型不能为空!");
+        if(StringUtils.equals(ApiTypeEnums.HTTP.getType(),apiConfig.getType())){
+            return createHttpApi((HttpApiConfig)apiConfig,input);
+        }else {
+            log.error("不支持的API类型:{}!",apiConfig.getType());
+        }
+        return null;
+    }
+
+    /**
+     * 创建HTTP API
+     * @param httpApiConfig http api config
+     * @return  HTTP API
+     */
+    private Api createHttpApi(HttpApiConfig httpApiConfig,Object input){
+        HttpApi httpApi = DomainFactory.create(HttpApi.class);
+        httpApi.load(httpApiConfig,input);
+        return httpApi;
+    }
+}

+ 10 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiGateway.java

@@ -0,0 +1,10 @@
+package com.hrsk.cloud.eg.domain.api;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 18:14
+ * @description: API防腐层
+ **/
+public interface ApiGateway {
+    Object request();
+}

+ 39 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/FunctionObject.java

@@ -0,0 +1,39 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.google.common.collect.Lists;
+import com.hrsk.cloud.op.eg.domain.api.func.ValueObjectFunctionManager;
+import com.hrsk.cloud.op.eg.domain.api.resolver.vo.ValueObjectResolverManager;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-27 11:05
+ * @description: 函数对象,值对象
+ **/
+@ToString
+@Data
+public class FunctionObject implements Serializable {
+    /**
+     * 编码
+     */
+    private String code;
+    /**
+     * 参数
+     */
+    private List<ValueObject> args = Lists.newArrayList();
+
+    /**
+     * 执行
+     */
+    public Object apply(Object value,ApiContext apiContext){
+        FunctionParam functionParam = new FunctionParam().setInput(value);
+        for(ValueObject arg : args){
+            functionParam.getExtArg().add(ValueObjectResolverManager.getInstance().resolve(arg,apiContext));
+        }
+        return ValueObjectFunctionManager.getInstance().apply(code,functionParam);
+    }
+}

+ 25 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/FunctionParam.java

@@ -0,0 +1,25 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.google.common.collect.Lists;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-30 11:40
+ * @description: 函数参数
+ **/
+@Data
+@Accessors(chain = true)
+public class FunctionParam {
+    /**
+     * 入参
+     */
+    private Object input;
+    /**
+     * 额外参数
+     */
+    private List<Object> extArg = Lists.newArrayList();
+}

+ 132 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/HttpApi.java

@@ -0,0 +1,132 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.alibaba.cola.domain.Entity;
+import com.alibaba.cola.exception.BizException;
+import com.hrsk.cloud.op.eg.domain.api.common.ApiPayloadTypeEnum;
+import com.hrsk.cloud.op.eg.domain.api.resolver.payload.ApiPayloadResolverManage;
+import lombok.Getter;
+import lombok.ToString;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-26 17:59
+ * @description: HTTP API
+ **/
+@ToString
+@Entity
+public class HttpApi implements Api {
+    /**
+     * url分隔符
+     */
+    private static final String URL_SEPARATOR = "/";
+
+    /**
+     * search分隔符
+     */
+    private static final String URL_SEARCH_SEPARATOR = "&";
+
+    /**
+     * 等于号
+     */
+    private static final String _EQUAL = "=";
+    /**
+     * search标记符
+     */
+    private static final String URL_SEARCH = "?";
+
+    @Override
+    public String getType() {
+        return "http";
+    }
+
+    /**
+     * url地址
+     */
+    @Getter
+    private String url;
+    /**
+     * 请求方法
+     */
+    @Getter
+    private String method;
+    /**
+     * http api配置
+     */
+    private HttpApiConfig httpApiConfig;
+    /**
+     * header数据
+     */
+    @Getter
+    private Map<String,Object> header = new HashMap<>();
+    /**
+     * 请求payload数据
+     */
+    @Getter
+    private Object payload;
+
+
+    /**
+     * 加载
+     * @param httpApiConfig http api 配置
+     */
+    public void load(HttpApiConfig httpApiConfig,Object input){
+        this.httpApiConfig = httpApiConfig;
+        ApiContext context = new ApiContext(input);
+        this.method = httpApiConfig.getMethod();
+        loadCompleteUrl(context);
+        loadHeader(context);
+        loadBody(context);
+    }
+
+    /**
+     * 加载path,包含path和search
+     * @param context 上下文
+     */
+    private void loadCompleteUrl(ApiContext context){
+        StringBuilder urlSb = new StringBuilder(httpApiConfig.getUrl());
+        for(ValueObject valueObject : httpApiConfig.getPath()){
+            urlSb.append(URL_SEPARATOR).append(valueObject.compile(context).getRealValue());
+        }
+        if(!CollectionUtils.isEmpty(httpApiConfig.getSearch())){
+            StringBuilder searchSb = new StringBuilder();
+            for(KeyValueObject keyValueObject : httpApiConfig.getSearch()){
+                searchSb.append(URL_SEARCH_SEPARATOR).append(keyValueObject.getKey()).append(_EQUAL).append(keyValueObject.compile(context).getRealValue());
+            }
+            urlSb.append(URL_SEARCH).append(searchSb.toString().replaceFirst(URL_SEARCH_SEPARATOR,""));
+        }
+        url = urlSb.toString();
+    }
+
+    /**
+     * 加载header
+     * @param context 上下文
+     */
+    private void loadHeader(ApiContext context){
+        for(KeyValueObject keyValueObject : httpApiConfig.getHeader()){
+            this.header.put(keyValueObject.getKey(),keyValueObject.compile(context).getRealValue());
+        }
+    }
+
+
+
+
+    /**
+     * 加载请求体
+     * @param context 上下文
+     */
+    private void loadBody(ApiContext context){
+        if(StringUtils.equals(httpApiConfig.getContentType(), ApiPayloadTypeEnum.APPLICATION_JSON.getCode())){
+            payload = Objects.toString(ApiPayloadResolverManage.getInstance().resolve(httpApiConfig.getContentType(),httpApiConfig.getContent(),context),"");
+        }else{
+            throw new BizException("不支持的请求体类型!");
+        }
+    }
+
+
+}

+ 50 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/HttpApiConfig.java

@@ -0,0 +1,50 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.google.common.collect.Lists;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 15:47
+ * @description: HTTP API配置
+ **/
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Accessors(chain = true)
+public class HttpApiConfig extends ApiConfig implements Serializable {
+    /**
+     * 请求方法
+     */
+    private String method;
+    /**
+     * url地址 http://baidu.com /a/b/c
+     */
+    private String url;
+    /**
+     * header
+     */
+    private List<KeyValueObject> header = Lists.newArrayList();
+    /**
+     * path  a/b/b
+     */
+    private List<ValueObject> path = Lists.newArrayList();
+    /**
+     * search
+     */
+    private List<KeyValueObject> search = Lists.newArrayList();
+    /**
+     * 内容类型
+     */
+    private String contentType;
+    /**
+     * body
+     */
+    private String content;
+
+
+}

+ 29 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/KeyValueObject.java

@@ -0,0 +1,29 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.hrsk.cloud.op.eg.domain.common.BizPreconditions;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 16:14
+ * @description: kv对象
+ **/
+@ToString
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class KeyValueObject extends ValueObject {
+    /**
+     * key
+     */
+    private String key;
+    /**
+     * 校验必要参数
+     */
+    void checkParam(){
+        super.checkParam();
+        BizPreconditions.checkArgument(StringUtils.isEmpty(key),"配置中值对象的key不能为空!");
+    }
+}

+ 64 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ValueObject.java

@@ -0,0 +1,64 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.hrsk.cloud.op.eg.domain.api.resolver.vo.ValueObjectResolverManager;
+import com.hrsk.cloud.op.eg.domain.common.BizPreconditions;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-27 10:21
+ * @description: 值对象
+ **/
+
+@Getter
+@ToString
+public class ValueObject implements Serializable {
+    /**
+     * 类型
+     */
+    @Setter
+    private String type;
+    /**
+     * 值
+     */
+    @Setter
+    private String value;
+    /**
+     * 真实值
+     */
+    private Object realValue;
+    /**
+     * 函数链
+     */
+    @Setter
+    private List<FunctionObject> functions = new ArrayList<>();
+
+    /**
+     * 校验必要参数
+     */
+    void checkParam(){
+        BizPreconditions.checkArgument(StringUtils.isEmpty(type),"配置中值对象的type不能为空!");
+        BizPreconditions.checkArgument(StringUtils.isEmpty(value),"配置中值对象的value不能为空!");
+    }
+
+
+    public ValueObject compile(ApiContext apiContext){
+        this.realValue = ValueObjectResolverManager.getInstance().resolve(this,apiContext);
+        if(CollectionUtils.isEmpty(functions)){
+            return this;
+        }
+        for(FunctionObject function : functions){
+            this.realValue = function.apply(realValue,apiContext);
+        }
+        return this;
+    }
+
+}

+ 32 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/common/ApiPayloadTypeEnum.java

@@ -0,0 +1,32 @@
+package com.hrsk.cloud.eg.domain.api.common;
+
+import lombok.Getter;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 17:38
+ * @description: api payload 类型枚举
+ **/
+@Getter
+public enum ApiPayloadTypeEnum {
+    APPLICATION_JSON("application/json");
+
+    /**
+     * 编码
+     * -- GETTER --
+     *  获取编码
+     *
+     * @return 编码
+
+     */
+    private String code;
+
+    /**
+     * 构造函数
+     * @param code 编码
+     */
+    ApiPayloadTypeEnum(String code) {
+        this.code = code;
+    }
+
+}

+ 31 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/common/ApiTypeEnums.java

@@ -0,0 +1,31 @@
+package com.hrsk.cloud.eg.domain.api.common;
+
+import lombok.Getter;
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-27 09:46
+ * @description: API类型枚举
+ **/
+@Getter
+public enum ApiTypeEnums {
+
+    HTTP("http","http类型");
+    /**
+     * 类型
+     */
+    private final String type;
+    /**
+     * 描述
+     */
+    private final String description;
+
+    /**
+     * 构造函数
+     * @param type 类型
+     * @param description 描述
+     */
+    ApiTypeEnums(String type, String description) {
+        this.type = type;
+        this.description = description;
+    }
+}

+ 33 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/common/ValueObjectTypeEnum.java

@@ -0,0 +1,33 @@
+package com.hrsk.cloud.eg.domain.api.common;
+
+import lombok.Getter;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 15:06
+ * @description: 值对象类型枚举
+ **/
+public enum ValueObjectTypeEnum {
+    SPEL("spel","spel类型"),
+    BASIC("basic","");
+    /**
+     * 类型
+     */
+    @Getter
+    private String type;
+    /**
+     * 描述
+     */
+    @Getter
+    private String memo;
+
+    /**
+     * 构造函数
+     * @param type 类型
+     * @param memo 描述
+     */
+    ValueObjectTypeEnum(String type, String memo) {
+        this.type = type;
+        this.memo = memo;
+    }
+}

+ 48 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/func/EncryptionFunction.java

@@ -0,0 +1,48 @@
+package com.hrsk.cloud.eg.domain.api.func;
+
+import com.hrsk.cloud.op.eg.domain.api.FunctionParam;
+
+import java.security.MessageDigest;
+import java.util.Objects;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 15:58
+ * @description: 加解密函数
+ **/
+public class EncryptionFunction {
+    /**
+     * MD5函数
+     * @param functionParam 入参
+     * @return MD字符串
+     */
+    public static String md5(FunctionParam functionParam){
+        String input = Objects.toString(functionParam.getInput(),null);
+        //用于加密的字符
+        char md5String[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+                'A', 'B', 'C', 'D', 'E', 'F' };
+        try {
+            //使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte数组中
+            byte[] btInput = input.getBytes();
+            //信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
+            MessageDigest mdInst = MessageDigest.getInstance("MD5");
+            //MessageDigest对象通过使用 update方法处理数据, 使用指定的byte数组更新摘要
+            mdInst.update(btInput);
+            // 摘要更新之后,通过调用digest()执行哈希计算,获得密文
+            byte[] md = mdInst.digest();
+            // 把密文转换成十六进制的字符串形式
+            int j = md.length;
+            char str[] = new char[j * 2];
+            int k = 0;
+            for (int i = 0; i < j; i++) {   //  i = 0
+                byte byte0 = md[i];  //95
+                str[k++] = md5String[byte0 >>> 4 & 0xf];    //    5
+                str[k++] = md5String[byte0 & 0xf];   //   F
+            }
+            //返回经过加密后的字符串
+            return new String(str);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}

+ 66 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/func/ValueObjectFunctionManager.java

@@ -0,0 +1,66 @@
+package com.hrsk.cloud.eg.domain.api.func;
+
+import com.alibaba.cola.exception.BizException;
+import com.hrsk.cloud.op.eg.domain.api.FunctionParam;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 09:48
+ * @description: 值对象函数管理器
+ **/
+@Slf4j
+public class ValueObjectFunctionManager {
+    /**
+     * 函数
+     */
+    private static final Map<String, Function<FunctionParam, Object>> FUNCTIONS = new HashMap<>();
+    /**
+     * 实例
+     */
+    private static final ValueObjectFunctionManager INSTANCE = new ValueObjectFunctionManager();
+
+    static {
+        regist();
+    }
+
+    /**
+     * 构造函数
+     */
+    private ValueObjectFunctionManager(){}
+
+    /**
+     * 获取实例
+     * @return 实例
+     */
+    public static ValueObjectFunctionManager getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * 注册函数
+     */
+    private static void regist(){
+        log.info("开始注册值对象函数!");
+        FUNCTIONS.put("md5", EncryptionFunction::md5);
+        log.info("md5函数已注册!");
+    }
+
+    /**
+     * 执行函数
+     * @param code 函数编码
+     * @param functionParam 函数参数
+     * @return 函数执行结果
+     */
+    public Object apply(String code,FunctionParam functionParam){
+        Function<FunctionParam,Object> function = FUNCTIONS.get(code);
+        if(function == null){
+            throw new BizException("不支持的函数编码!");
+        }
+        return function.apply(functionParam);
+    }
+}

+ 1 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/package-info.java

@@ -0,0 +1 @@
+package com.hrsk.cloud.eg.domain.api;

+ 91 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/payload/ApiJsonPayloadResolver.java

@@ -0,0 +1,91 @@
+package com.hrsk.cloud.eg.domain.api.resolver.payload;
+
+import com.alibaba.cola.exception.BizException;
+import com.google.gson.*;
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+import com.hrsk.cloud.op.eg.domain.api.ValueObject;
+import com.hrsk.cloud.op.eg.domain.common.GsonUtils;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 15:38
+ * @description: json类型payload
+ **/
+public class ApiJsonPayloadResolver implements ApiPayloadResolver {
+    /**
+     * JSON配置最大深度
+     */
+    private static final Integer MAX_DEEP = 10;
+    /**
+     * 配置前缀标记
+     */
+    private static final String CONFIG_PREFIX_SIGN = "#{";
+
+    /**
+     * 配置后缀标记
+     */
+    private static final String CONFIG_END_SIGN = "}";
+
+    @Override
+    public Object resolve(String jsonTemplate, ApiContext context) {
+        JsonElement jsonElement = GsonUtils.fromJson(jsonTemplate, JsonElement.class);
+        traverseJson(jsonElement,jsonElement,null,context,0);
+        return jsonElement.toString();
+    }
+
+    /**
+     * 遍历json
+     * @param jsonElement json元素
+     * @param context 上下文
+     * @param deep 深度
+     */
+    public void traverseJson(JsonElement jsonElement, JsonElement currentElement,String currentKey,ApiContext context,Integer deep) {
+        deep++;
+        if(deep >= MAX_DEEP){
+            throw new BizException(String.format("请求payload的json配置深度达到允许的最大深度[%s]!",MAX_DEEP));
+        }
+        if (jsonElement.isJsonObject()) {
+            JsonObject jsonObject = jsonElement.getAsJsonObject();
+            for (String key : jsonObject.keySet()) {
+                traverseJson(jsonObject.get(key),jsonObject,key,context,deep);
+            }
+        } else if (jsonElement.isJsonArray()) {
+            JsonArray jsonArray = jsonElement.getAsJsonArray();
+            for (JsonElement elem : jsonArray) {
+                traverseJson(elem,currentElement,null,context,deep);
+            }
+        } else {
+            if(jsonElement.isJsonPrimitive() && jsonElement.getAsJsonPrimitive().isString()){
+                String value = jsonElement.getAsString();
+                if(value.startsWith(CONFIG_PREFIX_SIGN)&&value.endsWith(CONFIG_END_SIGN)){
+                    JsonPrimitive newElement = parseSpelConfigToRealValue(jsonElement,context);
+                    if(StringUtils.isNotBlank(currentKey)){
+                        currentElement.getAsJsonObject().add(currentKey,newElement);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 将spel表达式转换成真实值
+     * @param jsonElement json元素
+     */
+    private JsonPrimitive parseSpelConfigToRealValue(JsonElement jsonElement, ApiContext context){
+        String value = jsonElement.getAsString();
+        value = StringUtils.replace(value,CONFIG_PREFIX_SIGN,"{",3);
+        ValueObject valueObject = new Gson().fromJson(value,ValueObject.class);
+        Object realValue = valueObject.compile(context).getRealValue();
+        if(realValue instanceof Number){
+            return new JsonPrimitive((Number)realValue);
+        }else if(realValue instanceof String){
+            return new JsonPrimitive((String)realValue);
+        }else if(realValue instanceof Boolean){
+            return new JsonPrimitive((Boolean)realValue);
+        }else if(realValue instanceof Character){
+            return new JsonPrimitive((Character)realValue);
+        }
+        return null;
+    }
+}

+ 17 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/payload/ApiPayloadResolver.java

@@ -0,0 +1,17 @@
+package com.hrsk.cloud.eg.domain.api.resolver.payload;
+
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 15:37
+ * @description: http api payload
+ **/
+public interface ApiPayloadResolver {
+    /**
+     * 获取payload
+     * @param template payload模版
+     * @param context 上下文
+     */
+    Object resolve(String template,ApiContext context);
+}

+ 56 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/payload/ApiPayloadResolverManage.java

@@ -0,0 +1,56 @@
+package com.hrsk.cloud.eg.domain.api.resolver.payload;
+
+import com.google.common.collect.Maps;
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+import com.hrsk.cloud.op.eg.domain.api.common.ApiPayloadTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 17:38
+ * @description: api payload 管理器
+ **/
+@Slf4j
+public class ApiPayloadResolverManage {
+    /**
+     * PAYLOAD MAP
+     */
+    private static final Map<String, ApiPayloadResolver> RESOLVER_MAP = Maps.newHashMap();
+    /**
+     * INSTANCE
+     */
+    private static final ApiPayloadResolverManage INSTANCE = new ApiPayloadResolverManage();
+
+    static {
+        regist();
+    }
+
+    private ApiPayloadResolverManage(){}
+
+    /**
+     * 获取实例
+     * @return 实例
+     */
+    public static ApiPayloadResolverManage getInstance(){
+        return INSTANCE;
+    }
+
+    /**
+     * 解析
+     * @param code 编码
+     * @param apiContext 上下文
+     * @return 解析结果
+     */
+    public Object resolve(String code, String template, ApiContext apiContext){
+        return RESOLVER_MAP.get(code).resolve(template,apiContext);
+    }
+    /**
+     * 注册
+     */
+    private static void regist(){
+        log.info("开始注册Payload解析器!");
+        RESOLVER_MAP.put(ApiPayloadTypeEnum.APPLICATION_JSON.getCode(),new ApiJsonPayloadResolver());
+    }
+}

+ 26 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/BasicTypeValueObjectResolver.java

@@ -0,0 +1,26 @@
+package com.hrsk.cloud.eg.domain.api.resolver.vo;
+
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+import com.hrsk.cloud.op.eg.domain.api.ValueObject;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 14:35
+ * @description: 基础类型值对象解析器
+ **/
+public class BasicTypeValueObjectResolver implements ValueObjectResolver {
+    /**
+     * 基本类型
+     */
+    public static final String[] BASIC_TYPES = new String[]{"text","string","double","float","boolean"};
+    /**
+     * 解析
+     * @param valueObject 待解析对象
+     * @return 解析后对象
+     */
+    @Override
+    public Object resolve(ValueObject valueObject, ApiContext context) {
+        return valueObject.getValue();
+    }
+
+}

+ 36 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/SpelValueObjectResolver.java

@@ -0,0 +1,36 @@
+package com.hrsk.cloud.eg.domain.api.resolver.vo;
+
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+import com.hrsk.cloud.op.eg.domain.api.ValueObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 14:38
+ * @description: Spel值对象解析器
+ **/
+@Slf4j
+public class SpelValueObjectResolver  implements ValueObjectResolver{
+    /**
+     * spel parser
+     */
+    private final ExpressionParser parser = new SpelExpressionParser();
+
+    /**
+     * 解析
+     * @param valueObject 解析对象
+     * @param context 上下文
+     * @return 解析结果
+     */
+    @Override
+    public Object resolve(ValueObject valueObject, ApiContext context) {
+        try{
+            return parser.parseExpression(valueObject.getValue()).getValue(context.getSpelContext());
+        }catch (Exception ex){
+            log.error("属性配置错误!",ex);
+            return null;
+        }
+    }
+}

+ 19 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/ValueObjectResolver.java

@@ -0,0 +1,19 @@
+package com.hrsk.cloud.eg.domain.api.resolver.vo;
+
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+import com.hrsk.cloud.op.eg.domain.api.ValueObject;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-07-31 14:32
+ * @description: 值对象解析器
+ **/
+public interface ValueObjectResolver {
+    /**
+     * 解析
+     * @param valueObject 解析对象
+     * @param context 上下文
+     * @return 解析结果
+     */
+    Object resolve(ValueObject valueObject, ApiContext context);
+}

+ 75 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/resolver/vo/ValueObjectResolverManager.java

@@ -0,0 +1,75 @@
+package com.hrsk.cloud.eg.domain.api.resolver.vo;
+
+import com.alibaba.cola.exception.BizException;
+import com.google.common.collect.Maps;
+import com.hrsk.cloud.op.eg.domain.api.ApiContext;
+import com.hrsk.cloud.op.eg.domain.api.ValueObject;
+import com.hrsk.cloud.op.eg.domain.api.common.ValueObjectTypeEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Map;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 09:53
+ * @description: 值对象处理器管理器
+ **/
+@Slf4j
+public class ValueObjectResolverManager {
+    /**
+     * 解析器映射
+     */
+    private static final Map<String,ValueObjectResolver> RESOLVERS = Maps.newHashMap();
+    /**
+     * INSTANCE
+     */
+    private static final ValueObjectResolverManager INSTANCE = new ValueObjectResolverManager();
+
+    static {
+        regist();
+    }
+
+    /**
+     * 构造函数
+     */
+    private ValueObjectResolverManager(){};
+
+    /**
+     * 获取实例
+     * @return 实例
+     */
+    public static ValueObjectResolverManager getInstance(){
+        return INSTANCE;
+    }
+
+    /**
+     * 解析
+     * @param valueObject 值对象
+     * @param context 上下文
+     * @return 解析结果
+     */
+    public Object resolve(ValueObject valueObject, ApiContext context){
+        String type = valueObject.getType();
+        String key = valueObject.getType();
+        if(StringUtils.equalsAnyIgnoreCase(type, BasicTypeValueObjectResolver.BASIC_TYPES)){
+            key = ValueObjectTypeEnum.BASIC.getType();
+        }
+        if(StringUtils.isBlank(key)){
+            throw new BizException("目前不支持此类型的解析!");
+        }
+        return RESOLVERS.get(key).resolve(valueObject,context);
+    }
+
+
+    /**
+     * 注册
+     */
+    private static void regist() {
+        log.info("开始注册ValueObject解析器......");
+        RESOLVERS.put(ValueObjectTypeEnum.SPEL.getType(),new SpelValueObjectResolver());
+        RESOLVERS.put(ValueObjectTypeEnum.BASIC.getType(),new BasicTypeValueObjectResolver());
+        log.info("结束注册ValueObject解析器,加载内容:{},{}.",ValueObjectTypeEnum.SPEL.getType(),ValueObjectTypeEnum.BASIC.getType());
+    }
+
+}

+ 0 - 1
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/utils/GsonUtil.java

@@ -6,7 +6,6 @@ import com.hrsk.pangu.tool.exception.BizException;
 import com.sun.org.slf4j.internal.Logger;
 import com.sun.org.slf4j.internal.LoggerFactory;
 import org.apache.commons.lang3.StringUtils;
-
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Date;

+ 4 - 0
egress-gateway-service-infrastructure/pom.xml

@@ -24,6 +24,10 @@
             <groupId>com.hrsk.cloud</groupId>
             <artifactId>egress-gateway-service-client</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>

+ 40 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/ApiGateWayImpl/ApiGatewayImpl.java

@@ -0,0 +1,40 @@
+package com.hrsk.cloud.eg.infrastructure.ApiGateWayImpl;
+
+import com.hrsk.cloud.eg.domain.api.ApiGateway;
+import com.hrsk.cloud.eg.infrastructure.clinent.HttpClient;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 18:15
+ * @description: API防腐层
+ **/
+@Slf4j
+@Component
+public class ApiGatewayImpl implements ApiGateway {
+
+
+    @Resource
+    private HttpClient httpClient;
+
+    @Override
+    public Object request() {
+//        UserInfoDto userInfoDto = new UserInfoDto();
+//        userInfoDto.setUserId(12345L);
+//        userInfoDto.setUserMobile("17766668888");
+//        EgApiEndpointDo egApiEndpointDo = egApiEndpointMapper.selectById(1819284080014041090L);
+//        HttpApiConfig httpApiConfig = (HttpApiConfig)HessianUtils.deserialize(egApiEndpointDo.getEndpointConfig());
+//        Api api = apiFactory.createApi(httpApiConfig,userInfoDto);
+//        if(StringUtils.equals(ApiTypeEnums.HTTP.getType(),api.getType())){
+//            return httpClient.request((HttpApi) api);
+//        }else{
+//            log.error("不支持的请求配置类型!");
+//            throw new BizException("不支持的请求配置类型!");
+//        }
+        return null;
+    }
+}

+ 40 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/HttpClient.java

@@ -0,0 +1,40 @@
+package com.hrsk.cloud.eg.infrastructure.clinent;
+
+import com.hrsk.cloud.eg.domain.api.HttpApi;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Objects;
+import org.springframework.web.client.RestTemplate;
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-02 17:08
+ * @description: http请求客户端
+ **/
+@Slf4j
+@Component
+public class HttpClient {
+    @Resource
+    private RestTemplate restTemplate;
+    /**
+     * 请求
+     * @param httpApi http api对象
+     * @return 响应数据
+     */
+    public Object request(HttpApi httpApi){
+        ResponseEntity<String> responseEntity = null;
+        try {
+            responseEntity = restTemplate.exchange(httpApi.getUrl(),
+                    Objects.requireNonNull(HttpMethod.resolve(httpApi.getMethod())),
+                    new HttpEntity<>(httpApi.getPayload()),
+                    String.class);
+        } catch (Exception e) {
+            log.error("请求异常,请求数据:[{}].", httpApi.toString() ,e);
+        }
+        return responseEntity ==null?null:responseEntity.getBody();
+    }
+}

+ 5 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/config/DiamondConfig.java

@@ -0,0 +1,5 @@
+package com.hrsk.cloud.eg.infrastructure.clinent.config;
+
+public class DiamondConfig {
+    public final static String DummyConfig = "DummyConfig";
+}

+ 108 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/utils/HessianUtils.java

@@ -0,0 +1,108 @@
+package com.hrsk.cloud.eg.infrastructure.clinent.utils;
+
+import com.alibaba.cola.exception.SysException;
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.Hessian2Output;
+import com.google.common.collect.Lists;
+import com.hrsk.cloud.op.eg.domain.api.FunctionObject;
+import com.hrsk.cloud.op.eg.domain.api.HttpApiConfig;
+import com.hrsk.cloud.op.eg.domain.api.KeyValueObject;
+import com.hrsk.cloud.op.eg.domain.api.ValueObject;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-02 08:43
+ * @description: hessian工具类
+ **/
+@Slf4j
+public class HessianUtils {
+    public static byte[] serialize(Object object){
+        Hessian2Output ho = null;
+        try{
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            ho = new Hessian2Output(bos);
+            ho.writeObject(object);
+            ho.flush();
+            return bos.toByteArray();
+        } catch (IOException e) {
+            log.error("序列化对象异常!",e);
+            throw new SysException("序列化对象异常!",e);
+        }finally {
+            if(ho !=null){
+                try {
+                    ho.close();
+                } catch (IOException e) {
+                    log.error("序列化流关闭失败!",e);
+                }
+            }
+        }
+    }
+
+    /** Hessian反序列化 */
+    public static Object deserialize(byte[] bytes){
+        Hessian2Input hi = null;
+        try{
+            ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+            hi = new Hessian2Input(is);
+            return hi.readObject();
+        }catch (Exception e){
+            log.error("反序列化对象异常!",e);
+            throw new SysException("反序列化对象异常!",e);
+        }finally {
+            if(hi !=null){
+                try {
+                    hi.close();
+                } catch (IOException e) {
+                    log.error("序列化流关闭失败!",e);
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        FunctionObject md5 = new FunctionObject();
+        md5.setCode("md5");
+        HttpApiConfig hac = new HttpApiConfig()
+                .setUrl("https://baidu.com");
+        hac.setType("http");
+        List<KeyValueObject> h = Lists.newArrayList();
+        KeyValueObject h1 = new KeyValueObject();
+        h1.setKey("secretKey");
+        h1.setType("text");
+        h1.setValue("Khw99%$l%-2gF7P4jXglp_-jQqQirtYnOY5D");
+        h.add(h1);
+        KeyValueObject h2 = new KeyValueObject();
+        h2.setKey("merchantNo");
+        h2.setType("spel");
+        h2.setValue("#input.merchantNo");
+        h.add(h2);
+        List<ValueObject> p = Lists.newArrayList();
+        ValueObject p1 = new ValueObject();
+        p1.setType("text");
+        p1.setValue("123");
+        ValueObject p2 = new ValueObject();
+        p2.setType("text");
+        p2.setValue("456");
+        p2.getFunctions().add(md5);
+        p.add(p1);
+        p.add(p2);
+        List<KeyValueObject> s = Lists.newArrayList();
+        KeyValueObject s1 = new KeyValueObject();
+        s1.setKey("username");
+        s1.setType("spel");
+        s1.setValue("#input.username");
+        KeyValueObject s2 = new KeyValueObject();
+        s2.setKey("channel");
+        s2.setType("spel");
+        s2.setValue("#input.channel");
+        s.add(s2);
+        hac.setPath(p).setSearch(s).setHeader(h).setMethod("GET");
+        hac.setContent("{\"merchant\":\"xxxxxxfffff\",\"phone\":\"#{\\\"value\\\":\\\"#input.phone\\\",\\\"type\\\": \\\"spel\\\",\\\"functions\\\":[ {\\\"code\\\": \\\"md5\\\"}]}\"}");
+    }
+}

+ 18 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/clinent/utils/HttpConfiguration.java

@@ -0,0 +1,18 @@
+package com.hrsk.cloud.eg.infrastructure.clinent.utils;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-05 11:01
+ * @description: HTTP配置
+ **/
+@Configuration
+public class HttpConfiguration {
+    @Bean
+    public RestTemplate restTemplate(){
+        return new RestTemplate();
+    }
+}

+ 47 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/entity/BaseDo.java

@@ -0,0 +1,47 @@
+package com.hrsk.cloud.eg.infrastructure.repository.database.entity;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 18:04
+ * @description: DO基础类,公共字段
+ **/
+@Data
+public class BaseDo {
+    /**
+     * 主键
+     */
+    private Long id;
+    /**
+     * 创建人ID
+     */
+    private String createUid;
+    /**
+     * 创建名称
+     */
+    private String createUsername;
+    /**
+     * 创建时间
+     */
+    private Date gmtCreate;
+    /**
+     * 修改人ID
+     */
+    private String modifyUid;
+    /**
+     * 修改人名称
+     */
+    private String modifyUsername;
+    /**
+     * 修改时间
+     */
+    private Date gmtModify;
+    /**
+     * 状态
+     */
+    private String status;
+
+}