bianlz 1 неделя назад
Родитель
Сommit
b8660459a5
68 измененных файлов с 2556 добавлено и 72 удалено
  1. 33 0
      egress-gateway-service-adapter/src/main/java/com/hrsk/cloud/eg/adapter/controller/ApiController.java
  2. 26 0
      egress-gateway-service-app/src/main/java/com/hrsk/cloud/eg/app/api/ApiServiceImpl.java
  3. 26 0
      egress-gateway-service-app/src/main/java/com/hrsk/cloud/eg/app/api/executor/ApiInvokeCmdExe.java
  4. 18 0
      egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/api/ApiService.java
  5. 28 0
      egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/cmd/ApiInvokeCmd.java
  6. 16 0
      egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/cmd/ApiQryCmd.java
  7. 17 0
      egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/cmd/RouteCmd.java
  8. 1 0
      egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/package-info.java
  9. 28 0
      egress-gateway-service-domain/pom.xml
  10. 57 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/Api.java
  11. 99 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiChannel.java
  12. 35 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiFactory.java
  13. 18 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/ApiGateway.java
  14. 33 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/ApiContext.java
  15. 32 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/ContentTypeEnum.java
  16. 32 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/EgressApiEndpointIntegrationModeEnum.java
  17. 47 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/EgressApiErrorCodeEnum.java
  18. 34 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/EgressApiStatusEnum.java
  19. 21 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/KeyValueObject.java
  20. 94 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/ValueObject.java
  21. 34 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/ValueObjectTypeEnum.java
  22. 46 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/func/EncryptionFunction.java
  23. 45 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/func/FunctionObject.java
  24. 25 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/func/FunctionParam.java
  25. 66 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/func/ValueObjectFunctionManager.java
  26. 120 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/HttpApiRequest.java
  27. 46 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/HttpApiRequestConfig.java
  28. 50 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/HttpApiResponse.java
  29. 1 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/package-info.java
  30. 1 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/package-info.java
  31. 103 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/payload/ApiJsonPayloadResolver.java
  32. 18 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/payload/ApiPayloadResolver.java
  33. 59 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/payload/ApiPayloadResolverManage.java
  34. 27 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/vo/BasicTypeValueObjectResolver.java
  35. 17 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/vo/JsonPathValueObjectResolver.java
  36. 38 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/vo/SpelValueObjectResolver.java
  37. 22 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/vo/ValueObjectResolver.java
  38. 66 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/vo/ValueObjectResolverManager.java
  39. 56 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/route/ApiRoute.java
  40. 35 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/route/strategy/ChannelCodeBasedRouteStrategy.java
  41. 21 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/route/strategy/RouteStrategy.java
  42. 73 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/BeetlHelper.java
  43. 32 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/Constants.java
  44. 70 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/GsonUtils.java
  45. 44 0
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/SysErrorCodeEnum.java
  46. 1 3
      egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/package-info.java
  47. 24 4
      egress-gateway-service-infrastructure/pom.xml
  48. 42 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/http/HttpClient.java
  49. 69 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/http/RetryRequestConfig.java
  50. 141 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/http/RetryRestTemplate.java
  51. 1 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/package-info.java
  52. 63 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/common/HessianUtils.java
  53. 29 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/common/InfrastructureException.java
  54. 76 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/gatewayimpl/ApiGatewayImpl.java
  55. 22 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/dao/EgressApiChannelDao.java
  56. 47 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/entity/BaseDO.java
  57. 53 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/entity/EgressApiChannelDO.java
  58. 47 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/entity/EgressApiDO.java
  59. 13 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/mapper/EgressApiChannelMapper.java
  60. 13 0
      egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/mapper/EgressApiMapper.java
  61. 0 6
      egress-gateway-service-infrastructure/src/main/resources/db/data.sql
  62. 0 23
      egress-gateway-service-infrastructure/src/main/resources/db/schema.sql
  63. 2 2
      egress-gateway-service-infrastructure/src/main/resources/mybatis-config.xml
  64. 12 0
      egress-gateway-service-infrastructure/src/main/resources/mybatis/EgressApiChannelMapper.xml
  65. 53 8
      pom.xml
  66. 7 5
      start/src/main/java/com/hrsk/cloud/eg/Application.java
  67. 28 18
      start/src/main/resources/application-local.yaml
  68. 3 3
      start/src/main/resources/application.yaml

+ 33 - 0
egress-gateway-service-adapter/src/main/java/com/hrsk/cloud/eg/adapter/controller/ApiController.java

@@ -0,0 +1,33 @@
+package com.hrsk.cloud.eg.adapter.controller;
+
+import com.hrsk.cloud.eg.client.api.ApiService;
+import com.hrsk.cloud.eg.client.dto.cmd.ApiInvokeCmd;
+import com.hrsk.pangu.dto.SingleResponse;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-09 10:33
+ * @description: API Controller
+ **/
+@RestController
+@RequestMapping("/api")
+public class ApiController {
+    @Resource
+    private ApiService apiService;
+
+    /**
+     * 请求
+     * @param apiInvokeCmd api请求CMD
+     * @return 响应数据
+     */
+    @PostMapping("/invoke")
+    public SingleResponse<String> invoke(@RequestBody ApiInvokeCmd apiInvokeCmd){
+        return apiService.invoke(apiInvokeCmd);
+    }
+}

+ 26 - 0
egress-gateway-service-app/src/main/java/com/hrsk/cloud/eg/app/api/ApiServiceImpl.java

@@ -0,0 +1,26 @@
+package com.hrsk.cloud.eg.app.api;
+
+import com.hrsk.cloud.eg.app.api.executor.ApiInvokeCmdExe;
+import com.hrsk.cloud.eg.client.api.ApiService;
+import com.hrsk.cloud.eg.client.dto.cmd.ApiInvokeCmd;
+import com.hrsk.pangu.dto.SingleResponse;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-09 10:35
+ * @description: API服务实现
+ **/
+@Service
+public class ApiServiceImpl implements ApiService {
+    @Resource
+    private ApiInvokeCmdExe apiInvokeCmdExe;
+
+    @Override
+    public SingleResponse<String> invoke(ApiInvokeCmd apiInvokeCmd) {
+        String result = apiInvokeCmdExe.execute(apiInvokeCmd);
+        return SingleResponse.of(result);
+    }
+}

+ 26 - 0
egress-gateway-service-app/src/main/java/com/hrsk/cloud/eg/app/api/executor/ApiInvokeCmdExe.java

@@ -0,0 +1,26 @@
+package com.hrsk.cloud.eg.app.api.executor;
+
+import com.hrsk.cloud.eg.client.dto.cmd.ApiInvokeCmd;
+import com.hrsk.cloud.eg.domain.api.ApiGateway;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-09 10:57
+ * @description: API调用CMD EXE
+ **/
+@Component
+public class ApiInvokeCmdExe {
+    @Resource
+    private ApiGateway apiGateway;
+    /**
+     * 执行
+     * @param apiInvokeCmd CMD
+     * @return 处理结果JSON
+     */
+    public String execute(ApiInvokeCmd apiInvokeCmd){
+        return apiGateway.invoke(apiInvokeCmd);
+    }
+}

+ 18 - 0
egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/api/ApiService.java

@@ -0,0 +1,18 @@
+package com.hrsk.cloud.eg.client.api;
+
+import com.hrsk.cloud.eg.client.dto.cmd.ApiInvokeCmd;
+import com.hrsk.pangu.dto.SingleResponse;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-09 10:34
+ * @description: API服务
+ **/
+public interface ApiService {
+    /**
+     * 调用
+     * @param apiInvokeCmd API调用CMD
+     * @return 响应数据
+     */
+    SingleResponse<String> invoke(ApiInvokeCmd apiInvokeCmd);
+}

+ 28 - 0
egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/cmd/ApiInvokeCmd.java

