SpringCloud(九)服务消费者Feign
什么是Feign:
- 声明式的伪Http客户端,使得写http客户端变得简单
- 使用Feign只要创建一个接口并注解就好,有可插拔的注解特性,可使用Feign注解和JAX-RS注解
- 支持可插拔的编码器和解码器
- 整合了Ribbon,有负载均衡的能力
- 整合了Hystrix,有熔断能力
创建一个Feign模块:
<!--引入eureka、feign、web的start-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
很普通的注册,没别的了:
server: port: 8801 #注册到eureka的服务器名称 spring: application: name: nohairLoss-feign-client #服务注册到eureka地址 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
启动类,加三个注解,springboot的启动类,注册到eureka,feign的客户端。
@SpringBootApplication @EnableEurekaClient @EnableFeignClients public class ServerFeignApplication { public static void main(String[] args){ SpringApplication.run(ServerFeignApplication.class,args); } }
写service:
就是用@RequestParam不行,用@PathVariable要加上value属性
//加此注解表示我要调用,注册到eureka里面的哪个服务,里面写服务名 @FeignClient("noHairLoss-eurake-user") public interface UserService { /** * 注解中指定要调用哪个接口,参数正常写就好。 * @param emoji * @return */ @RequestMapping(value="/user/judgeEmoji/{emoji}",method = RequestMethod.GET) public Object judgeEmoji(@PathVariable(value = "emoji")String emoji); }
{"timestamp":1563514519913,"status":404,"error":"Not Found","message":"No message available","path":"/detail"}] with root cause
@RestController public class UserController { @Autowired UserService userService; @RequestMapping("/testFeign/{emoji}") public Object testFeign(@PathVariable String emoji){ return userService.judgeEmoji(emoji); } @RequestMapping(value="/detail",method = RequestMethod.GET) public User getUser(){ return userService.getUser(); } @RequestMapping(value = "/detailGet",method = RequestMethod.GET) public User getMapperUser(){ return userService.getMapperUser(); } @RequestMapping(value = "/doubleCatch",method = RequestMethod.GET) public Object doubleCatch(){ return userService.doubleCatch(); } } //加此注解表示我要调用,注册到eureka里面的哪个服务,里面写服务名 @FeignClient("noHairLoss-eurake-user") public interface UserService { /** * 注解中指定要调用哪个接口,参数正常写就好。 * @param emoji * @return */ @RequestMapping(value="/user/judgeEmoji/{emoji}",method = RequestMethod.GET) public Object judgeEmoji(@PathVariable(value = "emoji")String emoji); @RequestMapping(value="/detail",method = RequestMethod.GET) public User getUser(); @RequestMapping(value = "/detail",method = RequestMethod.GET) public User getMapperUser(); @RequestMapping(value = "/doubleCatch",method = RequestMethod.GET) public Object doubleCatch(); }
这个问题解决了。顺便还规范了一下我的编码。
先说一下问题原因是:
代码主要规范了如下几个地方:
1.原来@FeignClient修饰的接口不是个Service接口,是单独的一个专门放Feign调用的接口。。。所以抽取出来了
2.写了个FeignConfig,里面有个Retryer,如果Feign调用失败,会重试。。
3.修复了另外一个bug。。之前noHairLoss-eurake-user里面有两个请求返回的是Object类型。。。然后我Feign调用的时候报错:
3.1报错信息是:no suitable HttpMessageConverter found for response type [class java.lang.Object
3.2是Feign接受报错,无法httpMessage 无法转换Object,默认是JacksonHttpMessageConvert,Object 它肯定装不了,feign 底层还是httpClient 只是用注解声明而已
3.3所以把返回值改成String就好了。。。noHairLoss-eurake-user和FeignClient的返回值
@Configuration public class FeignConfig { /* 注入一个名为feignRetryer的Retryer的bean,Feign在远程调用失败后会进行重试 */ @Bean public Retryer feignRetryer(){ return new Retryer.Default(100,SECONDS.toMillis(1),5); } } //加此注解表示我要调用,注册到eureka里面的哪个服务,里面写服务名 @FeignClient(value = "noHairLoss-eurake-user") public interface UserClientFeign { /** * 注解中指定要调用哪个接口 * @param emoji * @return */ @RequestMapping(value="/user/judgeEmoji/{emoji}",method = RequestMethod.GET) public String judgeEmoji(@PathVariable(value = "emoji") String emoji); @RequestMapping(value="/user/detail",method = RequestMethod.GET) public User getUser(); @RequestMapping(value = "/user/detail",method = RequestMethod.GET) public User getMapperUser(); @RequestMapping(value = "/exception/doubleCatch",method = RequestMethod.GET) public String doubleCatch(); } //加此注解表示我要调用,注册到eureka里面的哪个服务,里面写服务名 @Service public class UserService { @Autowired UserClientFeign userClientFeign; /** * 注解中指定要调用哪个接口,参数正常写就好。 * @param emoji * @return */ public String judgeEmoji(@PathVariable(value = "emoji")String emoji){ return userClientFeign.judgeEmoji(emoji); } public User getUser(){ return userClientFeign.getUser(); } public User getMapperUser(){ return userClientFeign.getMapperUser(); } public String doubleCatch(){ return userClientFeign.doubleCatch(); } }

浙公网安备 33010602011771号