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

背景

现在分布式系统已经大行其道,同时也出现了很多方便调用的工具,通常有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);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,174评论 19 139
  • 这个世界上每个人都有自己的使命,疯疯癫癫的我总是自恋又自卑的对自己疯言疯语,一会说哇!好标致的姑娘,居然会是我!一...
    幻听的世界观阅读 2,817评论 0 0
  • 01 是否曾想尽千方百计逼迫自己作为却还是两手空空? 是否曾雄心壮志发毒誓到头却只是告诉自己:等下次,我一...
    未明心阅读 3,550评论 0 0
  • 总是有这样的新闻出现:“减肥成功等于整容。”屌丝逆袭的话题不论什么时刻都是人们最喜欢看的。胖子都是潜力股呀,很多人...
    文艺青年盒盒阅读 2,905评论 0 1

友情链接更多精彩内容