@@ -0,0 +1,28 @@
+package com.hrsk.cloud.eg.client.dto.cmd;
+
+import com.hrsk.pangu.dto.Command;
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-09 10:44
+ * @description: API调用CMD
+ **/
+@Data
+public class ApiInvokeCmd extends Command {
+    /**
+     * API编码
+     */
+    private String apiCode;
+    /**
+     * 路由
+     */
+    private RouteCmd route;
+    /**
+     * 数据
+     */
+    private Map<String,Object> data;
+
+}

+ 16 - 0
egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/cmd/ApiQryCmd.java

@@ -0,0 +1,16 @@
+package com.hrsk.cloud.eg.client.dto.cmd;
+
+import lombok.Data;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 11:26
+ * @description:API查询CMD
+ **/
+@Data
+public class ApiQryCmd {
+    /**
+     * API编码
+     */
+    private String apiCode;
+}

+ 17 - 0
egress-gateway-service-client/src/main/java/com/hrsk/cloud/eg/client/dto/cmd/RouteCmd.java

@@ -0,0 +1,17 @@
+package com.hrsk.cloud.eg.client.dto.cmd;
+
+import com.hrsk.pangu.dto.Command;
+import lombok.Data;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 18:01
+ * @description: 路由CMD
+ **/
+@Data
+public class RouteCmd extends Command {
+    /**
+     * 路由编码
+     */
+    private String code;
+}

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

@@ -0,0 +1 @@
+package com.hrsk.cloud.eg.client.dto;

+ 28 - 0
egress-gateway-service-domain/pom.xml

@@ -24,9 +24,37 @@
             <groupId>com.hrsk.pangu</groupId>
             <artifactId>pangu-component-tool</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.hrsk.cloud</groupId>
+            <artifactId>egress-gateway-service-client</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.jayway.jsonpath</groupId>
+            <artifactId>json-path</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ibeetl</groupId>
+            <artifactId>beetl</artifactId>
+        </dependency>
     </dependencies>
 </project>

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

@@ -0,0 +1,57 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.google.common.base.Function;
+import com.hrsk.cloud.eg.client.dto.cmd.RouteCmd;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.EgressApiErrorCodeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiRequest;
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiResponse;
+import com.hrsk.cloud.eg.domain.api.route.ApiRoute;
+import com.hrsk.pangu.tool.exception.BizException;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 16:18
+ * @description: API实体
+ **/
+public class Api {
+    /**
+     * API通道列表
+     */
+    private List<ApiChannel> apiChannels;
+    /**
+     * 最终目标通道
+     */
+    private ApiChannel target;
+
+    /**
+     * 构造函数
+     * @param apiChannels
+     */
+    public Api(List<ApiChannel> apiChannels) {
+        this.apiChannels = apiChannels;
+    }
+
+    /**
+     * 调用
+     * @param input 入参
+     */
+    public String invoke(Map<String,Object> input, Function<HttpApiRequest, HttpApiResponse> httpClientFunc){
+        if(target == null){
+            throw new BizException(EgressApiErrorCodeEnum.AVAILABLE_API_CHANNEL_NOT_EXIST.getCode(),EgressApiErrorCodeEnum.API_CHANNEL_NOT_EXIST.getMessage());
+        }
+        return target.invoke(input,httpClientFunc);
+    }
+
+    /**
+     * 路由
+     * @param route 路由
+     * @return 路由后的API
+     */
+    public Api route(RouteCmd route){
+        target = ApiRoute.getInstance().route(apiChannels,route);
+        return this;
+    }
+}

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

@@ -0,0 +1,99 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.google.common.base.Function;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.EgressApiEndpointIntegrationModeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.EgressApiErrorCodeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiRequest;
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiRequestConfig;
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiResponse;
+import com.hrsk.cloud.eg.domain.common.BeetlHelper;
+import com.hrsk.cloud.eg.domain.common.GsonUtils;
+import com.hrsk.pangu.tool.exception.BizException;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.Map;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 16:28
+ * @description: API通道
+ **/
+@Data
+public class ApiChannel {
+    /**
+     * 通道编码
+     */
+    private String channelCode;
+    /**
+     * 集成方式
+     */
+    private String integrationMode;
+    /**
+     * 权重
+     */
+    private Integer weight;
+    /**
+     * 请求/响应数据JSON配置
+     */
+    private Pair<String,String> configStrPair;
+    /**
+     * Http Api 请求配置
+     */
+    private HttpApiRequestConfig httpApiRequestConfig;
+    /**
+     * Http Api 响应配置
+     */
+    private String httpApiResponseConfig;
+
+    /**
+     * 评分,用于路由排序
+     */
+    private Integer score;
+
+    /**
+     * 构造函数
+     * @param channelCode 渠道编码
+     * @param integrationMode 集成方式
+     * @param requestJsonConfig 请求配置
+     * @param responseJsonConfig 响应配置
+     */
+    public ApiChannel(String channelCode,String integrationMode ,String requestJsonConfig, String responseJsonConfig) {
+        this.channelCode = channelCode;
+        this.integrationMode = integrationMode;
+        configStrPair = Pair.of(requestJsonConfig,responseJsonConfig);
+    }
+
+
+
+    /**
+     * 使配置生效
+     */
+    public void config(){
+        if(StringUtils.equals(integrationMode,EgressApiEndpointIntegrationModeEnum.GUIDE.getCode())){
+            httpApiRequestConfig = GsonUtils.fromJson(configStrPair.getLeft(),HttpApiRequestConfig.class);
+            httpApiResponseConfig = configStrPair.getRight();
+        }
+    }
+
+    /**
+     * 调用
+     * @param input 入参
+     * @param httpClientFunc httpclient
+     * @return 处理结果
+     */
+    public String invoke(Map<String,Object> input,Function<HttpApiRequest, HttpApiResponse> httpClientFunc){
+        HttpApiResponse response = null;
+        if(StringUtils.equals(integrationMode, EgressApiEndpointIntegrationModeEnum.GUIDE.getCode())){
+            config();
+            response = httpClientFunc.apply(new HttpApiRequest(httpApiRequestConfig).request(input));
+            return BeetlHelper.render(httpApiResponseConfig,response);
+        }else if(StringUtils.equals(integrationMode, EgressApiEndpointIntegrationModeEnum.CUSTOMIZE.getCode())){
+            //todo 代码模式
+            return null;
+        }else{
+            throw new BizException(EgressApiErrorCodeEnum.ILLEGAL_INTEGRATION_MODE.getCode(),EgressApiErrorCodeEnum.ILLEGAL_INTEGRATION_MODE.getMessage());
+        }
+    }
+}

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

@@ -0,0 +1,35 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 21:01
+ * @description: API工厂
+ **/
+public class ApiFactory {
+    /**
+     * 创建API通道
+     * @param apiCode
+     */
+    /**
+     * 创建API通道
+     * @param apiCode API编码
+     * @param integrationMode 集成方式
+     * @param requestConfigStr 请求配置
+     * @param responseConfigStr 响应配置
+     * @return
+     */
+    public static ApiChannel createApiChannel(String apiCode,String integrationMode,String requestConfigStr,String responseConfigStr){
+        return new ApiChannel(apiCode,integrationMode,requestConfigStr,responseConfigStr);
+    }
+
+    /**
+     * 创建API
+     * @param apiChannels api通道
+     * @return API
+     */
+    public static Api createApi(List<ApiChannel> apiChannels){
+        return new Api(apiChannels);
+    }
+}

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

@@ -0,0 +1,18 @@
+package com.hrsk.cloud.eg.domain.api;
+
+import com.hrsk.cloud.eg.client.dto.cmd.ApiInvokeCmd;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-11 06:18
+ * @description: API网关
+ **/
+public interface ApiGateway {
+
+    /**
+     * 通过api code调用
+     * @param apiInvokeCmd cmd
+     * @return 调用结果
+     */
+    String invoke(ApiInvokeCmd apiInvokeCmd);
+}

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

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

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

@@ -0,0 +1,32 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.common;
+
+import lombok.Getter;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-11 15:05
+ * @description: 内容类型枚举
+ **/
+@Getter
+public enum ContentTypeEnum {
+    APPLICATION_JSON("application/json"),
+    JSON("json");
+
+    /**
+     * 编码
+     * -- GETTER --
+     *  获取编码
+     *
+     * @return 编码
+
+     */
+    private final String code;
+
+    /**
+     * 构造函数
+     * @param code 编码
+     */
+    ContentTypeEnum(String code) {
+        this.code = code;
+    }
+}

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

