背景
现在分布式系统已经大行其道,同时也出现了很多方便调用的工具,通常有RPC和HTTP的方式,但是由于各种原因可能项目中不一定能运用到一些完善的技术。现在我来讲下如何更加方便的通过HTTP方式调用。
痛点
普通的HTTP调用会在调用方出现调用的url等大量的硬代码,这样在服务方修改了地址调用方也要跟着改,耦合很重。
例如:
reJson = ApiToolUtils.getTool().get("/api/user/getUserToken?userId=" + userId);
所以可以用注解在提供服务的Service接口上标注,如:
@HttpEntry(url = "/exceptionlogs/save", method = HttpEntryMethod.POST)
这样只需要服务提供方顺带修改一下url,不需要调用方做任何的改动。
类图
![](https://img.haomeiwen.com/i1389484/c198d1e32b746d5e.png)
实现
- 使用动态代理来增加接口方法
class ServiceProxy<T> implements InvocationHandler {
private static final Logger logger = LoggerFactory.getLogger(ServiceProxy.class);
/**
* 代理的接口类
*/
private final Class<T> serviceInterface;
/**
* 服务器url
*/
private static final String SERVER_URL = XPropertiesUtil.getProperties("server.url");
/**
* session的cookie名
*/
private static final String SESSION_COOKIE_NAME = XPropertiesUtil.getProperties("server.sessionCookieName");
private static final String COOKIE = "COOKIE";
private static final HashMap<String, String> SKIP_CSRF_PARAM;
static {
SKIP_CSRF_PARAM = new HashMap<>();
SKIP_CSRF_PARAM.put("_c", "api");
}
private static final String[] HTML_TAG = {"<html>", "<div>"};
/**
* HTTP_CLIENT, 用于发送http请求与读取结果
*/
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient();
ServiceProxy(Class<T> serviceInterface) {
this.serviceInterface = serviceInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (logger.isInfoEnabled()) {
logger.info("invoking {}.{}, args: {}", serviceInterface.getName(), method.getName(), Arrays.toString(args));
}
HttpEntry httpEntry = method.getAnnotation(HttpEntry.class);
if (null == httpEntry) {
logger.warn("invoking {}.{} failed. no annotation @HttpEntry", serviceInterface.getName(), method.getName());
return null;
}
// 获取注解上的信息
String url = httpEntry.url();
HttpEntryMethod httpMethod = httpEntry.method();
Class[] returnType = httpEntry.returnType();
// 获取参数名
String[] paramNames = this.getMethodParameterNamesByAnnotation(method);
// 执行请求
String responseText = execute(url, httpMethod, paramNames, args);
// 处理返回结果
return processResponse(responseText, method, returnType);
}
}
网友评论