采坑日记之openfeign
程序员文章站
2022-04-15 18:09:20
...
感觉自己已经好久没写文章了哈哈哈哈,昨天下午踩到的一个坑,在今天早上得到了解决,很开心,但是开心的同时又清楚的认识到自己的不足之处,那就是自己在遇到以前很少遇到甚至是没遇到过的bug的时候,很难快速定位并将其解决。所以从今天开始会开设一个专题专门来记录自己的采坑经历。
先来简述下我的场景模拟:
我开了五个服务:两个Eureka服务注册中心(一个集群),两个服务提供方(一个集群),还有一个消费者。其中两个支付提供方注册进了服务注册中心。
而我踩到的是这么一个坑:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
[Request processing failed; nested exception is feign.codec.DecodeException:
Error while extracting response for type [com.hua.springcloud.entities.CommonResult<com.hua.springcloud.entities.Payment>]
and content type [application/json];
nested exception is org.springframework.http.converter.HttpMessageNotReadableException:
JSON parse error: Cannot construct instance of `com.hua.springcloud.entities.Payment`
(although at least one Creator exists): no String-argument constructor/factory method
to deserialize from String value ('8002Payment(id=1, serial=小华)');
nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot construct instance of `com.hua.springcloud.entities.Payment`
(although at least one Creator exists): no String-argument constructor/factory method
to deserialize from String value ('8002Payment(id=1, serial=小华)')
at [Source: (PushbackInputStream); line: 1, column: 92]
(through reference chain: com.hua.springcloud.entities.CommonResult["data"])] with root cause
其实在解决完问题之后想想其实道理蛮简单的,先来简单看下我的部分代码:
消费方:
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService
{
@GetMapping(value = "/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}
@RestController
public class OrderFeignController
{
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping(value = "/consumer/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id)
{
return paymentFeignService.getPaymentById(id);
}
}
服务提供方:
@RestController
public class PaymentController {
@Resource
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;//动态获取服务端口
@Resource //自动注入
private DiscoveryClient discoveryClient;
@GetMapping("/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
log.info("*****查询结果:"+payment);
if(payment!=null){
return new CommonResult(200,"查询成功,serverPort:",serverPort+payment);
}else {
return new CommonResult(444,"没有对应记录,查询ID:"+id,null);
}
}
}
到这里相信有微服务相关开发经历的大佬应该早就看出了问题所在,其实问题就在于:
服务提供方所提供的接口返回值累心是不指定具体泛型对象的CommonResult
,而我在消费者那边用来接收的类型自己指定了泛型对象CommonResult<Payment>
,由于前后这一个没有指定具体的泛型对象类型,一个有指定,前后不一致导致其采用的序列化、json与对象之间的转换得到的数据不太一样,从而在消费端想要接收数据的时候就报没法找到具体相应的construct来对数据进行对象构造从而曝出了此错误。简单的解决方案就是在消费方将具体泛型去掉即可解决
在微服务开发过程中,在针对具体应用场景问题方面设计出高效的解决方案尤为重要,同时接口的数据传输和数据接收的一致性也挺关键的,也是最最基本的。
上一篇: springboot 日常采坑
下一篇: 日常踩坑日记