@@ -0,0 +1,32 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.common;
+
+import lombok.Getter;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-04 10:43
+ * @description: 通道接出方式
+ **/
+@Getter
+public enum EgressApiEndpointIntegrationModeEnum {
+    CUSTOMIZE("customize","自定义代码模式"),
+    GUIDE("guide","向导模式");
+    /**
+     * 编码
+     */
+    private String code;
+    /**
+     * 描述
+     */
+    private String desc;
+
+    /**
+     * 构造函数
+     * @param code
+     * @param desc
+     */
+    EgressApiEndpointIntegrationModeEnum(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 47 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/EgressApiErrorCodeEnum.java

@@ -0,0 +1,47 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.common;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-11 11:02
+ * @description: 接出API错误码枚举
+ **/
+public enum EgressApiErrorCodeEnum {
+
+    ILLEGAL_INTEGRATION_MODE("100004","不合法的集成方式!"),
+    AVAILABLE_API_CHANNEL_NOT_EXIST("100003","没有可用的API通道!"),
+    API_CHANNEL_NOT_EXIST("100002","API通道不存在!"),
+    API_NOT_EXIST("100001","API不存在!");
+    private String code;
+
+    private String message;
+    /**
+     * 前缀
+     */
+    private static final String PREFIX = "egress-";
+
+    /**
+     * 构造函数
+     * @param code
+     * @param message
+     */
+    EgressApiErrorCodeEnum(String code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    /**
+     * 获取编码
+     * @return 编码
+     */
+    public String getCode() {
+        return PREFIX + code;
+    }
+
+    /**
+     * 获取消息
+     * @return 返回消息
+     */
+    public String getMessage() {
+        return message;
+    }
+}

+ 34 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/EgressApiStatusEnum.java

@@ -0,0 +1,34 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.common;
+
+import lombok.Getter;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-10-22 10:49
+ * @description: 接出API状态枚举
+ **/
+@Getter
+public enum EgressApiStatusEnum {
+    DRAFT("draft","草稿"),
+    OK("ok","启用"),
+    DEACTIVATE("deactivate","停用"),
+    DELETE("delete","删除");
+    /**
+     * 编码
+     */
+    private String code;
+    /**
+     * 描述
+     */
+    private String desc;
+
+    /**
+     * 构造函数
+     * @param code 编码
+     * @param desc 描述
+     */
+    EgressApiStatusEnum(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 21 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/KeyValueObject.java

@@ -0,0 +1,21 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.common;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-05 14:34
+ * @description: kv对象
+ **/
+@ToString
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class KeyValueObject extends ValueObject {
+    /**
+     * key
+     */
+    private String key;
+
+}

+ 94 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/common/ValueObject.java

@@ -0,0 +1,94 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.common;
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.func.FunctionObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.resolver.vo.ValueObjectResolverManager;
+import com.hrsk.cloud.eg.domain.common.GsonUtils;
+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: 值对象
+ **/
+
+@ToString
+public class ValueObject implements Serializable {
+    /**
+     * 值类型
+     */
+    private String type;
+    /**
+     * 值
+     */
+    @Getter
+    private String value;
+    /**
+     * 真实值
+     */
+    @Getter
+    private Object realValue;
+    /**
+     * 函数链
+     */
+    @Setter
+    private List<FunctionObject> functions = new ArrayList<>();
+
+    /**
+     * 构造函数
+     */
+    public ValueObject() {
+    }
+
+    /**
+     * 构造函数
+     * @param value 值
+     */
+    public ValueObject(String value) {
+        this.value = value;
+    }
+
+    /**
+     * 解析
+     * @param apiContext
+     * @return
+     */
+    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;
+    }
+
+    /**
+     * 类型
+     * @return 类型
+     */
+    public String getType(){
+        return StringUtils.isEmpty(type) ? typeInference():type;
+    }
+
+    /**
+     * 类型推测
+     * @return 类型
+     */
+    private String typeInference(){
+        if(GsonUtils.isJson(value)){
+            return ValueObjectTypeEnum.JSON_PATH.getType();
+        }else{
+            return ValueObjectTypeEnum.BASIC.getType();
+        }
+    }
+
+}

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

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

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

@@ -0,0 +1,46 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.func;
+
+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;
+        }
+    }
+}

+ 45 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/func/FunctionObject.java

@@ -0,0 +1,45 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.func;
+
+import com.google.common.collect.Lists;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.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();
+
+    /**
+     * 执行
+     * @param value 值对象
+     * @param apiContext 上下文
+     * @return 结果
+     */
+    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/channel/guide/func/FunctionParam.java

@@ -0,0 +1,25 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.func;
+
+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();
+}

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

@@ -0,0 +1,66 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.func;
+
+import com.hrsk.pangu.tool.exception.BizException;
+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);
+//        FUNCTIONS.put("md5Sign", EncryptionFunction::md5Sign);
+        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);
+    }
+}

+ 120 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/HttpApiRequest.java

@@ -0,0 +1,120 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.http;
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ContentTypeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.KeyValueObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.resolver.payload.ApiPayloadResolverManage;
+import com.hrsk.pangu.tool.exception.BizException;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import static com.hrsk.cloud.eg.domain.common.Constants.URL_SEARCH;
+import static com.hrsk.cloud.eg.domain.common.Constants.URL_SEARCH_SEPARATOR;
+import static com.hrsk.cloud.eg.domain.common.Constants.URL_SEPARATOR;
+import static com.hrsk.cloud.eg.domain.common.Constants._EQUAL;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-11 14:53
+ * @description: http api request
+ **/
+public class HttpApiRequest {
+    /**
+     * http api请求配置
+     */
+    private HttpApiRequestConfig httpApiRequestConfig;
+    /**
+     * 请求方法
+     */
+    @Getter
+    private String method;
+    /**
+     * url地址
+     */
+    @Getter
+    private String url;
+    /**
+     * header数据
+     */
+    @Getter
+    private final Map<String, Object> header = new HashMap<>();
+    /**
+     * 请求payload数据
+     */
+    @Getter
+    private Object payload;
+
+    /**
+     * 构造函数
+     * @param httpApiRequestConfig 请求配置
+     */
+    public HttpApiRequest(HttpApiRequestConfig httpApiRequestConfig) {
+        this.httpApiRequestConfig = httpApiRequestConfig;
+    }
+
+    /**
+     * 请求
+     * @param input 入参
+     * @return this
+     */
+    public HttpApiRequest request(Map<String,Object> input){
+        ApiContext context = new ApiContext(input);
+        url(context);
+        header(context);
+        body(context);
+        return this;
+    }
+
+    /**
+     * 创建URL
+     * @param context 上下文
+     */
+    private void url(ApiContext context){
+        StringBuilder urlSb = new StringBuilder(httpApiRequestConfig.getUrl());
+        for(ValueObject valueObject : httpApiRequestConfig.getPath()){
+            urlSb.append(URL_SEPARATOR).append(valueObject.compile(context).getRealValue());
+        }
+        if(!CollectionUtils.isEmpty(httpApiRequestConfig.getSearch())){
+            StringBuilder searchSb = new StringBuilder();
+            for(KeyValueObject keyValueObject : httpApiRequestConfig.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,""));
+        }
+        method = httpApiRequestConfig.getMethod();
+        url = urlSb.toString();
+    }
+
+    /**
+     * 创建header
+     * @param context 上下文
+     */
+    private void header(ApiContext context){
+        for(KeyValueObject keyValueObject : httpApiRequestConfig.getHeader()){
+            this.header.put(keyValueObject.getKey(),  keyValueObject.compile(context).getRealValue().toString());
+        }
+    }
+
+    /**
+     * 加载请求体
+     * @param context 上下文
+     */
+    private void body(ApiContext context){
+        if(StringUtils.isEmpty(httpApiRequestConfig.getBody())){
+            return ;
+        }
+        if(StringUtils.equals(httpApiRequestConfig.getContentType(), ContentTypeEnum.APPLICATION_JSON.getCode())){
+            payload = Objects.toString(
+                    ApiPayloadResolverManage.getInstance().resolve(httpApiRequestConfig.getContentType(),
+                            httpApiRequestConfig.getBody(),context),"{}");
+        }else{
+            throw new BizException("不支持的请求体类型!");
+        }
+    }
+}

