You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Spring Batch的StepExecution注入WebClient通用RestClient并传递执行上下文

解决方案

为什么直接注入StepExecution会失败?

StepExecution不是Spring IoC容器中的全局Bean,它是Spring Batch在执行Step时动态创建的上下文对象,仅在当前Step的执行周期内有效,所以无法通过@Autowired直接注入。必须通过Step执行时的回调(比如@BeforeStep)获取后,手动传递到需要使用的地方。

具体实现步骤

1. 修改ItemProcessor,传递ExecutionContext到ApiService

在Processor中,把通过@BeforeStep拿到的ExecutionContext,作为参数传给ApiService的调用方法:

class ItemProcessor implements ItemProcessor<String, String> {
    @Autowired
    private ApiService apiService;
    private ExecutionContext stepExecutionContext;

    @BeforeStep
    public void saveStepExecution(StepExecution stepExecution) {
        this.stepExecutionContext = stepExecution.getExecutionContext();
    }

    @Override
    public String process(String id) throws Exception {
        // 调用时传入ExecutionContext
        apiService.getApiResponse(stepExecutionContext).block();
        // 后续业务逻辑
        return id;
    }
}

2. 调整ApiService,转发ExecutionContext到RestClient

修改ApiService的方法签名,接收ExecutionContext并传递给RestClient的execute方法:

public class ApiService {
    private final RestClient<ApiResponse> restClient;

    // 推荐用构造函数注入替代字段注入
    public ApiService(RestClient<ApiResponse> restClient) {
        this.restClient = restClient;
    }

    public Mono<ApiResponse> getApiResponse(ExecutionContext executionContext) {
        return restClient.execute(ApiResponse.class, executionContext);
    }
}

3. 更新RestClient,在错误处理中操作ExecutionContext

修改RestClient的execute方法,新增ExecutionContext参数,并在错误处理方法中使用它存储错误信息:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class RestClient<T> {
    private final WebClient webClient;
    private final Logger log = LoggerFactory.getLogger(RestClient.class);
    // 确保method和uri已通过构造函数或其他方式初始化
    private HttpMethod method;
    private String uri;

    public RestClient(WebClient webClient) {
        this.webClient = webClient;
    }

    public Mono<T> execute(Class<T> responseClass, ExecutionContext executionContext) {
        return webClient
                .method(method)
                .uri(uri)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, clientResponse -> handle4xxError(clientResponse, executionContext))
                .onStatus(HttpStatus::is5xxServerError, clientResponse -> handle5xxError(clientResponse, executionContext))
                .bodyToMono(responseClass);
    }

    private Mono<? extends Throwable> handle4xxError(ClientResponse clientResponse, ExecutionContext executionContext) {
        return clientResponse.bodyToMono(String.class)
                .flatMap(message -> {
                    String errorMsg = "4xx Error: 状态码=" + clientResponse.statusCode() + ", 响应内容=" + message;
                    log.error(errorMsg);
                    // 将错误信息存入ExecutionContext
                    executionContext.put("api_4xx_error", errorMsg);
                    return Mono.error(new ClientException(errorMsg));
                });
    }

    private Mono<? extends Throwable> handle5xxError(ClientResponse clientResponse, ExecutionContext executionContext) {
        return clientResponse.bodyToMono(String.class)
                .flatMap(message -> {
                    String errorMsg = "5xx Error: 状态码=" + clientResponse.statusCode() + ", 响应内容=" + message;
                    log.error(errorMsg);
                    executionContext.put("api_5xx_error", errorMsg);
                    return Mono.error(new ServerException(errorMsg));
                });
    }
}

补充说明

如果你的项目使用的是Spring Batch 4.3+的Reactive Step,也可以通过Reactor的Context来传递ExecutionContext,避免显式传参,但因为你当前用了block()同步调用WebClient的结果,手动传递参数是最直接且兼容的方式。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:22:47