远程调用rpc,dubbo,openfegin核心功能实现

本文主要对okhttp3进行封装代理,使得调用者只需要关注参数,无需关注具体实现,极大降低代码的耦合性,由于我们的项目主要跑在java的服务端,因此我们主要做的是同步的请求,当需要对接第三方平台的实话,该框架能够发挥出极大的作用,下面通过的代码的形式一步步剖析。

1.使用方法,定义一个api请求的类,并定义出接口,如下:

@ZoneMapping(url = "http://127.0.0.1:8800")
public interface Api {

    @Get(path = "/pass/check/{id}")
    Test get(@Query Map<String, Object> map);

    @Post(path = "/pass/check")
    Test post(@MultipartMap Map<String, File> fileMap);

    @Header(contentType = "form-data",headMapName = "head")
    @Put(path = "/pass/put/{id}")
    Test put(@Query Map<String, Object> map,@PathVariable String id,Map<String,Object> head);

}

只需要如上所示就可以配置出接口的请求,面向接口进行http请求

@Query注解主要用来完成普通参数的请求,@MultipartMap标签主要实现了file类型的传输,通过map的形式,可以使用多个file一同进行传输,@Header标签需要注意一下,该标签有两个参数,一个是contentType,另外一个是其他的head参数,headMapName的值需要与方法中的map进行对应,代理后的接口会通过该名称去寻找head中的参数,并完成装配

2.调用过程及原理

@Bean
public NetAuxiliary netAuxiliary() throws ClassNotFoundException {
    NetAuxiliary netAuxiliary =new NetAuxiliary();
    netAuxiliary.setBasePackage("com.core.test.api");
    return netAuxiliary;
}将核心类NetAuxiliary装配到ioc容器中,setBasePackage进行包扫描,创建出api接口的动态代理
/**
 * 网络辅助核心类
 * */
public class NetAuxiliary {
    private final ConcurrentHashMap<String,Object> proxyObjMap =new ConcurrentHashMap<>();