+ 46 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/HttpApiRequestConfig.java

@@ -0,0 +1,46 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.http;
+
+import com.google.common.collect.Lists;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ContentTypeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.KeyValueObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObject;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 21:26
+ * @description: HTTP API 请求配置
+ **/
+@Data
+public class HttpApiRequestConfig {
+    /**
+     * 请求方法
+     */
+    private String method;
+    /**
+     * url地址
+     */
+    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 = ContentTypeEnum.APPLICATION_JSON.getCode();
+    /**
+     * body
+     */
+    private String body;
+}

+ 50 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/http/HttpApiResponse.java

@@ -0,0 +1,50 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.http;
+
+import lombok.Data;
+
+import java.util.HashMap;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-12 18:20
+ * @description: http api响应
+ **/
+@Data
+public class HttpApiResponse extends HashMap<String,Object> {
+    /**
+     * http响应编码
+     */
+    private Integer httpCode;
+    /**
+     * 数据body
+     */
+    private Object data;
+
+    /**
+     * 构造函数
+     * @param httpCode HTTP编码
+     * @param data 数据
+     */
+    public HttpApiResponse( Integer httpCode, Object data) {
+        super();
+        setHttpCode(httpCode);
+        setData(data);
+    }
+
+    public Integer getHttpCode() {
+        return (Integer)get("httpCode");
+    }
+
+    public Object getData() {
+        return get("data");
+    }
+
+
+    public void setHttpCode(Integer httpCode) {
+        put("httpCode",httpCode);
+    }
+
+    public void setData(Object data) {
+        put("data",data);
+    }
+}

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

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

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

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

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

@@ -0,0 +1,103 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.resolver.payload;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObject;
+import com.hrsk.cloud.eg.domain.common.GsonUtils;
+import com.hrsk.pangu.tool.exception.BizException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 15:38
+ * @description: json类型payload
+ **/
+@Slf4j
+public class ApiJsonPayloadResolver implements ApiPayloadResolver {
+    /**
+     * JSON配置最大深度
+     */
+    private static final Integer MAX_DEEP = 10;
+    /**
+     * 配置前缀标记
+     */
+    private static final String CV_PREFIX_SIGN = "<cv>";
+
+    /**
+     * 配置后缀标记
+     */
+    private static final String CV_END_SIGN = "</cv>";
+
+    @Override
+    public JsonObject resolve(String jsonTemplate, ApiContext context) {
+        JsonElement jsonElement = GsonUtils.fromJson(jsonTemplate, JsonElement.class);
+        traverseJson(jsonElement,jsonElement,null,context,0);
+        return jsonElement.getAsJsonObject();
+    }
+
+
+    /**
+     * 遍历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 {
+            JsonPrimitive newElement = parseValueConfigTagToRealValue(jsonElement.getAsJsonPrimitive(),context);
+            if(StringUtils.isNotBlank(currentKey)){
+                currentElement.getAsJsonObject().add(currentKey,newElement);
+            }
+        }
+    }
+
+    /**
+     * 将spel表达式转换成真实值 暂时不使用后续如果有spel表达式可以采用类型推测进行适配
+     * @param jsonPrimitive json元素
+     */
+    private JsonPrimitive parseValueConfigTagToRealValue(JsonPrimitive jsonPrimitive, ApiContext context){
+        String valueStr = jsonPrimitive.getAsString();
+        if(valueStr.startsWith("<cv>") && valueStr.endsWith("</cv>")){
+            valueStr = StringUtils.replaceOnce(valueStr,CV_PREFIX_SIGN,"");
+            valueStr = StringUtils.substringBeforeLast(valueStr,CV_END_SIGN);
+            try {
+                ValueObject valueObject = new Gson().fromJson(valueStr, 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);
+                }
+            }catch (Exception ex){
+                log.error("'{}'解析失败,转为字符串类型。",valueStr,ex);
+                return jsonPrimitive;
+            }
+        }
+        return jsonPrimitive;
+    }
+
+
+}

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

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

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

@@ -0,0 +1,59 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.resolver.payload;
+
+import com.google.common.collect.Maps;
+import com.google.gson.JsonObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ContentTypeEnum;
+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 JsonObject 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(ContentTypeEnum.APPLICATION_JSON.getCode(),new ApiJsonPayloadResolver());
+        RESOLVER_MAP.put(ContentTypeEnum.JSON.getCode(),new ApiJsonPayloadResolver());
+    }
+}

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

@@ -0,0 +1,27 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.resolver.vo;
+
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.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();
+    }
+
+}

+ 17 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/channel/guide/resolver/vo/JsonPathValueObjectResolver.java

@@ -0,0 +1,17 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.resolver.vo;
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.jayway.jsonpath.JsonPath;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-11 16:10
+ * @description: json path 值对象处理
+ **/
+public class JsonPathValueObjectResolver implements ValueObjectResolver {
+    @Override
+    public Object resolve(ValueObject valueObject, ApiContext context) {
+        return JsonPath.read(context.getData(), valueObject.getValue());
+    }
+}

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

@@ -0,0 +1,38 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.resolver.vo;
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.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;
+        }
+    }
+
+
+}

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

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

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

@@ -0,0 +1,66 @@
+package com.hrsk.cloud.eg.domain.api.channel.guide.resolver.vo;
+
+import com.google.common.collect.Maps;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObject;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ValueObjectTypeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.ApiContext;
+import com.hrsk.pangu.tool.exception.BizException;
+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();
+
+    /**
+     * 构造函数
+     */
+    private ValueObjectResolverManager(){
+        log.info("开始注册ValueObject解析器......");
+        RESOLVERS.put(ValueObjectTypeEnum.SPEL.getType(),new SpelValueObjectResolver());
+        RESOLVERS.put(ValueObjectTypeEnum.BASIC.getType(),new BasicTypeValueObjectResolver());
+        RESOLVERS.put(ValueObjectTypeEnum.JSON_PATH.getType(),new JsonPathValueObjectResolver());
+        log.info("结束注册ValueObject解析器,加载内容:{},{},{}.",ValueObjectTypeEnum.SPEL.getType(),ValueObjectTypeEnum.BASIC.getType(),ValueObjectTypeEnum.JSON_PATH.getType());
+    }
+
+    /**
+     * 获取实例
+     * @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);
+    }
+
+}

+ 56 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/route/ApiRoute.java

@@ -0,0 +1,56 @@
+package com.hrsk.cloud.eg.domain.api.route;
+
+import com.google.common.collect.Lists;
+import com.hrsk.cloud.eg.client.dto.cmd.RouteCmd;
+import com.hrsk.cloud.eg.domain.api.ApiChannel;
+import com.hrsk.cloud.eg.domain.api.route.strategy.ChannelCodeBasedRouteStrategy;
+import com.hrsk.cloud.eg.domain.api.route.strategy.RouteStrategy;
+
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 16:21
+ * @description:API路由
+ **/
+public class ApiRoute {
+    /**
+     * 单例
+     */
+    private static final ApiRoute ROUTE = new ApiRoute();
+    /**
+     * 路由策略列表
+     */
+    private List<RouteStrategy> routeStrategies = Lists.newArrayList();
+
+    /**
+     * 获取实例
+     * @return 实例
+     */
+    public static final ApiRoute getInstance(){
+        return ROUTE;
+    }
+    /**
+     * 构造函数
+     */
+    private ApiRoute(){
+        routeStrategies.add(new ChannelCodeBasedRouteStrategy());
+    }
+
+    /**
+     * 路由
+     * @param apiChannels API通道列表
+     */
+    public ApiChannel route(List<ApiChannel> apiChannels, RouteCmd route){
+        for(RouteStrategy routeStrategy : routeStrategies){
+            if(routeStrategy.route(apiChannels,route)){
+                break;
+            }
+        }
+        if(apiChannels.size()>0){
+            return apiChannels.get(0);
+        }
+        return null;
+    }
+
+}

