美文网首页
使用动态代理调用外部系统服务

使用动态代理调用外部系统服务

作者: RobertCrazying | 来源:发表于2018-01-23 18:36 被阅读9次

背景

现在分布式系统已经大行其道,同时也出现了很多方便调用的工具,通常有RPC和HTTP的方式,但是由于各种原因可能项目中不一定能运用到一些完善的技术。现在我来讲下如何更加方便的通过HTTP方式调用。

痛点

普通的HTTP调用会在调用方出现调用的url等大量的硬代码,这样在服务方修改了地址调用方也要跟着改,耦合很重。
例如:

  reJson = ApiToolUtils.getTool().get("/api/user/getUserToken?userId=" + userId);

所以可以用注解在提供服务的Service接口上标注,如:

    @HttpEntry(url = "/exceptionlogs/save", method = HttpEntryMethod.POST)

这样只需要服务提供方顺带修改一下url,不需要调用方做任何的改动。

类图

httpapi.png

实现

  1. 使用动态代理来增加接口方法
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);
    }
}

相关文章

网友评论

      本文标题:使用动态代理调用外部系统服务

      本文链接:https://www.haomeiwen.com/subject/boobnxtx.html