先来看官方说明文档,如下:
Overriding Feign Defaults
A central concept in Spring Cloud’s Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the @FeignClient
annotation. Spring Cloud creates a new ensemble as anApplicationContext
on demand for each named client using FeignClientsConfiguration
. This contains (amongst other things) an feign.Decoder
, a feign.Encoder
, and a feign.Contract
.
Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of the FeignClientsConfiguration
) using @FeignClient
. Example:
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
译文:Spring Cloud的Feign支持的一个中心概念是命名客户端。每个feign client是整体的一部分,它们一起工作以按需联系远程服务器,并且该整体具有一个名称,开发人员可以使用@FeignClent将其命名。Spring Cloud根据需要使用FeignClientsConfiguration为每个命名的客户端创建一个新的整体作为ApplicationContext。这包含(其他)feign Decoder(解码器),feign Encoder(编码器)和feign Contract(协议)
Spring Cloud让你通过声明额外的配置来完全控制feign client。
下面警告与我们学习ribbon时一样,@Configuration与@ComponentScan不能放到同级目录(或@ComponentScan的子目录)
WARNING
| The FooConfiguration has to be @Configuration but take care that it is not in a @ComponentScan for the main application context, otherwise it will be used for every @FeignClient . If you use @ComponentScan (or @SpringBootApplication ) you need to take steps to avoid it being included (for instance put it in a separate, non-overlapping package, or specify the packages to scan explicitly in the @ComponentScan ). |
接着读文档,下面这句警告的意思是,@FeignClient的url必须与name一起使用,否则启动会有问题。
WARNING
| Previously, using the url attribute, did not require the name attribute. Using name is now required. |
Placeholders are supported in the name
and url
attributes.
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
接下来我们来定义一个ConfigurationFegin,用来覆盖默认的feign配置,为了不与@ComponentScan包冲突,我把它放到com.itmuch.config目录下
package com.itmuch.config;
import feign.Contract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by wanghaijie on 2017/12/4.
*/
@Configuration
public class ConfigurationFegin {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
}
修改UserFeignClient文件,一个是加上了"configuration = ConfigurationFegin.class",另一个是修改了findById上面的注解。
package com.itmuch.cloud;
import com.itmuch.cloud.entity.User;
import com.itmuch.config.ConfigurationFegin;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.netflix.feign.FeignClient;
/**
* Created by wanghaijie on 2017/12/3.
*/
@FeignClient(name = "microservice-provider-user", configuration = ConfigurationFegin.class)
public interface UserFeignClient {
@RequestLine("GET /simple/{id}")
public User findById(@Param("id") Long id);
}
下面依次启动eureka、端口为7900和7901的user,feign-customizing工程,然后访问http://localhost:8010/movie/1便可以看到如下图所示结果。这时我们使用的是feign的默认配置。
下面来证明ConfigurationFeign只作用于microservice-provider-user,我们新建一个UserFeignClient2,如下所示。
package com.itmuch.cloud;
import com.itmuch.config.ConfigurationFeign2;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by wanghaijie on 2017/12/5.
*/
@FeignClient(name="xxxx", url = "http://localhost:8761/", configuration = ConfigurationFeign2.class)
public interface UserFeignClient2 {
@RequestMapping(value = "/eureka/apps/{serviceName}")
public String findServiceInfoByServiceName(@PathVariable("serviceName") String serviceName);
}
接着我们再新建一个ConfigurationFeign2(这个类是用来配置权限的,因为我们访问eureka需要用户名和密码)
package com.itmuch.config;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by wanghaijie on 2017/12/5.
*/
@Configuration
public class ConfigurationFeign2 {
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password123");
}
}
接着在MovieController当中添加
@GetMapping("/{serviceName}")
public String findServiceInfoByServiceName(@PathVariable String serviceName) {
return this.userFeignClient2.findServiceInfoByServiceName(serviceName);
}
下面我们依次启动Eureaka、端口为7900和7901的两个user工程、feign-customizing工程,然后我们在地址栏中输入http://localhost:8010/microservice-provider-user,结果如下图所示。
我们再访问http://localhost:8010/movie/1,结果如下图所示,可以看到两个配置的作用是不同的。