+ 35 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/route/strategy/ChannelCodeBasedRouteStrategy.java

@@ -0,0 +1,35 @@
+package com.hrsk.cloud.eg.domain.api.route.strategy;
+
+import com.hrsk.cloud.eg.client.dto.cmd.RouteCmd;
+import com.hrsk.cloud.eg.domain.api.ApiChannel;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 17:26
+ * @description: API通道编码路由策略 这是一个过滤路由
+ **/
+public class ChannelCodeBasedRouteStrategy implements RouteStrategy{
+
+    @Override
+    public boolean route(List<ApiChannel> apiChannels, RouteCmd route){
+        if(StringUtils.isEmpty(route.getCode())){
+            return true;
+        }
+        apiChannels = apiChannels.stream().filter(new Predicate<ApiChannel>() {
+            @Override
+            public boolean test(ApiChannel apiChannel) {
+                return StringUtils.equals(apiChannel.getChannelCode(),route.getCode());
+            }
+        }).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(apiChannels)){
+            return false;
+        }
+        return true;
+    }
+}

+ 21 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/api/route/strategy/RouteStrategy.java

@@ -0,0 +1,21 @@
+package com.hrsk.cloud.eg.domain.api.route.strategy;
+
+import com.hrsk.cloud.eg.client.dto.cmd.RouteCmd;
+import com.hrsk.cloud.eg.domain.api.ApiChannel;
+
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-10 19:18
+ * @description:路由策略
+ **/
+public interface RouteStrategy {
+    /**
+     * 路由
+     * @param apiChannels 通道列表
+     * @param route 路由数据
+     * @return 是否下一个
+     */
+    boolean route(List<ApiChannel> apiChannels, RouteCmd route);
+}

+ 73 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/BeetlHelper.java

@@ -0,0 +1,73 @@
+package com.hrsk.cloud.eg.domain.common;
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiResponse;
+import com.hrsk.pangu.tool.exception.SysException;
+import lombok.extern.slf4j.Slf4j;
+import org.beetl.core.Configuration;
+import org.beetl.core.GroupTemplate;
+import org.beetl.core.Template;
+import org.beetl.core.resource.StringTemplateResourceLoader;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-12 17:32
+ * @description: beetl帮助类 此方法使用spring bean周期,spring启动前不可用
+ **/
+@Slf4j
+@Component
+public class BeetlHelper implements InitializingBean {
+    /**
+     * TEMPLATE
+     */
+    private static GroupTemplate GT = null;
+
+    /**
+     * 解析 {success: ${data.httpStatus == 200 ? true : false} , data: ${data.data}}
+     * @param templateStr
+     * @param input
+     * @return
+     */
+    public static String render(String templateStr, Object input){
+        Template template = GT.getTemplate(templateStr);
+        template.binding("response", input);
+        try {
+            return template.render();
+        } catch (Exception e) {
+            log.error("模板渲染失败!template:{}",templateStr,e);
+            throw new SysException(SysErrorCodeEnum.BEETL_ERROR.getCode(),SysErrorCodeEnum.BEETL_ERROR.getMessage());
+        }
+    }
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
+        Configuration cfg = null;
+        try {
+            cfg = Configuration.defaultConfiguration();
+        } catch (IOException e) {
+            log.error("初始化BEETLE配置失败!",e);
+        }
+        GT = new GroupTemplate(resourceLoader, cfg);
+        log.info("完成Beetl工具类加载 ...");
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        HttpApiResponse response = new HttpApiResponse(200,"<html>\n" +
+                "<meta http-equiv=\"refresh\" content=\"0;url=http://www.baidu.com/\">\n" +
+                "</html>");
+        Map<String,Object> map = new HashMap<>();
+        map.put("httpStatus",200);
+        map.put("data","<html>\n" +
+                "<meta http-equiv=\"refresh\" content=\"0;url=http://www.baidu.com/\">\n" +
+                "</html>");
+        new BeetlHelper().afterPropertiesSet();
+        System.out.println(BeetlHelper.render("{success: ${response.httpStatus == 200 ? true : false} , data: ${response.data}}",map));
+    }
+}

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

@@ -0,0 +1,32 @@
+package com.hrsk.cloud.eg.domain.common;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-05 14:46
+ * @description:
+ **/
+public class Constants {
+    /**
+     * url分隔符
+     */
+    public static final String URL_SEPARATOR = "/";
+
+    /**
+     * search分隔符
+     */
+    public static final String URL_SEARCH_SEPARATOR = "&";
+
+    /**
+     * 等于号
+     */
+    public static final String _EQUAL = "=";
+    /**
+     * search标记符
+     */
+    public static final String URL_SEARCH = "?";
+    /**
+     * 正则-jsonpath
+     */
+    public static final String REGEX_JSON_PATH = "^\\$\\..*";
+
+}

+ 70 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/GsonUtils.java

@@ -0,0 +1,70 @@
+package com.hrsk.cloud.eg.domain.common;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 16:58
+ * @description: Gson工具类
+ **/
+public class GsonUtils {
+    /**
+     * gson
+     */
+    public static final Gson GSON = new Gson();
+    /**
+     * 转换JSON
+     * @return 实体
+     * @param <T> 范型
+     */
+    public static <T> T fromJson(String json,Class<T> classz){
+        return GSON.fromJson(json,classz);
+    }
+
+    /**
+     * 转换JSON
+     * @return 实体
+     * @param <T> 范型
+     */
+    public static <T> T fromJson(JsonElement json, Class<T> classz){
+        return GSON.fromJson(json,classz);
+    }
+
+
+    /**
+     * 转化JSON
+     * @param object 参数
+     * @return JSON
+     */
+    public static String toJson(Object object){
+        return GSON.toJson(object);
+    }
+
+    /**
+     * 转化json object
+     * @param object
+     * @return
+     */
+    public static JsonObject toJsonObject(Object object){
+        String json = GSON.toJson(object);
+        return GSON.fromJson(json, JsonObject.class);
+    }
+
+    /**
+     * json类型推测,判断是否是json
+     * @param str
+     * @return
+     */
+    public static boolean isJson(String str){
+        if(StringUtils.isEmpty(str)){
+            return false;
+        }
+        Pattern pattern = Pattern.compile(Constants.REGEX_JSON_PATH);
+        return pattern.matcher(str).matches();
+    }
+}

+ 44 - 0
egress-gateway-service-domain/src/main/java/com/hrsk/cloud/eg/domain/common/SysErrorCodeEnum.java

