SpringCloud实战5 - 使用Feign实现声明式rest调用

xiaoxiao2025-05-01  12

   上一节是是使用RestTemplate实现REST API调用的,大致代码如下:

   

@RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello(@RequestParam String name) { ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://provider/hello?name={1}", String.class,name); return responseEntity.getBody(); }

   由代码可知,我们是使用拼接字符串的方式构造url的,改url只有一个参数,然后在现实中,我们往往有很多的参数,如果还使用这种方式,那么就会变的很低效。并且难为维护。

   Feign简介   

   在springcloud中,使用feign非常简单,创建一个接口,并在接口上添加一些注解,代码就完成了,feign支持多种注解。Springcloud对feign进行了强化,是feign支持了springmvc注解,并整合了Ribbon和eureka,从而让feign的使用更方便。

   为服务消费者整合Feign

      创建一个子模块,在子模块的pom.xml里添加如下依赖:

   

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>

   创建一个feign接口,并添加@FeignClient注解   

@FeignClient(name = "provider") public interface TestFeignClient { @RequestMapping(value = "/hello", method = RequestMethod.GET) String hello(@RequestParam("name") String name); }

   @FeignClient注解中的provider是一个任意的客户端的名称,用于创建Ribbon负载均衡。

   创建controller代码

@RestController @RequestMapping(value = "feign") public class HelloController { @Autowired TestFeignClient testFeignClient; @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping(value = "/hello") public String hello(@RequestParam String name) { String str = testFeignClient.hello(name); return str; } @GetMapping("/log-user-instance") public void logUserInstance() { ServiceInstance serviceInstance = this.loadBalancerClient.choose("provider"); // 打印当前选择的是哪个节点 System.out.println("{}:{}:{}," + serviceInstance.getServiceId()+","+ serviceInstance.getHost()+","+ serviceInstance.getPort()); } }

 添加启动类代码:

@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients //注解表示开启Spring Cloud Feign的支持功能 public class YmkFeignConsumerApplication { public static void main(String[] args) { SpringApplication.run(YmkFeignConsumerApplication.class, args); } }

   以此启动服务,多次访问:http://localhost:8010/feign/hello?name=feign 返回结果如下

   

   看下提供者服务器其控制台打印结果,已经实现了负载均衡。

  

    扩展阅读:feign传递多参数  https://www.jianshu.com/p/7ce46c0ebe9d 

   自定义配置Feign

       feign的自定义配置同样支持java代码跟属性配置。

    Feign对继承的支持

    Feign支持继承,使用继承,可将一些公共的操作分组到一些父接口中,从而简化Feign的开发,下面展示了简单的例子。

   在api接口项目中,创建一个接口

public interface TestService { @RequestMapping(value = "/hello2", method = RequestMethod.GET) String hello(@RequestParam("name") String name); }

   在服务提供者中实现接口

@RestController public class TestController2 implements TestService { @RequestMapping(value = "/hello2", method = RequestMethod.GET) public String hello(String name) { System.out.println("Hello2 "+name); return "Hello2 "+name; } }

服务消费者中,新建一个接口并继承api中的接口

@FeignClient(name = "provider") public interface TestFeignClient2 extends TestService { }

 创建一个新的controller,用此接口即可

  

@RestController @RequestMapping(value = "feign2") public class HelloController2 { @Autowired TestFeignClient2 testFeignClient2; @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping(value = "/hello2") public String hello(@RequestParam String name) { String str = testFeignClient2.hello(name); return str; } @GetMapping("/log-user-instance2") public void logUserInstance() { ServiceInstance serviceInstance = this.loadBalancerClient.choose("provider"); // 打印当前选择的是哪个节点 System.out.println("{}:{}:{}," + serviceInstance.getServiceId()+","+ serviceInstance.getHost()+","+ serviceInstance.getPort()); } }

   在启动类添加接口路径,防止出现接口无法注入的问题。

@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients("com.yang.test.ymkfeignconsumer.feign") //注解表示开启Spring Cloud Feign的支持功能,指定接口路径,防止出现无法注入的问题 public class YmkFeignConsumerApplication { public static void main(String[] args) { SpringApplication.run(YmkFeignConsumerApplication.class, args); } }

   依次启动服务,访问 :http://localhost:8010/feign2/hello2?name=feign2 

    

   注意: 尽管Feign的继承可帮助我们进一步简化Feign的开发,但SpringCloud官方并不建议在提供者跟消费者之间共享接口。因为这种方式造成了提供者跟消费者之间的紧耦合。

   秉承这种思想:将我们的项目重新划分了一下,除了继承的接口在api项目中,其他的接口放在消费者端。具体见博客底部的源码!

   配置日志级别

   很多场景下,需要了解feign的具体细节,Feign对日志的处理非常灵活,可以为每个feign客户端指定日记记录策略。

   我们可以为每个Feign客户度配置各自的logger.Level对象。

   NONE 不输出日志

   BASIC 只有请求方法、URL、响应状态代码、执行时间

   HEADERS基本信息以及请求和响应头

   FULL 请求和响应 的heads、body、metadata,建议使用这个级别。

   创建一个配置类,此类一定要让spring可以扫描到

@Configuration public class FeignLogConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }

   修改feign接口,指定配置类

@FeignClient(name = "provider" ,configuration = FeignLogConfiguration.class) public interface TestFeignClient { @RequestMapping(value = "/hello", method = RequestMethod.GET) String hello(@RequestParam("name") String name); }

修改application.yml文件

logging: level: com.yang.test.ymkfeignconsumer.feign.TestFeignClient: debug # 将Feign接口的日志级别设置成DEBUG,因为Feign的Logger.Level只对DEBUG作出响应。

一次启动项目,访问: http://localhost:8010/feign/hello?name=feign

      

日志打印成功。

 

源码下载 :  https://download.csdn.net/download/u013083284/10755394

转载请注明原文地址: https://www.6miu.com/read-5029560.html

最新回复(0)