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") @Component public 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服务中,之所以出错
持续更新中