上一节是是使用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只有一个参数,然后在现实中,我们往往有很多的参数,如果还使用这种方式,那么就会变的很低效。并且难为维护。
在springcloud中,使用feign非常简单,创建一个接口,并在接口上添加一些注解,代码就完成了,feign支持多种注解。Springcloud对feign进行了强化,是feign支持了springmvc注解,并整合了Ribbon和eureka,从而让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的自定义配置同样支持java代码跟属性配置。
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