1.前言
前段时间使用了forest框架发起http请求,发现非常方便快捷,因为项目是内网部署的,需要走代理,于是去查找了官方文档,发现可以通过注解设置代理,但是通过注解设置代理会有个问题,不好区分环境,并且需要在每个接口上添加注解。
2.源码
于是笔者就去看了forest框架源码,发现其代理设置,主要是在com.dtflys.forest.lifecycles.proxy.HTTPProxyLifeCycle类中
以下为源码:
源码中主要是通过@HTTPProxy注解来实现代理配置。
于是笔者就自己重写了com.dtflys.forest.lifecycles.proxy.HTTPProxyLifeCycle类,通过读取配置文件来实现不同的环境,使用不同的代理。
3.修改源码
以下为笔者修后的类:
package com.dtflys.forest.lifecycles.proxy;
import com.dtflys.forest.annotation.HTTPProxy;
import com.dtflys.forest.callback.HTTPProxySource;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import com.dtflys.forest.http.ForestProxy;
import com.dtflys.forest.http.ForestProxyType;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.lifecycles.MethodAnnotationLifeCycle;
import com.dtflys.forest.mapping.MappingTemplate;
import com.dtflys.forest.reflection.ForestMethod;
import com.dtflys.forest.utils.HeaderUtils;
import com.dtflys.forest.utils.StringUtils;
import com.lkwecom.common.utils.ProxyConfig;
import java.util.Arrays;
/**
* HTTP正向代理生命周期类
*
* @author gongjun[dt_flys@hotmail.com]
* @since 1.5.0-BETA5
*/
public class HTTPProxyLifeCycle implements MethodAnnotationLifeCycle<HTTPProxy, Object> {
private final static String PARAM_KEY_HTTP_PROXY_SOURCE = "__http_proxy_source";
private final static String PARAM_KEY_HTTP_PROXY = "__http_proxy";
@Override
public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] args) {
Boolean agent = ProxyConfig.getAgent();
if (!agent) {
return;
}
final ForestProxyType type = (ForestProxyType) getAttribute(request, "type");
String portStr = (String) getAttribute(request, "port");
final String usernameStr = (String) getAttribute(request, "username");
final String passwordStr = (String) getAttribute(request, "password");
final String[] headersStr = (String[]) getAttribute(request, "headers");
final MappingTemplate portTemplate = method.makeTemplate(HTTPProxy.class, "port", portStr);
final MappingTemplate usernameTemplate = method.makeTemplate(HTTPProxy.class, "username", usernameStr);
final MappingTemplate passwordTemplate = method.makeTemplate(HTTPProxy.class, "password", passwordStr);
final Object httpProxySource = request.getMethod().getExtensionParameterValue(PARAM_KEY_HTTP_PROXY_SOURCE);
final MappingTemplate[] headersTemplates = Arrays.stream(headersStr)
.map(headerStr -> method.makeTemplate(HTTPProxy.class, "headers", headerStr))
.toArray(MappingTemplate[]::new);
// addAttribute(request, "host_temp", hostTemplate);
// addAttribute(request, "port_temp", portTemplate);
// addAttribute(request, "username_temp", usernameTemplate);
// addAttribute(request, "password_temp", passwordTemplate);
// addAttribute(request, "headers_temp", Arrays.stream(headersStr)
// .map(headerStr -> method.makeTemplate(HTTPProxy.class, "headers", headerStr))
// .toArray(MappingTemplate[]::new));
final String host = ProxyConfig.getHost();
String username = null, password = null;
if (usernameTemplate != null) {
username = usernameTemplate.render(args);
}
if (passwordTemplate != null) {
password = passwordTemplate.render(args);
}
int port = 80;
if (StringUtils.isBlank(host)) {
if (httpProxySource != null && httpProxySource instanceof HTTPProxySource) {
request.setProxy(((HTTPProxySource) httpProxySource).getProxy(request));
return;
}
throw new ForestRuntimeException("[Forest] Proxy host cannot be empty!");
}
if (StringUtils.isNotBlank(portStr)) {
portStr = portTemplate.render(args);
try {
port = Integer.parseInt(ProxyConfig.getPort());
} catch (Throwable th) {
}
}
final ForestProxy proxy = new ForestProxy(type, host, port);
if (StringUtils.isNotEmpty(username)) {
proxy.setUsername(username);
}
if (StringUtils.isNotEmpty(password)) {
proxy.setPassword(password);
}
if (headersTemplates != null && headersTemplates.length > 0) {
HeaderUtils.addHeaders(proxy, headersTemplates, args);
}
request.setProxy(proxy);
}
@Override
public boolean beforeExecute(ForestRequest request) {
final MappingTemplate hostTemplate = (MappingTemplate) getAttribute(request, "host_temp");
final MappingTemplate portTemplate = (MappingTemplate) getAttribute(request, "port_temp");
final MappingTemplate usernameTemplate = (MappingTemplate) getAttribute(request, "username_temp");
final MappingTemplate passwordTemplate = (MappingTemplate) getAttribute(request, "password_temp");
final MappingTemplate[] headersTemplates = (MappingTemplate[]) getAttribute(request, "headers_temp");
return true;
}
@Override
public void onMethodInitialized(ForestMethod method, HTTPProxy annotation) {
final Class<? extends HTTPProxySource> clazz = annotation.source();
if (clazz != null && !clazz.isInterface()) {
HTTPProxySource proxySource = method.getConfiguration().getForestObject(clazz);
method.setExtensionParameterValue(PARAM_KEY_HTTP_PROXY_SOURCE, proxySource);
}
method.setExtensionParameterValue(PARAM_KEY_HTTP_PROXY, annotation);
}
}
配置文件类:
package com.lkwecom.common.utils;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
@Slf4j
public class ProxyConfig {
private static Boolean agent = false;
private static String host;
private static String port;
private static String sdkPath;
private static String proxy;
/**
* jwt密钥
*/
private static String jwtSecret;
private static final String PROFILES_ACTIVE = "prod";
private static final String PROFILES_ACTIVE_TEST = "test";
private static final String PROFILES_ACTIVE_DEMO = "demo";
private static final String PROFILES_ACTIVE_LOCAL = "local";
static {
InputStream inputStream = ProxyConfig.class.getResourceAsStream("/proxy.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
} catch (IOException e) {
log.error("加载代理报错了==========================", e);
}
String active = ConfigUtils.getString("spring.profiles.active");
log.info("加载代理类,获取到的active环境变量是==================={}=============", active);
if (PROFILES_ACTIVE_TEST.equals(active)) {
ProxyConfig.sdkPath = properties.getProperty("devSdkPath");
ProxyConfig.jwtSecret = properties.getProperty("devJwtSecret");
} else if (PROFILES_ACTIVE_DEMO.equals(active)) {
ProxyConfig.sdkPath = properties.getProperty("demoSdkPath");
ProxyConfig.jwtSecret = properties.getProperty("demoJwtSecret");
} else if (PROFILES_ACTIVE.equals(active)) {
initProxy();
} else if (PROFILES_ACTIVE_LOCAL.equals(active)) {
ProxyConfig.sdkPath = properties.getProperty("localSdkPath");
ProxyConfig.jwtSecret = properties.getProperty("localJwtSecret");
}
}
private static void initProxy() {
InputStream stream = ProxyConfig.class.getResourceAsStream("/proxy-prod.properties");
Properties prop = new Properties();
try {
prop.load(stream);
} catch (IOException e) {
log.error("加载代理报错了==========================", e);
}
ProxyConfig.sdkPath = prop.getProperty("sdkPath");
ProxyConfig.jwtSecret = prop.getProperty("jwtSecret");
ProxyConfig.host = prop.getProperty("host");
ProxyConfig.port = prop.getProperty("port");
ProxyConfig.agent = Boolean.parseBoolean(prop.getProperty("agent"));
if (ProxyConfig.agent) {
ProxyConfig.proxy = "http://" + prop.getProperty("host") + ":" + prop.getProperty("port");
log.info("加载sdk的代理-------------------------------------------{}", ProxyConfig.proxy);
} else {
ProxyConfig.proxy = "";
}
}
public static String getJwtSecret() {
return jwtSecret;
}
public static void setJwtSecret(String jwtSecret) {
ProxyConfig.jwtSecret = jwtSecret;
}
public static String getSdkPath() {
return sdkPath;
}
public static void setSdkPath(String sdkPath) {
ProxyConfig.sdkPath = sdkPath;
}
public static String getProxy() {
return proxy;
}
public static void setProxy(String proxy) {
ProxyConfig.proxy = proxy;
}
public static Boolean getAgent() {
return agent;
}
public static void setAgent(Boolean agent) {
ProxyConfig.agent = agent;
}
public static String getHost() {
return host;
}
public static void setHost(String host) {
ProxyConfig.host = host;
}
public static String getPort() {
return port;
}
public static void setPort(String port) {
ProxyConfig.port = port;
}
}