Kaynağa Gözat

feat: 1.添加HttpUtils工具类,使用WebClient实现
2.执行预处理接口

wanggaokun 9 ay önce
ebeveyn
işleme
d4c98e1b28

+ 6 - 0
als-common/common-core/pom.xml

@@ -30,6 +30,12 @@
             <artifactId>spring-context-support</artifactId>
         </dependency>
 
+        <!-- WebClient -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+
         <!-- SpringWeb模块 -->
         <dependency>
             <groupId>org.springframework</groupId>

+ 277 - 0
als-common/common-core/src/main/java/org/eco/common/core/utils/HttpUtils.java

@@ -0,0 +1,277 @@
+package org.eco.common.core.utils;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.netty.channel.ChannelOption;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.reactive.ClientHttpConnector;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.ClientResponse;
+import org.springframework.web.reactive.function.client.ExchangeStrategies;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+
+import java.time.Duration;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description: HttpUtils
+ * @Author: GaoKun Wang
+ * @Date: 2024/7/30
+ */
+@Slf4j
+public class HttpUtils {
+    private static final Integer DEFAULT_CONNECT_TIMEOUT = 3000;
+
+    private static final Integer DEFAULT_REQUEST_TIMEOUT = 50000;
+
+    private static final Integer MAX_IN_MEMORY_SIZE = 100 * 1024 * 1024;
+
+    /**
+     * get请求解析成字符串
+     *
+     * @param url url
+     * @return java.lang.String
+     */
+    public static ClientResponse getResponse(String url) {
+        Mono<ClientResponse> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).exchangeToMono(Mono::just);
+        return resp.block();
+    }
+
+    /**
+     * get请求,解析成对象
+     *
+     * @param url     url
+     * @param tClass  class
+     * @param headers 请求头
+     * @return T
+     */
+    public static <T> T get(String url, Class<T> tClass, Map<String, String> headers) {
+        Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).headers(t -> t.setAll(headers))
+            .retrieve().bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * get请求,解析成对象
+     *
+     * @param url     url
+     * @param headers 请求头
+     * @return T
+     */
+    public static String get(String url, Map<String, String> headers) {
+        Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).headers(t -> t.setAll(headers))
+            .retrieve().bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * get请求,解析成对象
+     *
+     * @param scheme  协议 http/https
+     * @param host    host
+     * @param obj     query params
+     * @param headers 请求头
+     * @return T
+     */
+    public static String get(String scheme, String host, String path, Object obj, Map<String, String> headers) {
+        Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().get()
+            .uri(uriBuilder -> uriBuilder.scheme(scheme).host(host).path(path).queryParams(getRequestParamMapByObj(obj))
+                .build())
+            .headers(t -> t.setAll(headers)).retrieve().bodyToMono(String.class)
+            .timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * get请求,解析成对象
+     *
+     * @param url    url
+     * @param tClass class
+     * @return T
+     */
+    public static <T> T get(String url, Object obj, Class<T> tClass) {
+        Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().get()
+            .uri(uriBuilder -> uriBuilder.path(url).queryParams(getRequestParamMapByObj(obj)).build()).retrieve()
+            .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * get请求,解析成对象
+     *
+     * @param url    url
+     * @param tClass class
+     * @return T
+     */
+    public static <T> T get(String url, Class<T> tClass) {
+        Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).retrieve().bodyToMono(tClass)
+            .timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * get请求解析成字符串
+     *
+     * @param url url
+     * @return java.lang.String
+     */
+    public static String get(String url) {
+        Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().get().uri(url).retrieve()
+            .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * post表单请求返回对象
+     *
+     * @param url    url
+     * @param params 请求参数
+     * @param tClass 返回对象
+     * @return T
+     */
+    public static <T> T post(String url, Map<String, String> params, Class<T> tClass) {
+        MultiValueMap<String, String> formData = getRequestParamMap(params);
+        Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
+            .contentType(MediaType.APPLICATION_FORM_URLENCODED).body(BodyInserters.fromFormData(formData)).retrieve()
+            .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * post表单请求返回字符串
+     *
+     * @param url    url
+     * @param params 请求参数
+     * @return java.lang.String
+     */
+    public static String post(String url, Map<String, String> params) {
+        MultiValueMap<String, String> formData = getRequestParamMap(params);
+        Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
+            .contentType(MediaType.APPLICATION_FORM_URLENCODED).body(BodyInserters.fromFormData(formData)).retrieve()
+            .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * post json请求结果解析成对象
+     *
+     * @param url      url
+     * @param jsonBody 请求body,可以是对象或者是map
+     * @param tClass   解析对象
+     * @return T
+     */
+    public static <T> T postJson(String url, Object jsonBody, Class<T> tClass) {
+        Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
+            .contentType(MediaType.APPLICATION_JSON).body(Mono.just(jsonBody), Object.class).retrieve()
+            .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * post json请求结果解析成对象
+     *
+     * @param url      url
+     * @param jsonBody 请求body,可以是对象或者是map
+     * @param tClass   解析对象
+     * @return T
+     */
+    public static <T> T postJson(String url, Map<String, String> headers, Object jsonBody, Class<T> tClass) {
+        Mono<T> resp =
+            createWebClientWithConnectAndReadTimeOuts().post().uri(url).contentType(MediaType.APPLICATION_JSON)
+                .headers(t -> t.setAll(headers)).body(Mono.just(jsonBody), Object.class).retrieve().bodyToMono(tClass)
+                .timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * post json请求结果解析成字符串
+     *
+     * @param url      url
+     * @param jsonBody 请求body,可以是对象或者是map
+     * @return java.lang.String
+     */
+    public static String postJson(String url, Object jsonBody) {
+        Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
+            .contentType(MediaType.APPLICATION_JSON).body(Mono.just(jsonBody), Object.class).retrieve()
+            .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    /**
+     * post json请求结果解析成字符串
+     *
+     * @param url      url
+     * @param jsonBody 请求body,可以是对象或者是map
+     * @return java.lang.String
+     */
+    public static String postJson(String url, Map<String, String> headers, Object jsonBody) {
+        Mono<String> resp =
+            createWebClientWithConnectAndReadTimeOuts().post().uri(url).contentType(MediaType.APPLICATION_JSON)
+                .headers(t -> t.setAll(headers)).body(Mono.just(jsonBody), Object.class).retrieve()
+                .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+        return resp.block();
+    }
+
+    public static <T> T postRawJson(String url, String jsonBody, Class<T> tClass) {
+        Mono<T> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
+            .contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(jsonBody)).retrieve()
+            .bodyToMono(tClass).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+
+        return resp.block();
+    }
+
+    public static String postRawJson(String url, String jsonBody) {
+        Mono<String> resp = createWebClientWithConnectAndReadTimeOuts().post().uri(url)
+            .contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(jsonBody)).retrieve()
+            .bodyToMono(String.class).timeout(Duration.ofMillis(DEFAULT_REQUEST_TIMEOUT));
+
+        return resp.block();
+    }
+
+    private static WebClient createWebClientWithConnectAndReadTimeOuts() {
+        // 创建 reactor netty HTTP client
+        HttpClient httpClient = HttpClient.create().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, DEFAULT_CONNECT_TIMEOUT).doOnConnected(connection ->
+            connection.addHandlerLast(new ReadTimeoutHandler(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS))
+        );
+        // 使用上述 HTTP 客户端创建客户端 HTTP 连接器
+        ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
+        // 使用此配置的 HTTP 连接器构建 Web 客户端
+        return WebClient.builder()
+            .exchangeStrategies(ExchangeStrategies.builder()
+                .codecs(
+                    clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE))
+                .build())
+            .clientConnector(connector).build();
+    }
+
+    private static MultiValueMap<String, String> getRequestParamMap(Map<String, String> params) {
+        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
+        for (Map.Entry<String, String> entry : params.entrySet()) {
+            queryParams.add(entry.getKey(), entry.getValue());
+        }
+        return queryParams;
+    }
+
+    private static MultiValueMap<String, String> getRequestParamMapByObj(Object obj) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> map = objectMapper.convertValue(obj, new TypeReference<>() {
+        });
+        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            if (Objects.isNull(entry.getValue())) {
+                continue;
+            }
+            queryParams.add(entry.getKey(), String.valueOf(entry.getValue()));
+        }
+        return queryParams;
+    }
+}

+ 4 - 5
als-common/common-core/src/main/java/org/eco/common/core/utils/file/FileUtils.java

@@ -1,10 +1,6 @@
 package org.eco.common.core.utils.file;
 
 import cn.hutool.core.io.FileUtil;
-import org.eco.common.core.config.EcoConfig;
-import org.eco.common.core.utils.DateUtils;
-import org.eco.common.core.utils.StringUtils;
-import org.eco.common.core.utils.uuid.IdUtils;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.AccessLevel;
@@ -12,6 +8,10 @@ import lombok.NoArgsConstructor;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
+import org.eco.common.core.config.EcoConfig;
+import org.eco.common.core.utils.DateUtils;
+import org.eco.common.core.utils.StringUtils;
+import org.eco.common.core.utils.uuid.IdUtils;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -176,7 +176,6 @@ public class FileUtils extends FileUtil {
      */
     public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
         String percentEncodedFileName = percentEncode(realFileName);
-
         StringBuilder contentDispositionValue = new StringBuilder();
         contentDispositionValue.append("attachment; filename=")
             .append(percentEncodedFileName)

+ 2 - 0
als-common/common-log/src/main/java/org/eco/common/log/enums/BusinessType.java

@@ -55,4 +55,6 @@ public enum BusinessType {
      * 清空数据
      */
     CLEAN,
+
+    EXECUTE,
 }

+ 35 - 0
als-modules/agile-assurance/src/main/java/org/eco/als/controller/AlgorithmController.java

@@ -0,0 +1,35 @@
+package org.eco.als.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import org.eco.als.domain.bo.AlgorithmBo;
+import org.eco.als.service.IAlgorithmService;
+import org.eco.common.core.core.domain.CommonResult;
+import org.eco.common.log.annotation.Log;
+import org.eco.common.log.enums.BusinessType;
+import org.springframework.validation.annotation.Validated;
+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;
+
+/**
+ * @Description: AlgorithmController 算法相关控制
+ * @Author: GaoKun Wang
+ * @Date: 2024/7/30
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/als/algorithm")
+public class AlgorithmController {
+    @Resource
+    private IAlgorithmService algorithmService;
+    @SaCheckPermission("als:algorithm:execute")
+    @Log(title = "执行算法", businessType = BusinessType.EXECUTE)
+    @PostMapping("/execute/pro")
+    public CommonResult<String> executePro(@Validated @RequestBody AlgorithmBo algorithmBo) {
+        return CommonResult.success(algorithmService.executePro(algorithmBo));
+    }
+}

+ 49 - 0
als-modules/agile-assurance/src/main/java/org/eco/als/domain/bo/AlgorithmBo.java

@@ -0,0 +1,49 @@
+package org.eco.als.domain.bo;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.eco.common.orm.core.domain.BaseEntity;
+
+/**
+ * 模型信息业务对象 als_model_t
+ *
+ * @author wgk
+ * @date 2024-07-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class AlgorithmBo extends BaseEntity {
+    /**
+     * 模型Id
+     */
+    @NotNull(message = "模型Id不能为空")
+    private Long modelId;
+
+    /**
+     * 数据Id
+     */
+    @NotNull(message = "模型Id不能为空")
+    private Long dataId;
+
+    /**
+     * 模型链接
+     */
+    @NotBlank(message = "模型链接不能为空")
+    private String url;
+
+    /**
+     * 参数
+     */
+    @NotBlank(message = "模型参数不能为空")
+    private String param;
+
+    /**
+     * 数据列
+     */
+    @NotBlank(message = "数据列不能为空")
+    private String columnData;
+
+
+}

+ 15 - 0
als-modules/agile-assurance/src/main/java/org/eco/als/domain/vo/ModelHttpVo.java

@@ -0,0 +1,15 @@
+package org.eco.als.domain.vo;
+
+import lombok.Data;
+
+/**
+ * @Description: ModelHttpVo
+ * @Author: GaoKun Wang
+ * @Date: 2024/7/30
+ */
+@Data
+public class ModelHttpVo {
+    private String status;
+    private String data;
+    private String msg;
+}

+ 12 - 0
als-modules/agile-assurance/src/main/java/org/eco/als/service/IAlgorithmService.java

@@ -0,0 +1,12 @@
+package org.eco.als.service;
+
+import org.eco.als.domain.bo.AlgorithmBo;
+
+/**
+ * @Description: IAlgorithmService
+ * @Author: GaoKun Wang
+ * @Date: 2024/7/30
+ */
+public interface IAlgorithmService {
+    String executePro(AlgorithmBo algorithmBo);
+}

+ 80 - 0
als-modules/agile-assurance/src/main/java/org/eco/als/service/impl/AlgorithmService.java

@@ -0,0 +1,80 @@
+package org.eco.als.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.eco.als.domain.bo.AlgorithmBo;
+import org.eco.als.domain.vo.DataImportVo;
+import org.eco.als.domain.vo.ModelHttpVo;
+import org.eco.als.domain.vo.ModelVo;
+import org.eco.als.service.IAlgorithmService;
+import org.eco.als.service.IDataImportService;
+import org.eco.als.service.IModelService;
+import org.eco.common.core.exception.BusinessException;
+import org.eco.common.core.utils.HttpUtils;
+import org.eco.system.service.ISysOssService;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description: AlgorithmService
+ * @Author: GaoKun Wang
+ * @Date: 2024/7/30
+ */
+@Service
+@Slf4j
+public class AlgorithmService implements IAlgorithmService {
+    @Resource
+    private IModelService modelService;
+
+    @Resource
+    private IDataImportService dataImportService;
+
+    @Resource
+    private ISysOssService ossService;
+
+    /**
+     * executePro 预处理
+     *
+     * @param algorithmBo 参数
+     * @return java.lang.String
+     **/
+    @Override
+    public String executePro(AlgorithmBo algorithmBo) {
+        // 模型相关信息
+        ModelVo modelVo = modelService.selectById(algorithmBo.getModelId());
+        if (ObjectUtil.isNull(modelVo)) {
+            throw new BusinessException("模型信息为空,请检查!");
+        }
+        // 数据相关信息
+        DataImportVo dataVo = dataImportService.selectById(algorithmBo.getDataId());
+        if (ObjectUtil.isNull(dataVo)) {
+            throw new BusinessException("数据为空,请检查!");
+        }
+        // 参数
+        String param = algorithmBo.getParam();
+        Map<String, Object> map = new HashMap<>(JSONUtil.parseObj(param));
+        map.put("url", modelVo.getUrl());
+
+        // 数据url
+
+
+        // 请求
+        ModelHttpVo result = HttpUtils.postJson(modelVo.getUrl(), map, ModelHttpVo.class);
+
+
+        String url = modelVo.getUrl();
+
+        return null;
+    }
+
+    public static void main(String[] args) {
+        String jsonStr = "{\"name\":\"John\", \"age\":30, \"city\":\"New York\"}";
+        Map<String, Object> map = new HashMap<>(JSONUtil.parseObj(jsonStr));
+        System.out.println(map);
+
+    }
+}

+ 1 - 1
pom.xml

@@ -41,7 +41,7 @@
         <lombok.version>1.18.30</lombok.version>
         <mapstruct-plus.version>1.3.6</mapstruct-plus.version>
         <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
-        <hutool.version>5.8.27</hutool.version>
+        <hutool.version>5.8.29</hutool.version>
         <redisson.version>3.26.0</redisson.version>
         <lock4j.version>2.2.7</lock4j.version>
         <alibaba-ttl.version>2.14.4</alibaba-ttl.version>