Feign常见的坑总结

来源:互联网 发布:iprint打印监控软件 编辑:程序博客网 时间:2024/06/06 09:22

1.feign返回参数为map遇到的问题

spring cloud服务之间通过restApi相互调用的时候,如服务A调用服务B

         服务B的controller如下,返回一个Map,其中

userAllMessage.getPoints()的类型为Bigdecimal

@RequestMapping("/sec/getPoints")public ResponseEntity< Map<String, Object>> getPoints() {    Map<String, Object> map = new HashMap<>();    UserAllMessage userAllMessage = userService.getUserById(RequestUtil.getUserId());    if (userAllMessage != null) {        map.put("state", 0);        map.put("points", userAllMessage.getPoints());    } else {        map.put("state", 1);    }    return new ResponseEntity<>(map, HttpStatus.OK);}

服务A的的Feign接收为

@FeignClient(name = "user-server")@Componentpublic interface UserFeignServiceClient {    @RequestMapping(value = "/api/user/sec/getPoints",method = RequestMethod.POST)    Map<String, Object> getPoints();}


调用该feignClient的代码为

Map<String, Object> map = userFeignServiceClient.getPoints();Double points = (Double) map.get("points");

代码

Double points = (Double) map.get("points");
进行类型强转  会抛出类型转化异常:不能将Integer类型转化为double类型


解决办法:方法1,将服务B中points类型BigDicmal转化为Double类型

                    方法2,将服务B中返回类型map该为一个实体entity类型,该实体包含两个属性state和points(其中points类型为BigDicmal)

以上方法测试可用


2.feign传递参数遇到的问题

@RequestMapping(value = "/api/user/getInvitation",method = RequestMethod.GET) List<Invitation> getInvitation(@RequestParam Long id);


在以前spring使用中@RequestParam不需要指定value值,@RequestMapping也可以直接指定为PostMapping或者GetMapping,在feign中必须指定value值,必须通过method=RequestMethod.GET(POST)的方式进行指定,拥有多个参数的时候可以通过(@RequestParam("id")Long id,@RequestParam("userId")Long userId的形式调用

猜想:拥有多个参数为什么不通过map来调用呢,于是尝试Map调用   A服务为消费者    B服务为服务提供者

A 的部分代码

/** * 测试看看 */@RequestMapping("/test")public Map<String, Object> test() throws Exception {    Map<String,Object> map=new HashMap<>();    map.put("test1",new Integer(2));    map.put("test2",new Double(2));    map.put("test3",new BigDecimal(2));    workerFeignServiceClient.test(map);    return map;}

feign的部分代码

@FeignClient("worker-server")public interface WorkerFeignServiceClient {    @RequestMapping(value = "/api/worker/feign/test", method = RequestMethod.GET)    Worker test(Map<String,Object> map);}


B 的部分代码

@GetMapping("/test")public ResponseEntity<Map> test(Map<String,Object> map) {    int test1=(int) map.get("test1");    int test2=(Integer) map.get("test1");    double test5=(double) map.get("test2");    Integer test6=(Integer)map.get("test3");    double test3=(double) map.get("test3");    Double test4=(Double) map.get("test3");    return new ResponseEntity<>(map, HttpStatus.OK);}
启动调用:报错了

Caused by: feign.FeignException: status 405 reading WorkerFeignServiceClient#test(Map); content:
{"timestamp":1506147245404,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/api/worker/feign/test"}

报错的意思是不支持GET提交,好的修改提交方式为POST

@FeignClient("worker-server")public interface WorkerFeignServiceClient {    @RequestMapping(value = "/api/worker/feign/test", method = RequestMethod.POST)    Worker test(Map<String,Object> map);}

@PostMapping("/test")public ResponseEntity<Map> test(@RequestBody Map<String,Object> map) {    int test1=(int) map.get("test1");    int test2=(Integer) map.get("test1");    double test5=(double) map.get("test2");    Integer test6=(Integer)map.get("test3");    double test3=(double) map.get("test3");    Double test4=(Double) map.get("test3");    return new ResponseEntity<>(map, HttpStatus.OK);}


启动执行:java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double,错误发生位置为

double test3=(double) map.get("test3");

Integer test6=(Integer)map.get("test3");
正确


将map的传入参数test2改为以下,其他位置不变

map.put("test2",new Double(2.6555));

启动执行:java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer,错误发生位置为

Integer test6=(Integer)map.get("test3");
从上可以看出当参数为BigDicmal时,存在不稳定性,最好不要传递BigDicmal,如果非要传,应该将BigDicmal放在一个entity对象里面传递,避免放在map里面




调用已经进入到B服务中,之所以出错


持续更新中


原创粉丝点击