    public NetAuxiliary()  {

    }
    public void setBasePackage(String basePackage) throws ClassNotFoundException {
        List<String> classes = ReflectUtil.getClazzName(basePackage, true);
        String[] beans = new String[classes.size()];
        for (int i = 0; i < classes.size(); i++) {
            Class<?> clsObj = Class.forName(classes.get(i));
            Object obj = Proxy.createProxy(clsObj);
            beans[i]=obj.getClass().getName();
            proxyObjMap.put(classes.get(i),obj);
        }
    }
    public <T> T getApi(Class<T> cls){
        return (T) proxyObjMap.get(cls.getName());
    }
}
public class HttpInvocationHandler implements InvocationHandler {
    private ParameterSelector parameterSelector = new ParameterSelector();

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //已实现的具体类
        if (Object.class.equals(method.getDeclaringClass())) {
            try {
                return method.invoke(this, args);
            } catch (Throwable t) {
                t.printStackTrace();
            }
            //接口
        } else {
            return run(method, args);
        }
        return null;
    }

    public Object run(Method method, Object[] args) throws IllegalAccessException, NoSuchFieldException, InstantiationException {
        ZoneMapping zoneMapping = method.getDeclaringClass().getAnnotation(ZoneMapping.class);
        if (null == zoneMapping) {
            throw new RuntimeException("Domain name not found,please set ZoneMapping annotation");
        }
        Get get = method.getAnnotation(Get.class);
        Post post = method.getAnnotation(Post.class);
        Put put = method.getAnnotation(Put.class);
        Delete delete = method.getAnnotation(Delete.class);
        if (null != get) {
            return HttpUtil.getInstance().get(parsePathVariable(zoneMapping.url() + get.path(), args, method), parseQuery(args, method), (Class<? extends HttpResp>) method.getReturnType(), head(args, method));
        } else if (null != post) {
            return HttpUtil.getInstance().post(parsePathVariable(zoneMapping.url() + post.path(), args, method), parseQuery(args, method), parseMultipartMap(args, method), (Class<? extends HttpResp>) method.getReturnType(), head(args, method));
        } else if (null != put) {
            return HttpUtil.getInstance().put(parsePathVariable(zoneMapping.url() + put.path(), args, method), parseQuery(args, method), (Class<? extends HttpResp>) method.getReturnType(), head(args, method));
        } else if (null != delete) {
            return HttpUtil.getInstance().delete(parsePathVariable(zoneMapping.url() + delete.path(), args, method), parseQuery(args, method), (Class<? extends HttpResp>) method.getReturnType(), head(args, method));
        } else {
            throw new RuntimeException("Request method comment not found");
        }
    }


    /**
     * 组装head参数
     */
    private Map<String, Object> head(Object[] args, Method method) {
        //定义head的map
        Map<String, Object> headMap = new HashMap<>();
        if (args != null) {
            if (!method.isAnnotationPresent(Header.class)) {
                return headMap;
            }
            Header header = method.getAnnotation(Header.class);
            String contentType = header.contentType();
            if (!TextUtils.isEmpty(contentType)) {
                headMap.put("Content-Type", contentType);
            }
            String headMapName = header.headMapName();
            if (TextUtils.isEmpty(headMapName)) {
                return headMap;
            }
            Parameter[] parameters = method.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                Parameter parameter = parameters[i];
                if (!parameter.getName().equals(headMapName)) {
                    continue;
                }
                if (!(args[i] instanceof Map)) {
                    throw new RuntimeException("head must be map values");
                }
                headMap.putAll((Map<? extends String, ?>) args[i]);
            }
        }
        return null;
    }

    /**
     * 查询map组装
     *
     * @param args :参数集合
     */
    private Map<String, Object> parseQuery(Object[] args, Method method) {
        if (args != null) {
            for (Object o : args) {
                if (null == o) {
                    continue;
                }
                Annotation[][] annotations = method.getParameterAnnotations();
                for (Annotation[] annotation : annotations) {
                    if (annotation.length == 0) {
                        continue;
                    }
                    Annotation parameter = annotation[0];
                    if (parameter instanceof Query) {
                        if (o instanceof Map) {
                            return (Map<String, Object>) o;
                        }
                    }
                }

            }
        }
        return null;
    }


    /**
     * 查询是否包含@PathVariable标签,使用rest方式url
     */
    private String parsePathVariable(String url, Object[] args, Method method) {
        if (args != null) {
            for (Object o : args) {
                if (null == o) {
                    continue;
                }
                Annotation[][] annotations = method.getParameterAnnotations();
                for (Annotation[] annotation : annotations) {
                    if (annotation.length == 0) {
                        continue;
                    }
                    Annotation parameter = annotation[0];
                    if (parameter instanceof PathVariable) {
                        Parameter[] parameters = method.getParameters();
                        for (int i = 0; i < parameters.length; i++) {
                            Parameter parameter1 = parameters[i];
                            if (null != parameter1.getAnnotation(PathVariable.class)) {
                                url = url.replace("{" + parameter1.getName() + "}", args[i].toString());
                            }
                        }
                    }
                }


            }
        }
        return url;
    }

    /**
     * 查询map组装Map<String,File>
     *
     * @param args :参数集合
     */
    private Map<String, File> parseMultipartMap(Object[] args, Method method) {
        if (args != null) {
            for (Object o : args) {
                if (null == o) {
                    continue;
                }
                Annotation[][] annotations = method.getParameterAnnotations();
                for (Annotation[] annotation : annotations) {
                    if (annotation.length == 0) {
                        continue;
                    }
                    Annotation parameter = annotation[0];
                    if (parameter instanceof MultipartMap) {
                        if (o instanceof Map) {
                            return (Map<String, File>) o;
                        }
                    }
                }
            }
        }
        return null;
    }

}

3.代码调用

Map<String, File> fileMap =new HashMap<>();
fileMap.put("rootImage",new File("/Users/gfh/Downloads/fj.jpeg"));
Test test= IocBeanUtil.getBean(NetAuxiliary.class).getApi(Api.class).post(fileMap);

其中Test类需要继承并实现

public class Test extends HttpResp implements HttpListener {
    private String msg;

    private String code;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String toString() {
        return "Test{" +
                "msg='" + msg + '\'' +
                ", code='" + code + '\'' +
                ", isSuccess=" + isSuccess() +
                ", statusCode=" + statusCode +
                ", httpErrorMsg='" + httpErrorMsg + '\'' +
                '}';
    }

    @Override
    public boolean isSuccess() {
        if(isSuccessful()&&"0".equals(code)){
            return true;
        }
        return false;
    }
}
实现HttpListener后,可以自定义成功失败的状态,即isSuccess方法,后续将把源码上传至git,感兴趣的同学可以关注一下,github地址:GitHub - sgfh/NetAuxiliary: 网络请求辅助

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值