@@ -0,0 +1,44 @@
+package com.hrsk.cloud.eg.domain.common;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-12 18:15
+ * @description: 系统错误编码枚举
+ **/
+public enum SysErrorCodeEnum {
+    BEETL_ERROR("100001","模版渲染失败!");
+    private String code;
+
+    private String message;
+    /**
+     * 前缀
+     */
+    private static final String PREFIX = "sys-";
+
+    /**
+     * 构造函数
+     * @param code 编码
+     * @param message 描述消息
+     */
+    SysErrorCodeEnum(String code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    /**
+     * 获取编码
+     * @return 编码
+     */
+    public String getCode() {
+        return PREFIX + code;
+    }
+
+    /**
+     * 获取消息
+     * @return 返回消息
+     */
+    public String getMessage() {
+        return message;
+    }
+
+}

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

@@ -1,3 +1 @@
-package com.hrsk.cloud.eg.domain;
-
-xx
+package com.hrsk.cloud.eg.domain;

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

@@ -20,10 +20,6 @@
             <groupId>com.hrsk.cloud</groupId>
             <artifactId>egress-gateway-service-domain</artifactId>
         </dependency>
-        <dependency>
-            <groupId>com.hrsk.cloud</groupId>
-            <artifactId>egress-gateway-service-client</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
@@ -42,5 +38,29 @@
             <artifactId>h2</artifactId>
             <scope>runtime</scope>
         </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.caucho</groupId>
+            <artifactId>hessian</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 42 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/http/HttpClient.java

@@ -0,0 +1,42 @@
+package com.hrsk.cloud.eg.infrastructure.client.http;
+
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiRequest;
+import com.hrsk.cloud.eg.infrastructure.common.InfrastructureException;
+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 org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.Objects;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-06 11:14
+ * @description: HTTP请求客户端
+ **/
+@Slf4j
+@Component
+public class HttpClient {
+    @Resource
+    private RestTemplate restTemplate;
+    /**
+     * 数据交换
+     * @param request 请求
+     * @return response 响应
+     */
+    public ResponseEntity<String> exchange(HttpApiRequest request){
+        ResponseEntity<String> responseEntity = null;
+        try {
+            return restTemplate.exchange(request.getUrl(),
+                    Objects.requireNonNull(HttpMethod.resolve(request.getMethod())),
+                    new HttpEntity<>(request.getPayload()),
+                    String.class);
+        } catch (Exception e) {
+            log.error("请求异常,请求数据:[{}].", request.toString() ,e);
+            throw new InfrastructureException("请求异常!",e);
+        }
+    }
+}

+ 69 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/http/RetryRequestConfig.java

@@ -0,0 +1,69 @@
+package com.hrsk.cloud.eg.infrastructure.client.http;
+
+/**
+ * Author: zhangyy
+ * Date: 2019/3/20
+ * Description:
+ */
+public class RetryRequestConfig {
+    //http请求timeout时的重试次数
+    int retryCount = 3;
+    //http请求timeout,重试间隔时间,重试间隔时间=次数*100 ms.
+    long retryIntervalTime = 100;
+    //连接池连接数量
+    int connectMaxTotal = 200;
+    //连接超时时间
+    int connectTimeout = 30000;
+    // 数据读取超时时间,即SocketTimeout
+    int readTimeout = 30000;
+    // 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
+    int ConnectionRequestTimeout = 10000;
+
+    public int getRetryCount() {
+        return retryCount;
+    }
+
+    public void setRetryCount(int retryCount) {
+        this.retryCount = retryCount;
+    }
+
+    public long getRetryIntervalTime() {
+        return retryIntervalTime;
+    }
+
+    public void setRetryIntervalTime(long retryIntervalTime) {
+        this.retryIntervalTime = retryIntervalTime;
+    }
+
+    public int getConnectMaxTotal() {
+        return connectMaxTotal;
+    }
+
+    public void setConnectMaxTotal(int connectMaxTotal) {
+        this.connectMaxTotal = connectMaxTotal;
+    }
+
+    public int getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    public void setConnectTimeout(int connectTimeout) {
+        this.connectTimeout = connectTimeout;
+    }
+
+    public int getReadTimeout() {
+        return readTimeout;
+    }
+
+    public void setReadTimeout(int readTimeout) {
+        this.readTimeout = readTimeout;
+    }
+
+    public int getConnectionRequestTimeout() {
+        return ConnectionRequestTimeout;
+    }
+
+    public void setConnectionRequestTimeout(int connectionRequestTimeout) {
+        ConnectionRequestTimeout = connectionRequestTimeout;
+    }
+}

+ 141 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/client/http/RetryRestTemplate.java

@@ -0,0 +1,141 @@
+package com.hrsk.cloud.eg.infrastructure.client.http;
+
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.NoHttpResponseException;
+import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.protocol.HttpContext;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Author: zhangyy
+ * Date: 2019/3/20
+ * Description:
+ */
+@Configuration
+public class RetryRestTemplate {
+
+    @Value("${http.client.retryIntervalTime:0}")
+    private Long retryIntervalTime;
+
+    @Value("${http.client.connectTimeout:2500}")
+    private Integer connectTimeout;
+
+    @Value("${http.client.connectionRequestTimeout:1500}")
+    private Integer connectionRequestTimeout;
+
+    private RetryRequestConfig requestConfig = new RetryRequestConfig();
+
+    public RetryRestTemplate(RetryRequestConfig requestConfig) {
+        this.requestConfig = requestConfig;
+    }
+
+    public RetryRestTemplate() {
+    }
+
+    /**
+     * 配置restTemplate
+     */
+    private void config(){
+        if(retryIntervalTime!=null){
+            requestConfig.setRetryIntervalTime(retryIntervalTime);
+        }
+        if(connectTimeout!=null){
+            requestConfig.setConnectTimeout(connectTimeout);
+        }
+        if(connectionRequestTimeout!=null){
+            requestConfig.setConnectionRequestTimeout(connectionRequestTimeout);
+        }
+    }
+
+    @Bean
+    public RestTemplate restTemplate(){
+        RestTemplate restTemplate = new RestTemplate();
+        config();
+        //1.用UTF-8 StringHttpMessageConverter替换默认StringHttpMessageConverter
+        List<HttpMessageConverter<?>> newMessageConverters = new ArrayList<>();
+        for(HttpMessageConverter<?> converter : restTemplate.getMessageConverters()){
+            if(converter instanceof StringHttpMessageConverter){
+                StringHttpMessageConverter messageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
+                newMessageConverters.add(messageConverter);
+            }else {
+                newMessageConverters.add(converter);
+            }
+        }
+        restTemplate.setMessageConverters(newMessageConverters);
+        //2. retryHandler add
+        HttpClientBuilder httpClientBuilder = HttpClients.custom();
+        HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
+            @Override
+            public boolean retryRequest(IOException exception, int curRetryCount, HttpContext context) {
+                try {
+                    //重试延迟
+                    TimeUnit.SECONDS.sleep(curRetryCount*requestConfig.getRetryIntervalTime());
+                } catch (InterruptedException e) {
+
+                }
+                if (curRetryCount > requestConfig.getRetryCount()) {
+                    return false;
+                }
+                if (exception instanceof ConnectTimeoutException
+                        || exception instanceof NoHttpResponseException || exception instanceof ConnectException) {
+                    return true;
+                }
+                HttpClientContext clientContext = HttpClientContext.adapt(context);
+                org.apache.http.HttpRequest request = clientContext.getRequest();
+                boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
+                // 如果请求被认为是幂等的,那么就重试。即重复执行不影响程序其他效果的
+                return idempotent;
+            }
+        };
+        // 3.支持HTTP、HTTPS
+        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
+                .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                .register("https", SSLConnectionSocketFactory.getSocketFactory())
+                .build();
+        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
+        connectionManager.setMaxTotal(this.requestConfig.getConnectMaxTotal());
+        connectionManager.setDefaultMaxPerRoute(100);
+        connectionManager.setValidateAfterInactivity(2000);
+        httpClientBuilder.setRetryHandler(handler)
+                            .setConnectionManager(connectionManager);
+
+        CloseableHttpClient httpClient = httpClientBuilder.build();
+        // httpClient连接配置,底层是配置RequestConfig
+        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+        // 连接超时
+        clientHttpRequestFactory.setConnectTimeout(this.requestConfig.getConnectTimeout());
+        // 数据读取超时时间,即SocketTimeout
+        clientHttpRequestFactory.setReadTimeout(this.requestConfig.getReadTimeout());
+        // 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
+        clientHttpRequestFactory.setConnectionRequestTimeout(this.requestConfig.getConnectionRequestTimeout());
+        // 缓冲请求数据,默认值是true。通过POST或者PUT大量发送数据时,建议将此属性更改为false,以免耗尽内存。
+        // clientHttpRequestFactory.setBufferRequestBody(false);
+        restTemplate.setRequestFactory(clientHttpRequestFactory);
+        return restTemplate;
+    }
+
+}

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

@@ -0,0 +1 @@
+package com.hrsk.cloud.eg.infrastructure.client;

+ 63 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/common/HessianUtils.java

