前面已经学习了Ribbon,从Eureka获取服务的实例在通过RestTemplate调用,并转换成需要的对象
如:List<Product> list = restTemplate.exchange(PRODUCT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(httpHeaders), List.class).
getBody();
可以发现所有的数据调用和转换都是由用户直接来完成的,我们可能不想直接访问Rest接口,如果转换回来的直接是对象而不需要直接使用RestTemplate进行转换就好了,这个时候就需要使用Feign了。
代码Git地址:https://gitee.com/hankin_chj/springcloud-micro-service.git
注意:Feign不建议大家使用,流程简单并发不高的方法可以用一用。
一、Feign基本使用
1、创建新模块Feign
复制springcloud-micro-consumer成一个新的模块springcloud-micro-consumer-feign
Feign服务修改pom文件,增加对feign的支持:
<dependencies>
<dependency>
<groupId>com.chj</groupId>
<artifactId>springcloud-micro-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- eureka中已经内置集成了ribbon,所以并不需要显示引入ribbon的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 增加对feign的支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
注意:这里又有版本问题,如果是Edgware或之前的版本,使用下面的版本
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
feign的操作其实需要ribbon的支持。
2、新建springcloud-micro-service-feign模块
2.1、这个模块专门定义客户端的调用接口,修改pom文件如下:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.chj</groupId>
<artifactId>springcloud-micro-api</artifactId>
</dependency>
</dependencies>
2.2、安全服务提供方的认证问题
service-feign模块如果要通过Feign进行远程调用,依然需要安全服务提供方的认证问题,不过在feign里面已经集成了这块功能,代码如下:
@Configuration
public class FeignClientConfig {
@Bean
public BasicAuthRequestInterceptor getBasicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("admin", "admin");
}
}
2.3、service-feign模块新建一个IProductClientService接口
@FeignClient(name = "SPRINGCLOUD-MICRO-PRODUCT", configuration = FeignClientConfig.class)
public interface IProductClientService {
@RequestMapping("/prodcut/get/{id}")
public Product getProduct(@PathVariable("id")long id);
@RequestMapping("/prodcut/list")
public List<Product> listProduct() ;
@RequestMapping("/prodcut/add")
public boolean addPorduct(Product product) ;
}
3、模块springcloud-micro-consumer-feign配置
3.1、consumer-feign引入service-feign包
springcloud-micro-consumer-feign模块修改pom文件,引入springcloud-micro-service-feign包:
<!-- feign接口模块 -->
<dependency>
<groupId>com.chj</groupId>
<artifactId>springcloud-micro-service-feign</artifactId>
</dependency>
3.2、consumer-feign模块删除RestConfig.java类
springcloud-micro-consumer-feign模块由于microcloud-service里面已经做了安全验证,并且后面并不直接使用RestTemplate ,所以删除RestConfig.java类。
3.3、consumer-feign模块修改ConsumerProductController
springcloud-micro-consumer-feign模块修改ConsumerProductController,这个时候直接使用microcloud-service定义的服务就可以了,具体实现如下:
@RestController
@RequestMapping("/consumer")
public class ConsumerProductController {
@Resource
private IProductClientService iProductClientService;
@RequestMapping("/product/get")
public Object getProduct(long id) {
return iProductClientService.getProduct(id);
}
@RequestMapping("/product/list")
public Object listProduct() {
return iProductClientService.listProduct();
}
@RequestMapping("/product/add")
public Object addPorduct(Product product) {
return iProductClientService.addPorduct(product);
}
}
由此可见,这个时候ConsumerProductController的代码已经简洁了不少。
3.4、consumer-feign模块修改程序主类
由于使用了feign接口功能,需要添加@EnableFeignClients()注解:
@SpringBootApplication
@EnableEurekaClient
//@RibbonClient(name ="SPRINGCLOUD-MICRO-PRODUCT" ,configuration = RibbonConfig.class)
@EnableFeignClients("com.chj.service") // 扫描feign接口服务的service包
public class ConsumerFeignApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerFeignApp.class,args);
}
}
4、启动测试:
访问地址:http://localhost/consumer/product/list
可以发现Feign在调用接口的时候自带负载均衡,并且使用了默认的轮询方式,这也不奇怪,因为Fegin里面内置就使用了Ribbon,可以做个测试,看下是否真的如此consumer-feign修改程序主类ConsumerFeignApp。
添加注解:@RibbonClient(name ="MICROCLOUD-PROVIDER-PRODUCT" ,configuration = RibbonConfig.class)
启动测试:http://localhost/consumer/product/list
可以发现,现在的路由规则以及变成了随机访问
二、其他配置
1、数据压缩
前面我们已经知道Feign之中最核心的作用就是将Rest服务的信息转化为接口,这其中还有其他的一些地方应该要考虑,比如,数据的压缩。Rest协议更多的传输的是文本,JSON或者XML,如果用户发送的请求很大,这个时候有必要对数据进行压缩处理,好在feign本身就提供了压缩的支持。
FeignContentGzipEncodingAutoConfiguration可以先看下这个类:
@Configuration
@EnableConfigurationProperties({FeignClientEncodingProperties.class})
@ConditionalOnClass({Feign.class})
@ConditionalOnBean({Client.class})
@ConditionalOnMissingBean(
type = {
"okhttp3.OkHttpClient"}
)
@ConditionalOnProperty(
value = {
"feign.compression.request.enabled"},
matchIfMissing = false
)
@AutoConfigureAfter({FeignAutoConfiguration.class})
public class FeignContentGzipEncodingAutoConfiguration {
虽然Feign支持压缩,但默认是不开启的,再看下FeignClientEncodingProperties,可以根据这里面的属性进行相关压缩的配置。
@ConfigurationProperties("feign.compression.request")
public class FeignClientEncodingProperties {
private String[] mimeTypes = new String[]{
"text/xml", "application/xml", "application/json"};
private int minRequestSize = 2048;
consumer-feign模块修改application.yml配置文件:
feign:
compression:
request:
enabled: true
mime-types: # 可以被压缩的类型
- text/xml
- application/xml
- application/json
min-request-size: 2048 # 超过2048的字节进行压缩