Spring Cloud Alibaba - fegin入门案例(注意事项)
什么是fegin?
Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
为什么要使用fegin?
通过上一章 我们可以明显的感受到,消费者在调用生产者的时候,我们需要额外的使用 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 "请求成功"; }
这样就可以接收到数据了。