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
相关产品推荐
相关产品推荐

