Feign调用时ResponseEntity反序列化失败问题求助
Feign调用接口时ResponseEntity反序列化失败
错误信息
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.http.ResponseEntity` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (BufferedReader); line: 1, column: 2]
相关代码
控制器端点
@RestController @RequestMapping(Routes.URI_PREFIX) public class CartoController { @Autowired private ReadCartographyApiDelegate readCartographyApiDelegate; @GetMapping(value = "/cartographies/{uid}", produces = {MediaType.APPLICATION_JSON_VALUE}) public ResponseWrapper<ReadCartographyResponse> readCarto(HttpServletRequest request, @PathVariable(name = "uid") String uid) { ResponseEntity<ReadCartographyResponse> result ; try { result = readCartographyApiDelegate.readCartography(uid); }catch (Exception e){ throw new TechnicalException("Error during read Carto"); } return responseWrapperWithIdBuilder.of(result.getBody()); } }
OpenAPI自动生成的ReadCartographyApiDelegate接口
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "...") public interface ReadCartographyApiDelegate { default Optional<NativeWebRequest> getRequest() { return Optional.empty(); } default ResponseEntity<ReadCartographyResponse> readCartography(String uid) { getRequest().ifPresent(request -> { for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) { if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) { String exampleString = "null"; ApiUtil.setExampleResponse(request, "application/json", exampleString); break; } } }); return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } }
实现类ReadCartographyApiDelegateImpl
@Service public class ReadCartographyApiDelegateImpl implements ReadCartographyApiDelegate { private EcomGtmClient ecomGtmClient; public ReadCartographyApiDelegateImpl(EcomGtmClient ecomGtmClient) { this.ecomGtmClient = ecomGtmClient; } @Override public ResponseEntity<ReadCartographyResponse> readCartography(String uid) { ResponseEntity<ReadCartographyResponse> response = ecomGtmClient.readCartography(uid); return response; } }
Feign客户端EcomGtmClient
@FeignClient(name = "ecomGtmSvc", url = "http://localhost/") public interface EcomGtmClient { @GetMapping(value = "/read-carto/{uid}") ResponseEntity<ReadCartographyResponse> readCartography(@PathVariable("uid") String uid); }
问题分析
已知问题在于Spring的ResponseEntity类没有默认构造方法,导致Jackson反序列化时无法创建实例。
解决方案
方案1:直接返回业务对象(推荐)
Feign本身会自动处理HTTP响应的状态码,无需用ResponseEntity包裹返回结果。修改Feign客户端的返回类型为业务对象ReadCartographyResponse,再在实现类中手动封装成ResponseEntity:
修改EcomGtmClient:
@FeignClient(name = "ecomGtmSvc", url = "http://localhost/") public interface EcomGtmClient { @GetMapping(value = "/read-carto/{uid}") ReadCartographyResponse readCartography(@PathVariable("uid") String uid); }
修改ReadCartographyApiDelegateImpl:
@Override public ResponseEntity<ReadCartographyResponse> readCartography(String uid) { ReadCartographyResponse responseBody = ecomGtmClient.readCartography(uid); return ResponseEntity.ok(responseBody); }
方案2:配置Jackson支持ResponseEntity反序列化
通过注册Spring提供的Jackson模块,让Jackson能够正确序列化/反序列化ResponseEntity:
创建Feign配置类,自定义Decoder并注册SpringModule:
@Configuration public class FeignConfig { @Bean public Decoder feignDecoder(ObjectMapper objectMapper) { objectMapper.registerModule(new SpringModule()); return new JacksonDecoder(objectMapper); } }
在Feign客户端上指定该配置:
@FeignClient(name = "ecomGtmSvc", url = "http://localhost/", configuration = FeignConfig.class) public interface EcomGtmClient { @GetMapping(value = "/read-carto/{uid}") ResponseEntity<ReadCartographyResponse> readCartography(@PathVariable("uid") String uid); }
注意:确保项目依赖了spring-web模块,SpringModule包含在该模块中。
内容的提问来源于stack exchange,提问作者Wijdane KHATTAT
相关产品推荐
相关产品推荐

