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

Spring Boot Starter Batch中配置RestItemWriter实现Patch请求

实现支持Patch请求的Spring Batch RestItemWriter方案

一、解决RestTemplate发起Patch请求的问题

RestTemplate本身没有提供直接的patch方法,但可以通过exchange方法指定HttpMethod.PATCH来实现,同时确保消息转换器支持请求体的序列化。

1. 配置支持Patch的RestTemplate(含连接池优化,适配8万+记录场景)

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate patchRestTemplate() {
        // 配置HTTP连接池,避免频繁创建连接
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setMaxConnTotal(100)    // 最大总连接数
                .setMaxConnPerRoute(20)   // 单路由最大连接数
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        requestFactory.setConnectTimeout(5000);  // 连接超时
        requestFactory.setReadTimeout(10000);    // 读取超时

        RestTemplate restTemplate = new RestTemplate(requestFactory);
        
        // 配置JSON消息转换器,确保请求体正确序列化
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(new ObjectMapper().registerModule(new JavaTimeModule()));
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
        
        restTemplate.getMessageConverters().add(converter);
        return restTemplate;
    }
}

2. 发送单条Patch请求的核心代码

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<YourRecord> requestEntity = new HttpEntity<>(processedItem, headers);

// 发起Patch请求
ResponseEntity<Void> response = restTemplate.exchange(
        "http://your-target-api/patch/{id}",  // 假设接口带ID路径参数
        HttpMethod.PATCH,
        requestEntity,
        Void.class,
        processedItem.getId()  // 路径参数值
);

// 校验响应状态,非2xx则抛出异常触发Batch重试/跳过逻辑
if (!response.getStatusCode().is2xxSuccessful()) {
    throw new ItemWriteException(String.format("Patch失败,ID: %d,状态码: %s", processedItem.getId(), response.getStatusCode()));
}

二、实现自定义PatchRestItemWriter

直接实现Spring Batch的ItemWriter接口,根据目标API支持情况选择单条Patch或批量Patch模式:

1. 单条Patch模式(适配不支持批量的API)

public class PatchRestItemWriter<T> implements ItemWriter<T> {

    private final RestTemplate restTemplate;
    private final String patchUrl;

    public PatchRestItemWriter(RestTemplate restTemplate, String patchUrl) {
        this.restTemplate = restTemplate;
        this.patchUrl = patchUrl;
    }

    @Override
    public void write(List<? extends T> items) throws Exception {
        // 遍历处理每个Item
        for (T item : items) {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<T> requestEntity = new HttpEntity<>(item, headers);

            ResponseEntity<Void> response = restTemplate.exchange(
                    patchUrl,
                    HttpMethod.PATCH,
                    requestEntity,
                    Void.class,
                    ((YourRecord) item).getId()  // 替换为你的实体ID字段
            );

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new ItemWriteException("Patch item failed: " + item.toString());
            }
        }
    }
}

2. 批量Patch模式(适配支持批量更新的API,大幅提升性能)

如果目标API支持接收批量更新请求,可修改Writer为批量发送:

@Override
public void write(List<? extends T> items) throws Exception {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<List<? extends T>> requestEntity = new HttpEntity<>(items, headers);

    ResponseEntity<Void> response = restTemplate.exchange(
            "http://your-target-api/batch-patch",
            HttpMethod.PATCH,
            requestEntity,
            Void.class
    );

    if (!response.getStatusCode().is2xxSuccessful()) {
        throw new ItemWriteException("Batch patch failed, status code: " + response.getStatusCode());
    }
}

三、在Batch Job中配置Writer

将自定义Writer注入Step,同时配置合适的chunk大小(建议100-500,根据API性能调整):

@Bean
public Step dataMigrationStep(FlatFileReader<YourRecord> flatFileReader,
                              YourItemProcessor itemProcessor,
                              PatchRestItemWriter<YourRecord> patchRestItemWriter) {
    return stepBuilderFactory.get("dataMigrationStep")
            .<YourRecord, YourRecord>chunk(200)  // Chunk大小根据实际性能调整
            .reader(flatFileReader)
            .processor(itemProcessor)
            .writer(patchRestItemWriter)
            .faultTolerant()  // 开启容错机制
            .retry(HttpClientErrorException.class)  // 重试网络异常
            .retryLimit(3)  // 最大重试次数
            .skip(ItemWriteException.class)  // 跳过无法修复的写入失败
            .skipLimit(10)  // 最大跳过次数
            .build();
}

@Bean
public PatchRestItemWriter<YourRecord> patchRestItemWriter(RestTemplate patchRestTemplate) {
    return new PatchRestItemWriter<>(patchRestTemplate, "http://your-target-api/patch/{id}");
}

内容的提问来源于stack exchange,提问作者Theri Muthu Selvam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 02:06:01