首先使用的不是 springCloud的feign。
主要是想实现 springcloud 中 feign在@FeignClient(url="${cmdb.url}") 这种占位符的效果
下面是引入的依赖
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>8.18.0</version>
</dependency>
application.properties
cmdb.url=http://localhost:8005
@Component
public class CmdbFeignClient implements BeanFactoryPostProcessor {
//扫描的接口路径
private String scanPath="com.example.java.*";
public static Long OPTIONS_CONNECTTIMEOUTMILLIS = 120000L;
public static Long OPTIONS_READTIMEOUTMILLIS = 120000L;
public static String REQUEST_HEADER_REMOTE_TOKEN = "Authorization";
public static String TOKEN_PREFIX = "Bearer ";
public static String CONTENT_TYPE = "Content-Type";
private ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Set<String> classes = PackageTools.findPackageClass(scanPath);
if(classes==null){
return ;
}
Feign.Builder builder = getFeignBuilder();
//动态创建bean,并注入到Spring容器中
if(classes.size()>0){
for (String claz : classes) {
Class<?> targetClass = null;
try {
targetClass = Class.forName(claz);
CmdbFeignApi api = targetClass.getAnnotation(CmdbFeignApi.class);
if(api==null){
continue;
}
// 这里是可以读取每一个申明接口的地址, 但是这个地址只能写死,不能从配置文件中读取, 现在的问题就是想从配置文件中读取
String url=api.serviceUrl();
if(url.indexOf("http://")!=0){
url="http://"+url;
}
Object target = builder.target(targetClass, url);
beanFactory.registerSingleton(targetClass.getName(), target);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(),e);
}
}
}
this.beanFactory =beanFactory;
}
public Feign.Builder getFeignBuilder(){
Feign.Builder builder = Feign.builder()
//使用Jackson进行参数处理,如果有必要可以自行定义
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
//超时处理
.options(new Request.Options(OPTIONS_CONNECTTIMEOUTMILLIS.intValue(), OPTIONS_READTIMEOUTMILLIS.intValue()))
.retryer(new Retryer.Default(5000, 5000, 3))
//每次请求时,自定义内部请求头部信息,例如:权限相关的信息
.requestInterceptor(template -> {
//请求的不是获取token接口,向请求头部里设置token
if(!template.url().contains(CmdbTokenApi.tokenUrl)){
CmdbTokenService tokenService = this.beanFactory.getBean(CmdbTokenService.class);
template.header(REQUEST_HEADER_REMOTE_TOKEN, TOKEN_PREFIX + tokenService.getToken());
}else {
//请求获取token接口,向请求头部里设置key
}
template.header(CONTENT_TYPE,"application/json");
});//.client(new Client.Default(TrustingSSLSocketFactory.get(), new NoopHostnameVerifier()));
return builder;
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CmdbFeignApi {
/**
* 调用的服务地址
* @return
*/
String serviceUrl();
}
// 这里如果是springcloud 的 feign,直接可以使用 ${cmdb.url}就可以使用配置文件中的url,
// 但是 feign-core是不可以的, 这里是希望能实现如springcloud 的feign一样的使用占位符方式,有没有大佬来解一下。
@CmdbFeignApi(serviceUrl="localhost:8002")
public interface CmdbTokenApi {
public static final String tokenUrl = "/v1/api/auth";
@Headers({"Content-Type: application/json","Accept: application/json"})
@RequestLine("GET /v1/api/auth?code={code}")
public AccessTokenModel getAccessToken(@Param("code") String code);
}