All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.youzan.httpfetch.HttpApiService Maven / Gradle / Ivy

The newest version!
package com.github.youzan.httpfetch;

import com.github.youzan.httpfetch.chains.HttpApiChain;
import com.github.youzan.httpfetch.convertor.ResponseGeneratorConvertor;
import com.github.youzan.httpfetch.resolver.FormParam;
import com.github.youzan.httpfetch.resolver.PostParam;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by daiqiang on 16/12/6.
 */
public class HttpApiService {

    private final static Logger LOGGER = LoggerFactory.getLogger(HttpApiService.class);

    private HttpApiConfiguration configuration;

    private HttpApiInvoker startInvoker = null;

    private Map, Object> serviceCache = new ConcurrentHashMap<>();

    private Map methodsCache = new HashMap<>();

    public HttpApiService(HttpApiConfiguration configuration) {
        this.configuration = configuration;
    }

    public void init() {
        //创建调用链
        configuration.init();
        List chains = configuration.getChains();

        //排序
        Collections.sort(chains, new Comparator() {
            @Override
            public int compare(HttpApiChain o1, HttpApiChain o2) {
                int order1 = o1.getOrder();
                int order2 = o2.getOrder();
                return order2 > order1 ? 1 : -1;
            }
        });

        HttpApiInvoker last = null;
        for (int i = chains.size() - 1; i >= 0; i--) {
            final HttpApiChain chain = chains.get(i);
            final HttpApiInvoker next = last;
            last = new HttpApiInvoker() {
                @Override
                public HttpResult invoke(Invocation invocation) {
                    return chain.doChain(next, invocation);
                }
            };
        }
        startInvoker = last;
    }

    public  T getOrCreateService(Class serviceCls) {
        Object service;
        if (!serviceCache.containsKey(serviceCls)) {
            try {
                service = createService(serviceCls);
            } catch (Exception e) {
                String msg = String.format("服务创建失败! serviceCls [" + serviceCls + "]");
                LOGGER.error(msg, e);
                throw new RuntimeException(msg);
            }
            serviceCache.put(serviceCls, service);
        } else {
            service = serviceCache.get(serviceCls);
        }
        return (T) service;
    }

