初始化项目

This commit is contained in:
2026-04-21 15:45:20 +08:00
parent 16d7cb6531
commit 0baba59d57
21 changed files with 1131 additions and 19 deletions

35
xtools-cloud-call/pom.xml Normal file
View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xujun</groupId>
<artifactId>xtools-cloud</artifactId>
<version>5.0.0</version>
</parent>
<artifactId>xtools-cloud-call</artifactId>
<!-- 依赖 -->
<dependencies>
<!-- xtools-boot begin -->
<!-- xtools-boot-core -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-core</artifactId>
</dependency>
<!-- xtools-boot-log -->
<dependency>
<groupId>org.xujun</groupId>
<artifactId>xtools-boot-log</artifactId>
</dependency>
<!-- xtools-boot end -->
<!-- Loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,28 @@
package xtools.cloud.call;
import org.springframework.context.annotation.Import;
import xtools.boot.core.utils.ModuleLoadUtils;
import xtools.cloud.call.selector.CloudClientImportSelector;
/**
* <p>Title : CloudClientConfiguration</p>
* <p>Description : CloudClientConfiguration</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
@Import(CloudClientImportSelector.class)
public class CloudClientConfiguration {
/**
* 构造方法
*/
public CloudClientConfiguration() {
ModuleLoadUtils.loadSuccess(CloudClientConfiguration.class);
}
}

View File

@@ -0,0 +1,45 @@
package xtools.cloud.call.config;
import org.springframework.boot.restclient.RestClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import xtools.cloud.call.interceptor.ClientHttpInterceptor;
/**
* <p>Title : RestClientConfig</p>
* <p>Description : RestClientConfig</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/26 15:36
*/
@Configuration
public class RestClientConfig {
/**
* RestClient自定义配置
*
* @return RestClient自定义配置
*/
@Bean
public RestClientCustomizer restClientCustomizer() {
return restClientBuilder -> {
// 配置拦截器
restClientBuilder.requestInterceptor(clientHttpInterceptor());
};
}
/**
* 创建拦截器
*
* @return 拦截器
*/
@Bean
public ClientHttpInterceptor clientHttpInterceptor() {
return new ClientHttpInterceptor();
}
}

View File

@@ -0,0 +1,60 @@
package xtools.cloud.call.interceptor;
import lombok.AllArgsConstructor;
import org.jspecify.annotations.NonNull;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.client.ClientHttpResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* <p>Title : BufferedClientHttpResponse</p>
* <p>Description : BufferedClientHttpResponse</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/25 10:24
*/
@AllArgsConstructor
public class BufferedClientHttpResponse implements ClientHttpResponse {
private final ClientHttpResponse original;
private final byte[] body;
@NonNull
@Override
public InputStream getBody() {
// 返回新的 ByteArrayInputStream,可以重复读取
return new ByteArrayInputStream(body);
}
@NonNull
@Override
public HttpHeaders getHeaders() {
return original.getHeaders();
}
@NonNull
@Override
public HttpStatusCode getStatusCode() throws IOException {
return original.getStatusCode();
}
@NonNull
@Override
public String getStatusText() throws IOException {
return original.getStatusText();
}
@Override
public void close() {
original.close();
}
}

View File

@@ -0,0 +1,27 @@
package xtools.cloud.call.interceptor;
import org.jspecify.annotations.NonNull;
import org.springframework.http.HttpRequest;
/**
* <p>Title : CallInterceptor</p>
* <p>Description : CallInterceptor</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/27 14:13
*/
public interface CallInterceptor {
/**
* 请求之前
*
* @param request 请求
*/
default void before(@NonNull HttpRequest request) {
}
}

View File

@@ -0,0 +1,100 @@
package xtools.cloud.call.interceptor;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jspecify.annotations.NonNull;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;
import xtools.boot.api.constant.BootCommonConstant;
import xtools.boot.api.model.dto.log.LogTrack;
import xtools.boot.log.LogBus;
import xtools.boot.log.enums.LogBusBaseType;
import xtools.boot.log.holder.LogTrackHolder;
import xtools.core.enums.LogLevel;
import java.io.IOException;
import java.util.Objects;
/**
* <p>Title : ClientHttpInterceptor</p>
* <p>Description : ClientHttpInterceptor</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/2/26 15:37
*/
@Slf4j
public class ClientHttpInterceptor implements ClientHttpRequestInterceptor {
@Resource
private CallInterceptor callInterceptor;
/**
* 拦截请求
*
* @param request 请求
* @param body 请求体
* @param execution 执行器
* @return 响应
* @throws IOException 异常
*/
@Override
@NonNull
public ClientHttpResponse intercept(
@NonNull HttpRequest request,
byte @NonNull [] body,
@NonNull ClientHttpRequestExecution execution
) throws IOException {
// 请求前执行
if (Objects.nonNull(callInterceptor)) {
callInterceptor.before(request);
}
// 获取请求头信息
HttpHeaders headers = request.getHeaders();
// 获取日志追踪信息
LogTrack logTrack = LogTrackHolder.get();
// 添加日志追踪信息
headers.add(BootCommonConstant.LOG_TRACK, LogTrackHolder.getBase64(logTrack));
// 添加微服务请求标识
headers.add(BootCommonConstant.CLOUD, String.valueOf(true));
// 创建请求日志
JSONObject reqLog = new JSONObject();
reqLog.put("uri", request.getURI());
reqLog.put(BootCommonConstant.UID, headers.get(BootCommonConstant.UID));
reqLog.put(BootCommonConstant.AUTHORIZATION, headers.get(BootCommonConstant.AUTHORIZATION));
reqLog.put("method", request.getMethod().name());
reqLog.put("body", new String(body));
LogBus.init(LogLevel.INFO, LogBusBaseType.CLOUD_REQUEST, logTrack).data(reqLog).save();
// 执行请求
long startTime = System.currentTimeMillis();
ClientHttpResponse originalResponse = execution.execute(request, body);
long execTime = System.currentTimeMillis() - startTime;
// 读取响应体
byte[] responseBody = StreamUtils.copyToByteArray(originalResponse.getBody());
String respBody = new String(responseBody);
// 创建响应日志
JSONObject respLog = new JSONObject();
respLog.put("execTime", execTime);
respLog.put("statusCode", originalResponse.getStatusCode());
respLog.put("body", JSON.isValid(respBody) ? JSON.parseObject(respBody) : respBody);
LogBus.init(LogBusBaseType.CLOUD_RESPONSE).data(respLog).save();
// 返回响应
return new BufferedClientHttpResponse(originalResponse, responseBody);
}
}

View File

@@ -0,0 +1,36 @@
package xtools.cloud.call.selector;
import org.jspecify.annotations.NonNull;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* <p>Title : CloudClientImportSelector</p>
* <p>Description : CloudClientImportSelector</p>
* <p>DevelopTools : Idea_x64_v2026.1</p>
* <p>DevelopSystem : macOS Sequoia 15.7.5</p>
* <p>Company : org.xujun</p>
*
* @author : XuJun
* @version : 5.0.0
* @date : 2026/01/01 09:30
*/
public class CloudClientImportSelector implements ImportBeanDefinitionRegistrar {
/**
* 根据给定的注释元数据,根据需要注册bean
*
* @param importingClassMetadata AnnotationMetadata
* @param registry BeanDefinitionRegistry
*/
@Override
public void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMetadata, @NonNull BeanDefinitionRegistry registry) {
// 构建扫描对象
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, true);
// 扫描包下路径
scanner.scan("xtools.cloud.call");
}
}

View File

@@ -0,0 +1 @@
xtools.cloud.call.CloudClientConfiguration