Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
通过上一章 SpringCloud Alibaba - Ribbon入门案例 我们可以明显的感受到,消费者在调用生产者的时候,我们需要额外的使用 restTemplate 进行调用,并且请求的参数也是需要写入,这样一来不仅代码可读性不好,并且编写的风格不统一。
现在,我们就用 fegin 来优化代码。
同样的,生产者不需要改变,只需修改消费者的配置。
在pom中添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.1.0.RELEASE</version> </dependency>启动类中添加注解,此注解用于声明启用Feign
@EnableFeignClients增加一个对应的调用生产者的接口
@FeignClient("test-scz") public interface NacosSCZService { @GetMapping(value = "/scz/testFunction") String testFunction(@RequestParam(value = "message") String message); } @FeignClient(“test-scz”) 注解中的值用于指定调用的生产者名称,对应的是 Nacos 上的服务名称@GetMapping(value = “/scz/testFunction”) 注解中value的值对应需要访问的地址接下来,我们就可以在本地注入我们新增加的接口,利用调用的方式去访问生产者了。
消费者 Controller
@Slf4j @RequestMapping("/xfz") @RestController public class TestController { @Autowired private NacosSCZService nacosSCZService; @RequestMapping("/testFunction") public void testFunction(String message){ log.info("消费者控制层的调用"); log.info("输出的参数为"+ message); String forMessage = nacosSCZService.testFunction(message); } }利用 idea 自带的 REST Client 进行测试 进行五次请求后查看生产者的调用信息。
两个服务生产者的调用次数分别为 两次/三次 总共五次,证明调用成功。
原因 :(初步排查)
此类编译时可用,而运行时在Java的classpath路径中,对应的类不可用导致的错误。
spring-cloud-starter-openfeign的spring-cloud-starter-netflix-archaius中没有CachedDynamicIntProperty这个类。 引入archaius-core的核心包,注意报错这里的com.google.common.collect.FluentIterable.append(Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable; but it does not exist 所以排除此guava添加pom依赖
<dependency> <groupId>com.netflix.archaius</groupId> <artifactId>archaius-core</artifactId> <version>0.7.6</version> <exclusions> <exclusion> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </exclusion> </exclusions> </dependency>对于这个问题,如果更好的解决方案,知会博主一声,欢迎大家一起探讨。
需要在消费者新增的接口参数上加上注解 @RequestParam(value = “message”),其中 value 值对应的是声明的名称,例如:
String testFunction(@RequestParam(value = "message") String message);生产者的Controller也需要添加注解 @RequestParam(“message”) ,其中 value 值对应的是声明的名称,例如:
@RequestMapping("testFunction") public String testFunction(@RequestParam("message") String message){ log.info("该请求打印出了:nacos2 "+message+"信息"); return "请求成功"; }这样就可以接收到数据了。