    /**
     * 创建代理服务,对代理类和头参数等进行封装
     *
     * @param serviceCls 服务接口类
     * @return
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private Object createService(final Class serviceCls) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        ProxyFactory factory = new ProxyFactory();
        if (serviceCls.isInterface()) {
            factory.setInterfaces(new Class[]{serviceCls});
        } else {
            String msg = String.format("类[%s]不是接口!", serviceCls);
            LOGGER.error(msg);
            throw new IllegalArgumentException(msg);
        }
        return factory.create(null, null, new HttpApiMethodHandler(serviceCls));
    }

    class HttpApiMethodHandler implements MethodHandler {

        private Class serviceCls;

        public HttpApiMethodHandler(Class serviceCls) {
            this.serviceCls = serviceCls;
        }

        public Object invoke(Object target, Method method, Method arg2, Object[] args) throws Throwable {

            HttpApi httpApiAnno = method.getAnnotation(HttpApi.class);
            if (httpApiAnno == null) {
                //没有httpApi注解
                throw new RuntimeException("系统异常,httpapi注解不存在!");
            }

            Invocation invocation = new Invocation();
            HttpApiMethodWrapper wrapper = getOrNewWrapper(method, httpApiAnno);
            invocation.setWrapper(wrapper);

            this.wrapRequestParameter(invocation, wrapper, args);

            //设置请求参数
            HttpApiRequestParam requestParam = new HttpApiRequestParam();
            requestParam.setEncoding(wrapper.getEncoding());
            requestParam.addHeaders(wrapper.getHeaders());
            invocation.setRequestParam(requestParam);

            invocation.setMethod(method);
            invocation.setServiceCls(serviceCls);

            HttpResult httpResult = startInvoker.invoke(invocation);

            return httpResult.getData();


        }

        private void wrapRequestParameter(Invocation invocation, HttpApiMethodWrapper wrapper, Object[] args) {
            //封装参数
            if (!CommonUtils.isArrayEmpty(wrapper.getParameters())) {
                for (int i = 0; i < wrapper.getParameters().length; i++) {
                    ParameterWrapper parameterWrapper = wrapper.getParameters()[i];
                    invocation.addParameters(new RequestParameter(parameterWrapper, args[i]));
                }
            }
        }

        public HttpApiMethodWrapper getOrNewWrapper(Method method, HttpApi httpApiAnno) {
            HttpApiMethodWrapper wrapper;
            if (methodsCache.containsKey(method)) {
                wrapper = methodsCache.get(method);
            } else {
                wrapper = new HttpApiMethodWrapper();
                wrapper.setMethod(httpApiAnno.method());
                wrapper.setReturnCls(method.getReturnType());
                wrapper.setAnnotations(method.getAnnotations());
                wrapper.setEncoding(httpApiAnno.encoding());

                //获取参数名称
                ParameterWrapper[] parameters = wrapperPameters(method);
                wrapper.setParameters(parameters);

                //获取头参数
                Map headers = getHeaders(httpApiAnno);
                wrapper.setHeaders(headers);

                //查询指定的结果转换类获取结果转换服务类
                ResponseGeneratorConvertor generatorService = null;
                if (!CommonUtils.isStringEmpty(httpApiAnno.generator())) {
                    for (ResponseGeneratorConvertor handler : configuration.getConvertors()) {
                        if (httpApiAnno instanceof ResponseGeneratorConvertor) {
                            generatorService = handler;
                            break;
                        }
                    }
                }

                wrapper.setGeneratorService(generatorService);

                //去函数的返回类
                wrapper.setResponseCls(method.getReturnType());

                if (httpApiAnno.timeout() > 0) {
                    wrapper.setTimeout(httpApiAnno.timeout());
                }
                if (httpApiAnno.readTimeout() > 0) {
                    wrapper.setReadTimeout(httpApiAnno.readTimeout());
                }

                //重试次数
                wrapper.setRetry(httpApiAnno.retry());
                //获取重试判断类
                wrapper.setRetryPolicyClazz(httpApiAnno.retryPolicy());

                methodsCache.put(method, wrapper);
            }
            return wrapper;
        }

        /**
         * 从methods中读取
         *
         * @param method
         * @return
         */
        private ParameterWrapper[] wrapperPameters(Method method) {
            Annotation[][] annotationArray = method.getParameterAnnotations();
            if (annotationArray == null || annotationArray.length == 0) {
                LOGGER.info("该函数没有参数!method [{}]", method.getName());
                return new ParameterWrapper[]{};
            }
            String[] paramNames = new String[annotationArray.length];
            for (int i = 0; i < annotationArray.length; i++) {
                //校验里面是否有param注解
                Annotation[] annotations = annotationArray[i];
                paramNames[i] = null;
                for (Annotation annotation : annotations) {
                    if (QueryParam.class.isAssignableFrom(annotation.annotationType())) {
                        paramNames[i] = ((QueryParam) annotation).value();
                        break;
                    } else if (FormParam.class.isAssignableFrom(annotation.annotationType())) {
                        paramNames[i] = ((FormParam) annotation).value();
                        break;
                    } else if (PostParam.class.isAssignableFrom(annotation.annotationType())) {
                        paramNames[i] = ((PostParam) annotation).value();
                        break;
                    }
                }
                if (paramNames[i] == null) {
                    paramNames[i] = "";
                }
            }

            ParameterWrapper[] parameters = new ParameterWrapper[paramNames.length];
            for (int i = 0; i < paramNames.length; i++) {
                parameters[i] = new ParameterWrapper(
                        method.getParameterTypes()[i], paramNames[i],
                        method.getGenericParameterTypes()[i], annotationArray[i]);
            }
            return parameters;
        }

        /**
         * 取注解上面的header
         *
         * @param anno
         * @return
         */
        private Map getHeaders(HttpApi anno) {
            Map headers = new HashMap<>();
            Header[] headersAnno = anno.headers();
            if (!CommonUtils.isArrayEmpty(headersAnno)) {
                for (Header header : headersAnno) {
                    if (header != null) {
                        headers.put(header.key(), header.value());
                    }
                }
            }
            return headers;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy