1.引入
之前在讲解服务之间的远程调用的时候都是用RestTemplate来发送HTTP请求,但这种方式显得比较冗余,不方便维护,所以现在使用Feign来代替这种方式
- Feign是一个声明式HTTP客户端,专门用来发送HTTP请求
2.快速入门
2.1.引入依赖
<!--feign的客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
注意:Feign版本高于Hoxton.M2 RELEASED版本之后不再使用ribbon作为负载均衡器,而是使用loadbalancer,所以还要引入以下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
不仅要引入loadbalancer依赖,还要在Nacos依赖中排除ribbon的依赖,如下:
<!--nacos客户端依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
2.2.开启Feign客户端
引入依赖之后,需要在启动类添加注解来开启Feign客户端,并且把它注册到spring中
2.3.编写接口
import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("userService")
public interface UserClients {
@GetMapping("/user/{id}")
User findById(@PathVariable Long id);
}
- 在这个接口中,首先需要一个@FeignClient注解,用来表明远程调用的服务名称
- 在接口中编写一个方法,这个方法就是远程调用userService服务的方法,其样式和controll接口中的格式基本一致,要表明调用的路径,这里返回值是User实体类,表明调用之后获取的数据就封装到User中
2.4.调用接口
- 注入刚刚编写的接口
- 用feign远程调用就是调用接口中的方法(下面的第二步)
@Autowired
private UserClients userClients;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.用feign远程调用
User user = userClients.findById(order.getUserId());
// 3.把user对象封装到order中
order.setUser(user);
// 4.返回
return order;
}
2.5.小结
这样一对比,以往的RestTemplate,不仅把url暴露在外面,而且路径一长就不好维护了,而这个feign不仅把路径统一管理在接口中,而且不暴露url,可维护性更高
3.实现Feign的最佳实践
假如有多个服务都需要远程调用user-service这个服务,那每次都在服务里编写UserClient显得就很麻烦,那么此时我们就可以把这个UserClient抽出来,放到另外一个专门用来存放Client的服务中,别的服务要用的时候,只需要把依赖导入进去就可以了
原来的模式:
现在的模式:
接下来讲讲如何实现
feign-api目录
把order-service中的clients包里的UserClients接口和pojo包里的User类移动到这个新建的服务中,然后引入feign的依赖
<!--feign客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
现在有了单另的专门存放Client的服务,那就把原来的服务中的对应的部分删除掉,具体删的就是存放进feign-api中的部分
注意:
这个时候项目可能会报错,说无法用@Autowired注入UserClient接口,说没有相应的bean,这个时候就要注意了,我们在上面的2.2小节中讲到@EnableFeignClients不仅有开启feign的功能,并且有这个注解后这个接口就可以被spring扫描到,并创建对应的bean
- 而在order-service服务中,spring默认扫描的包是启动类所在的包,而在这个包里可没有UserClient,他已经被移到feign-api这个服务里了,所以我们现在要让spring扫描到这个UserClient可以这么做:
- 在@EnableFeignClients后面添加配置,指定其扫描UserClient这个接口