@@ -0,0 +1,63 @@
+package com.hrsk.cloud.eg.infrastructure.common;
+
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.Hessian2Output;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * @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);
+            throw new RuntimeException("序列化对象异常!",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);
+            throw new RuntimeException("反序列化对象异常!",e);
+        }finally {
+            if(hi !=null){
+                try {
+                    hi.close();
+                } catch (IOException e) {
+                    log.error("序列化流关闭失败!",e);
+                }
+            }
+        }
+    }
+
+}

+ 29 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/common/InfrastructureException.java

@@ -0,0 +1,29 @@
+package com.hrsk.cloud.eg.infrastructure.common;
+
+import com.hrsk.pangu.tool.exception.BaseException;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-06 17:01
+ * @description: 基础设施异常
+ **/
+public class InfrastructureException extends BaseException {
+    private static final long serialVersionUID = 1L;
+    private static final String DEFAULT_ERR_CODE = "INF_ERROR";
+
+    public InfrastructureException(String errMessage) {
+        super("INF_ERROR", errMessage);
+    }
+
+    public InfrastructureException(String errCode, String errMessage) {
+        super(errCode, errMessage);
+    }
+
+    public InfrastructureException(String errMessage, Throwable e) {
+        super("INF_ERROR", errMessage, e);
+    }
+
+    public InfrastructureException(String errorCode, String errMessage, Throwable e) {
+        super(errorCode, errMessage, e);
+    }
+}

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

@@ -0,0 +1,76 @@
+package com.hrsk.cloud.eg.infrastructure.gatewayimpl;
+
+import com.google.gson.JsonElement;
+import com.hrsk.cloud.eg.client.dto.cmd.ApiInvokeCmd;
+import com.hrsk.cloud.eg.domain.api.Api;
+import com.hrsk.cloud.eg.domain.api.ApiChannel;
+import com.hrsk.cloud.eg.domain.api.ApiFactory;
+import com.hrsk.cloud.eg.domain.api.ApiGateway;
+import com.hrsk.cloud.eg.domain.api.channel.guide.common.EgressApiErrorCodeEnum;
+import com.hrsk.cloud.eg.domain.api.channel.guide.http.HttpApiResponse;
+import com.hrsk.cloud.eg.domain.common.GsonUtils;
+import com.hrsk.cloud.eg.infrastructure.client.http.HttpClient;
+import com.hrsk.cloud.eg.infrastructure.repository.database.dao.EgressApiChannelDao;
+import com.hrsk.cloud.eg.infrastructure.repository.database.entity.EgressApiChannelDO;
+import com.hrsk.pangu.tool.exception.BizException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-06 13:54
+ * @description: API网关防腐层实现类
+ **/
+@Slf4j
+@Component
+public class ApiGatewayImpl implements ApiGateway {
+    @Resource
+    private HttpClient httpClient;
+    @Resource
+    private EgressApiChannelDao egressApiChannelDao;
+
+    /**
+     * 调用
+     * @param apiInvokeCmd cmd CMD
+     * @return 处理结果
+     */
+    @Override
+    public String invoke(ApiInvokeCmd apiInvokeCmd) {
+        List<EgressApiChannelDO> egressApiChannels = egressApiChannelDao.selectByApiCode(apiInvokeCmd.getApiCode());
+        if(CollectionUtils.isEmpty(egressApiChannels)){
+            throw new BizException(EgressApiErrorCodeEnum.API_CHANNEL_NOT_EXIST.getCode(),
+                    EgressApiErrorCodeEnum.API_CHANNEL_NOT_EXIST.getMessage());
+        }
+        List<ApiChannel> apiChannels = egressApiChannels.stream().
+                map(egressApiChannelDO -> ApiFactory.createApiChannel(egressApiChannelDO.getChannelCode(),egressApiChannelDO.getIntegrationMode(),
+                        egressApiChannelDO.getRequestConfig(),egressApiChannelDO.getResponseConfig())).collect(Collectors.toList());
+        Api api = ApiFactory.createApi(apiChannels);
+        return api.route(apiInvokeCmd.getRoute()).invoke(apiInvokeCmd.getData(), input -> {
+            ResponseEntity<String> response = httpClient.exchange(input);
+            if(GsonUtils.isJson(response.getBody())){
+                JsonElement jsonElement = GsonUtils.fromJson(response.getBody(), JsonElement.class);
+                if(jsonElement.isJsonObject()){
+                    return new HttpApiResponse(response.getStatusCodeValue(),jsonElement.getAsJsonObject());
+                }else if(jsonElement.isJsonArray()){
+                    return new HttpApiResponse(response.getStatusCodeValue(),jsonElement.getAsJsonArray());
+                }else{
+                    return new HttpApiResponse(response.getStatusCodeValue(),jsonElement.getAsJsonPrimitive());
+                }
+            }
+            else{
+                return new HttpApiResponse(response.getStatusCodeValue(),response.getBody());
+            }
+        });
+    }
+
+    public static void main(String[] args) {
+        JsonElement jsonElement = GsonUtils.fromJson("<html>123</html>",JsonElement.class);
+        System.out.println(jsonElement);
+    }
+}

+ 22 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/dao/EgressApiChannelDao.java

@@ -0,0 +1,22 @@
+package com.hrsk.cloud.eg.infrastructure.repository.database.dao;
+
+import com.hrsk.cloud.eg.infrastructure.repository.database.entity.EgressApiChannelDO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-11-11 16:42
+ * @description: dao
+ **/
+@Repository
+public interface EgressApiChannelDao {
+    /**
+     * 通过API CODE查询
+     * @param apiCode API CODE
+     * @return 通道列表
+     */
+    List<EgressApiChannelDO> selectByApiCode(@Param("apiCode") String apiCode);
+}

+ 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;
+
+}

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

@@ -0,0 +1,53 @@
+package com.hrsk.cloud.eg.infrastructure.repository.database.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-01 18:34
+ * @description: API通道数据对象
+ **/
+@Data
+@TableName("egress_api_channel")
+@EqualsAndHashCode(callSuper = true)
+public class EgressApiChannelDO extends BaseDO{
+    /**
+     * ID
+     */
+    private Long id;
+    /**
+     * egress_api的主键
+     */
+    private Long apiId;
+    /**
+     * 通道名称
+     */
+    private String channelName;
+    /**
+     * 通道编码
+     */
+    private String channelCode;
+    /**
+     * 通道类型
+     */
+    private String channelType;
+    /**
+     * 集成方式
+     */
+    private String integrationMode;
+    /**
+     * 请求配置
+     */
+    private String requestConfig;
+    /**
+     * 响应配置
+     */
+    private String responseConfig;
+    /**
+     * 备注
+     */
+    private String memo;
+
+}

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

@@ -0,0 +1,47 @@
+package com.hrsk.cloud.eg.infrastructure.repository.database.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-08-02 08:14
+ * @description: 接出网关API表
+ **/
+@Data
+@TableName("eg_api")
+@EqualsAndHashCode(callSuper = true)
+public class EgressApiDO extends BaseDO{
+    /** ID **/
+    private Long id;
+    /**
+     * API名称
+     */
+    private String apiName;
+    /**
+     * API编码
+     */
+    private String apiCode;
+    /**
+     * API类型
+     */
+    private String apiType;
+    /**
+     * 技术负责人ID
+     */
+    private Long techOwnerUserid;
+    /**
+     * 技术负责人
+     */
+    private String techOwnerUsername;
+
+    /**
+     * 备注
+     */
+    private String memo;
+    /**
+     * 状态
+     */
+    private String status;
+}

+ 13 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/mapper/EgressApiChannelMapper.java

@@ -0,0 +1,13 @@
+package com.hrsk.cloud.eg.infrastructure.repository.database.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.hrsk.cloud.eg.infrastructure.repository.database.entity.EgressApiChannelDO;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-06 14:51
+ * @description: eg_api_channel数据库映射类
+ **/
+public interface EgressApiChannelMapper extends BaseMapper<EgressApiChannelDO> {
+
+}

+ 13 - 0
egress-gateway-service-infrastructure/src/main/java/com/hrsk/cloud/eg/infrastructure/repository/database/mapper/EgressApiMapper.java

