标签 WebClient 下的文章

这里好像没有讨论 java 技术的 继续讨论。
在前段时间公司要自己搞个电商平台,首选开发语言用 java, 架子用 springboot,我作为研发负责人。
在立项初期我准备上 cloud, 但是老板没同意,说后面再迭代,我因为刚来这家公司我也就没好说什么,单体就单体呗。
在后面的开发过程中产品提出要增加一个供应商服务端,两端会有频繁的数据交互,我思考了半天有几个方案,要么是谷歌的 grpc, 要么是阿里的 dubbo, 或者是 openfeign, 不过 grpc 要写 protobuf,dubbo 以前用的 2.8 版本遇到兼容性问题现在好多年不用而且时间给的少我怕来不及,openfeign 又没脱离 cloud 依赖,需要引入一堆 maven 依赖,思来想去总不能直接 http 吧,这不胶水架构了么。
最后吧,还是用了胶水架构,不过是好用一点的,这就是 HTTP Interface 啦,因为当时是我负责搭建架子的,所以我采用了基于 jdk17 的 boot3.5, 正好是基于 Spring Framework 6 的。
这个东西用起来门槛非常低,只需要一个配置:

@Configuration @RequiredArgsConstructor @Slf4j public class HttpInterfaceConfig {

    private final TenantPropagator tenantPropagator;

    @Value("${service.auth.secret-key}") private String secretKey;

    private WebClient.Builder createWebClientBuilder(String baseUrl) {
        return WebClient.builder()
                .baseUrl(baseUrl)
                .filter(this::addAuthHeaders) // 添加认证过滤器
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    }

    /**
* 为每次请求动态添加认证头
*/
private Mono<ClientResponse> addAuthHeaders(ClientRequest request, ExchangeFunction next) { // 每次请求时动态生成时间戳、随机数和签名 long timestamp = System.currentTimeMillis(); String nonce = UUID.randomUUID().toString().replace("-", "").substring(0, 16); String signature = HmacSignUtils.generateTimestampSignature(timestamp, nonce, secretKey); log.debug("🔐 动态生成认证头 - timestamp: {}, nonce: {}, signature: {}", timestamp, nonce, signature); // 创建新的请求,添加认证头 ClientRequest newRequest = ClientRequest.from(request) .header("X-Internal-Service", "true") .header("X-Service-Timestamp", String.valueOf(timestamp)) .header("X-Service-Nonce", nonce) .header("X-Service-Signature", signature) .build(); return next.exchange(newRequest); } @Bean public OperationPlatFormApiClient operationPlatformApiClient(
@Value("${service.operationPlatform.url}") String baseUrl)
{ log.info("=== operationPlatformApiClient 配置信息 ==="); log.info("baseUrl: {}", baseUrl); log.info("secretKey: {}", secretKey != null ? "已配置" : "未配置"); // 创建基础的 WebClient Builder WebClient.Builder webClientBuilder = createWebClientBuilder(baseUrl); // 传播租户信息 webClientBuilder = tenantPropagator.propagateTenant(webClientBuilder); WebClient webClient = webClientBuilder.build(); WebClientAdapter adapter = WebClientAdapter.create(webClient); HttpServiceProxyFactory factory = HttpServiceProxyFactory .builderFor(adapter) .build(); OperationPlatFormApiClient client = factory.createClient(OperationPlatFormApiClient.class); log.info("✅ operationPlatformApiClient 创建成功"); return client; } @Bean public SupplierApiClient supplierApiClient(
@Value("${service.supplier.url}") String baseUrl)
{ log.info("=== SupplierApiClient 配置信息 ==="); log.info("baseUrl: {}", baseUrl); log.info("secretKey: {}", secretKey != null ? "已配置" : "未配置"); // 创建基础的 WebClient Builder WebClient.Builder webClientBuilder = createWebClientBuilder(baseUrl); // 传播租户信息 webClientBuilder = tenantPropagator.propagateTenant(webClientBuilder); WebClient webClient = webClientBuilder.build(); WebClientAdapter adapter = WebClientAdapter.create(webClient); HttpServiceProxyFactory factory = HttpServiceProxyFactory .builderFor(adapter) .build(); SupplierApiClient client = factory.createClient(SupplierApiClient.class); log.info("✅ SupplierApiClient 创建成功"); return client; } @Bean public CrowdsourcingApiClient crowdsourcingApiClient(
@Value("${service.crowdsourcing.url}") String baseUrl)
{ log.info("=== CrowdsourcingApiClient 配置信息 ==="); log.info("baseUrl: {}", baseUrl); // 创建基础的 WebClient Builder WebClient.Builder webClientBuilder = createWebClientBuilder(baseUrl); // 传播租户信息 webClientBuilder = tenantPropagator.propagateTenant(webClientBuilder); WebClient webClient = webClientBuilder.build(); WebClientAdapter adapter = WebClientAdapter.create(webClient); return HttpServiceProxyFactory .builderFor(adapter) .build() .createClient(CrowdsourcingApiClient.class); } }

就可以了,然后就能像写 openfeign 那样:

@Resource private SupplierApiClient supplierApiClient;

@PostMapping("/createSupplier") @Operation(summary = "新增供应商用户") public Mono<CommonResult<Integer>> createSupplier(@Valid @RequestBody SuppLierUsersVO reqVO) {
    return ReactiveApiHandler.processReactive(supplierApiClient.createAccount(reqVO), "创建供应商账户");
}

要使用它只需要有 spring-webflux 就可以了,好像是 Spring Framework 6 自带的。

ps:
这东西有个坑,就是你的客户端里的接口越多,启动的时候就越慢,所以一般推荐做个懒加载,不然你客户端写上百个接口,启动就要占用你一分钟的时间。


📌 转载信息
原作者:
furry
转载时间:
2026/1/6 11:59:34