初始化项目
This commit is contained in:
35
xtools-cloud-call/pom.xml
Normal file
35
xtools-cloud-call/pom.xml
Normal 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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
xtools.cloud.call.CloudClientConfiguration
|
||||
Reference in New Issue
Block a user