问题描述
如何给Feign接口单独设置一个代理访问地址
一般微服务之间的通信采用Feign,Feign的声明式调用也是很方便,当然Feign底层也是封装了Http调用,http客户端可选,这里选择的是OkHttp作为调用方式,OkHttp的优势就不多说了,这里主要讨论如何给Feign接口设置代理访问地址。
有些时候我们需要通过代理的方式请求某个地址,可能因为网络之间无法直接通信,需要通过代理方式,这里就需要给http调用设置一个代理调用地址。因为上面选择OkHttp作为底层访问的http客户端,所以只需要给OkHttp设置一个代理地址即可。
那么既然给OkHttp设置一个代理地址,不是可以自定义配置在全局设置即可吗?当然这是可以的,也最方便,但是如果项目里面有很多Feign接口只有部分接口需要单独设置代理访问,这时候就需要单独撸代码了,话不多说直接上代码。
package com.zhoule.demoactuator.service;
import com.zhoule.demoactuator.feign.RemoteFeignService;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Iterator;
import java.util.Map;
@Service
public class OrderService implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
//远程调用的一个feign客户端
@Resource
private RemoteFeignService remoteFeignService;
@Resource
private ApplicationContext applicationContext;
@Override
public void afterPropertiesSet() throws Exception {
//获取创建OkhttpClient的Builder对象
OkHttpClient.Builder builder = applicationContext.getBean(OkHttpClient.Builder.class);
//设置代理地址
builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 9090)));
//创建一个新的okhttp client
okhttp3.OkHttpClient newClient = builder.build();
//创建一个feign client
feign.okhttp.OkHttpClient feignClient = new feign.okhttp.OkHttpClient(newClient);
//获取代理接口的实际处理对象
InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(remoteFeignService);
Field dispatchField = ReflectionUtils.findField(handler.getClass(), "dispatch");
ReflectionUtils.makeAccessible(dispatchField);
Map<Object, Object> methodMap = (Map<Object, Object>) ReflectionUtils.getField(dispatchField, handler);
//遍历feign接口里面的每个方法
Iterator<Map.Entry<Object, Object>> iterator = methodMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Object, Object> next = iterator.next();
Object value = next.getValue();
Field clientField = ReflectionUtils.findField(value.getClass(), "client");
ReflectionUtils.makeAccessible(clientField);
//需要直接替换Client而不是Client中的delegate,否则改的还是一个对象
//Object okHttpClient = ReflectionUtils.getField(clientField, value);
//Field delegateField = ReflectionUtils.findField(okHttpClient.getClass(), "delegate");
//ReflectionUtils.makeAccessible(delegateField);
//设置新的对象
ReflectionUtils.setField(clientField, value, feignClient);
}
logger.info("代理对象初始化完毕");
}
}