欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

采坑日记之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来对数据进行对象构造从而曝出了此错误。简单的解决方案就是在消费方将具体泛型去掉即可解决
  在微服务开发过程中,在针对具体应用场景问题方面设计出高效的解决方案尤为重要,同时接口的数据传输和数据接收的一致性也挺关键的,也是最最基本的

相关标签: 异常 开坑日记