Feign Client调用直接传递new实例报错咨询:是否需提前创建对象及解决方法
咱们先把问题的核心搞清楚:你直接传new ProcessDto()时触发的报错,本质是Feign对@RequestParam修饰的复杂对象的默认处理逻辑导致的。
Feign默认会把@RequestParam的非简单类型参数(比如你的ProcessDto)转换成字符串——也就是调用对象的toString()方法,得到的结果就是你报错里看到的ProcessDto(id=null, system=null)。但服务端期望的是能反序列化成ProcessDto的标准JSON字符串,自然就出现了解析失败的问题。
而提前创建好对象再传递时,Feign的序列化机制会正确识别这是需要序列化的复杂对象;传null时则直接跳过该参数的处理,所以这两种情况都能正常运行。
1. 配置Feign使用SpringFormEncoder(推荐方案)
通过自定义Feign的编码器,让它把@RequestParam的复杂对象参数序列化为合法的JSON字符串,这样服务端就能正确解析了。
步骤1:添加依赖(如果还没引入)
如果你用Maven,在pom.xml里加这个依赖:
<dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form-spring</artifactId> <version>适配你Spring Cloud版本的号</version> </dependency>
步骤2:创建Feign配置类
@Configuration public class CustomFeignConfig { @Bean public Encoder feignEncoder() { // 用SpringFormEncoder搭配JacksonEncoder,实现复杂对象的JSON序列化 return new SpringFormEncoder(new JacksonEncoder()); } }
步骤3:给Feign Client指定配置
在你的FileResource接口上加上配置类:
@FeignClient(name = "你的服务名", configuration = CustomFeignConfig.class) @Api(value = "Operations with files") @RequestMapping("files") public interface FileResource { // 你的createFile方法保持不变 }
配置完成后,不管你是直接传new ProcessDto()还是提前创建的对象,Feign都会把它序列化为标准的JSON(比如{"id":null,"system":null}),服务端就能顺利反序列化为ProcessDto了。
2. 改用@RequestBody传递复杂对象(替代方案)
如果你的接口设计允许调整,也可以把ProcessDto的参数注解从@RequestParam改成@RequestBody——不过这会改变请求的参数传递方式,需要服务端的接口也同步修改:
@PostMapping(value = "createFile") @ResponseStatus(HttpStatus.CREATED) @ResponseBody FileDto createFile( @RequestParam("file") FileDto file, @RequestBody(required = false) ProcessDto process, @RequestParam(value = "new", defaultValue = "true") boolean new );
这种方式下,Feign会自动把ProcessDto序列化为JSON放在请求体里,不管是直接new还是提前创建的对象都能正常传递,但要注意和服务端的接口保持一致。
3. 手动序列化(临时应急方案,不推荐)
如果只是临时需要快速解决,也可以手动把new ProcessDto()序列化为JSON字符串再传递,但这种方式繁琐且不易维护:
ObjectMapper objectMapper = new ObjectMapper(); try { String processJson = objectMapper.writeValueAsString(new ProcessDto()); feignClient.createFile(file, objectMapper.readValue(processJson, ProcessDto.class), true); } catch (JsonProcessingException e) { // 处理序列化异常 }
显然第一种配置编码器的方式是最优雅、最适合长期维护的方案。
内容的提问来源于stack exchange,提问作者Evgenia Rubanova

