Spring Cloud Alibaba - fegin入门案例(注意事项)?
什么是fegin?
Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
为什么要使用fegin?
通过上一章 SpringCloud Alibaba - Ribbon入门案例 我们可以明显的感受到,消费者在调用生产者的时候,我们需要额外的使用 restTemplate 进行调用,并且请求的参数也是需要写入,这样一来不仅代码可读性不好,并且编写的风格不统一。
现在,我们就用 fegin 来优化代码。
同样的,生产者不需要改变,只需修改消费者的配置。
使用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.lang.NoClassDefFoundError: Lcom/netflix/config/CachedDynamicIntProperty
原因 :(初步排查)
此类编译时可用,而运行时在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 "请求成功";
}
这样就可以接收到数据了。