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);
}

 

 遇到一个bug,controller和service的代码如下,错误信息是:

{"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();

}

 这个问题解决了。顺便还规范了一下我的编码。

先说一下问题原因是:

 我的controller上面还有一层请求路径。。在@FeignClient定义的接口的方法中要加上。。。。。。。。。。。。。。。。。
代码主要规范了如下几个地方:
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();
    }

}

 

posted @ 2019-07-13 14:35  TangXinPing  阅读(417)  评论(0)    收藏  举报