@@ -0,0 +1,13 @@
+package com.hrsk.cloud.eg.infrastructure.repository.database.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.hrsk.cloud.eg.infrastructure.repository.database.entity.EgressApiDO;
+
+/**
+ * @author: bianlanzhou
+ * @create: 2024-09-06 14:47
+ * @description: eg_api数据库映射
+ **/
+public interface EgressApiMapper extends BaseMapper<EgressApiDO> {
+
+}

+ 0 - 6
egress-gateway-service-infrastructure/src/main/resources/db/data.sql

@@ -1,6 +0,0 @@
-/*  本地模式,h2数据库数据初始化脚本 **/
-
-SET FOREIGN_KEY_CHECKS=0;
-
-INSERT INTO `tb_archetype` (`id`, `status`, `create_userid`, `create_username`, `modify_userid`, `modify_username`)
-VALUES (1, 'ok', '10000', 'admin', '10000', 'admin');

+ 0 - 23
egress-gateway-service-infrastructure/src/main/resources/db/schema.sql

@@ -1,23 +0,0 @@
-/* 本地模式,h2数据库表结构初始化脚本**/
-SET NAMES utf8 ;
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-SET FOREIGN_KEY_CHECKS=0;
-
-/** 样例原型表 **/
-DROP TABLE IF EXISTS `tb_archetype`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `tb_archetype` (
-    `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
-    `status` varchar(20) NOT NULL COMMENT '状态:created=已创建,deleted=已删除。',
-    `create_userid` varchar(100) DEFAULT NULL COMMENT '创建人',
-    `create_username` varchar(100) DEFAULT NULL COMMENT '创建用户名',
-    `modify_userid` varchar(100) DEFAULT NULL COMMENT '修改人ID',
-    `modify_username` varchar(100) DEFAULT NULL COMMENT '修改人名称',
-    `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-    `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-    PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='原型表';

+ 2 - 2
egress-gateway-service-infrastructure/src/main/resources/mybatis-config.xml

@@ -13,6 +13,6 @@
         <package name="com.hrsk.cloud.eg.infrastructure.repository.database.entity"/>
     </typeAliases>
     <mappers>
-        <!--<mapper resource="mybatis/ExampleMapper.xml"/>-->
+        <mapper resource="mybatis/EgressApiChannelMapper.xml"/>
     </mappers>
-</configuration>
+</configuration>

+ 12 - 0
egress-gateway-service-infrastructure/src/main/resources/mybatis/EgressApiChannelMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.hrsk.cloud.eg.infrastructure.repository.database.dao.EgressApiChannelDao">
+    <select id="selectByApiCode" parameterType="EgressApiChannelDO" resultType="EgressApiChannelDO">
+        select eac.* from egress_api_channel eac
+        join egress_api ea on eac.api_id = ea.id
+        <where>
+            ea.api_code = #{apiCode} and eac.`status` = 'ok' and ea.`status` = 'ok'
+        </where>
+    </select>
+</mapper>

+ 53 - 8
pom.xml

@@ -17,9 +17,14 @@
         <atlantis-component.version>1.0.0</atlantis-component.version>
         <spring-boot.version>2.7.6</spring-boot.version>
         <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
-        <mybatis-starter.version>2.2.2</mybatis-starter.version>
+        <mybatis-starter.version>2.3.1</mybatis-starter.version>
         <mybatis-plus.version>3.5.4.1</mybatis-plus.version>
         <druid-starter.version>1.2.9</druid-starter.version>
+        <guava.version>33.2.1-jre</guava.version>
+        <hessian.version>4.0.60</hessian.version>
+        <flyway-core.version>7.15.0</flyway-core.version>
+        <json-path.version>2.7.0</json-path.version>
+        <beetl.version>3.9.3.RELEASE</beetl.version>
     </properties>
 
     <dependencies>
@@ -94,14 +99,54 @@
                 <artifactId>druid-spring-boot-starter</artifactId>
                 <version>${druid-starter.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.baomidou</groupId>
+                <artifactId>mybatis-plus-boot-starter</artifactId>
+                <version>${mybatis-plus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.baomidou</groupId>
+                <artifactId>mybatis-plus</artifactId>
+                <version>${mybatis-plus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.caucho</groupId>
+                <artifactId>hessian</artifactId>
+                <version>${hessian.version}</version>
+            </dependency>
+            <!-- 数据库版本控制 -->
+            <dependency>
+                <groupId>org.flywaydb</groupId>
+                <artifactId>flyway-core</artifactId>
+                <version>${flyway-core.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.jayway.jsonpath</groupId>
+                <artifactId>json-path</artifactId>
+                <version>${json-path.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.ibeetl</groupId>
+                <artifactId>beetl</artifactId>
+                <version>${beetl.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
-<modules>  <module>start</module>
-    <module>egress-gateway-service-app</module>
-    <module>egress-gateway-service-adapter</module>
-    <module>egress-gateway-service-client</module>
-    <module>egress-gateway-service-infrastructure</module>
-    <module>egress-gateway-service-domain</module>
-  </modules>
+    <modules>
+        <module>start</module>
+        <module>egress-gateway-service-app</module>
+        <module>egress-gateway-service-adapter</module>
+        <module>egress-gateway-service-client</module>
+        <module>egress-gateway-service-infrastructure</module>
+        <module>egress-gateway-service-domain</module>
+    </modules>
 </project>

+ 7 - 5
start/src/main/java/com/hrsk/cloud/eg/Application.java

@@ -4,10 +4,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.util.StopWatch;
 
 @Slf4j
 @SpringBootApplication
-@MapperScan("com.hrsk.cloud.eg.infrastructure.repository.database.mapper")
+@MapperScan("com.hrsk.cloud.eg.infrastructure.repository.database")
 public class Application {
     /**
      * main函数
@@ -23,9 +24,10 @@ public class Application {
      */
     private static void launch(String[] args){
         log.info("Begin to start Spring Boot Application ......");
-        long startTime = System.currentTimeMillis();
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start();
         SpringApplication.run(Application.class, args);
-        long endTime = System.currentTimeMillis();
-        log.info("Spring Boot Application has been started, Time used: "+ (endTime - startTime) + "ms" );
+        stopWatch.stop();
+        log.info("Spring Boot Application has been started, Time used: {} ms .",stopWatch.getTotalTimeMillis());
     }
-}
+}

+ 28 - 18
start/src/main/resources/application-local.yaml

@@ -1,26 +1,36 @@
 #spring
 spring:
-  sql:
-    init:
-      schema-locations: classpath:db/schema.sql
-      data-locations: classpath:db/data.sql
-      platform: H2
-      encoding: utf-8
-  h2:
-    console:
-      enabled: true
-      settings:
-        web-allow-others: true
-      path: /h2
   datasource:
-    driver-class-name: org.h2.Driver
-    url: jdbc:h2:mem:atlantis;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=true;INIT=CREATE SCHEMA IF NOT EXISTS atlantis
-    username: sa
-    password:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://chengyirongpre.rwlb.rds.aliyuncs.com:3306/open-platform?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+    username: loan_pre
+    password: A3oDWgM4YxaHR0cDovL2NybDMu
     type: com.zaxxer.hikari.HikariDataSource
     hikari:
       minimum-idle: 5
       idle-timeout: 180000
       auto-commit: true
-      connection-timeout: 30000
-      connection-test-query: select 1
+      connection-timeout: 300000
+      connection-test-query: select 1
+  # redis 配置
+  redis:
+    # 地址
+    host: 47.96.139.31
+    # 端口,默认为6379
+    port: 6380
+    # 数据库索引
+    database: 2
+    # 密码
+    password: IICdQIBA#DANB%gkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAK8f%
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms

+ 3 - 3
start/src/main/resources/application.yaml

@@ -1,6 +1,6 @@
 #server
 server:
-  port: 8081
+  port: 8082
   servlet:
     context-path: /
 #spring
@@ -9,8 +9,8 @@ spring:
     name: xx-server
   profiles:
     active: local
-#mybatis
-mybatis:
+#mybatis-plus
+mybatis-plus:
   config-location: classpath:mybatis-config.xml
 #pageHelper
 pagehelper: