packageorg.rx.socks.http;importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.JSONObject;importnet.sf.cglib.proxy.Enhancer;importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;importorg.apache.commons.lang3.ArrayUtils;importorg.rx.common.Contract;importorg.rx.beans.Tuple;importorg.rx.common.App;importorg.springframework.core.ParameterNameDiscoverer;importorg.springframework.core.PrioritizedParameterNameDiscoverer;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Parameter;importjava.lang.reflect.Proxy;importjava.util.Arrays;importjava.util.HashMap;importjava.util.Map;importjava.util.function.Function;import staticorg.rx.common.Contract.isNull;public classRestClient {private static class DynamicProxy implementsInvocationHandler, MethodInterceptor {privateString baseUrl, proxyHost;private ParameterNameDiscoverer parameterNameDiscoverer = newPrioritizedParameterNameDiscoverer();privateDynamicProxy(String baseUrl, String proxyHost) {this.baseUrl =baseUrl;this.proxyHost =proxyHost;
}
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {if (method.getDeclaringClass().equals(Object.class)) {returnmethod.invoke(proxy, args);
}
String apiPath=method.getName(),
httpMethod= ArrayUtils.isEmpty(args) ?HttpClient.GetMethod : HttpClient.PostMethod;boolean isFormParam = args != null && args.length > 1;
RestMethod restMethod= method.getDeclaredAnnotation(RestMethod.class);if (restMethod != null) {
String temp=isNull(restMethod.path(), restMethod.value());if (!App.isNullOrEmpty(temp)) {
apiPath=temp;
}if (!App.isNullOrEmpty(restMethod.method())) {
httpMethod=restMethod.method();
}
isFormParam=restMethod.isFormParam();
}
String url= String.format("%s/%s", baseUrl, apiPath);
HttpClient client= newHttpClient();
client.setProxyHost(proxyHost);if (App.equals(httpMethod, HttpClient.GetMethod, true)) {returnsetResult(method, client.httpGet(url));
}
Parameter[] parameters=method.getParameters();
String[] parameterNames=parameterNameDiscoverer.getParameterNames(method);
Function func = offset -> !ArrayUtils.isEmpty(parameterNames)&& parameters.length == parameterNames.length ?parameterNames[offset]
: parameters[offset].getName();
System.out.println(method.getDeclaringClass().getName()+ " pNames: " +Arrays.toString(parameterNames));if (!isFormParam && parameters.length == 1) {return setResult(method, client.httpPost(url, args[0]));
}if (!isFormParam) {
JSONObject jsonEntity= newJSONObject();for (int i = 0; i < parameters.length; i++) {
Parameter p=parameters[i];
RestParam restParam= p.getDeclaredAnnotation(RestParam.class);
jsonEntity.put(restParam!= null ?isNull(restParam.name(), restParam.value()) : func.apply(i),
args[i]);
}returnsetResult(method, client.httpPost(url, jsonEntity));
}
Map params = new HashMap<>();for (int i = 0; i < parameters.length; i++) {
Parameter p=parameters[i];
RestParam restParam= p.getDeclaredAnnotation(RestParam.class);
params.put(restParam!= null ?isNull(restParam.name(), restParam.value()) : func.apply(i),
Contract.toJsonString(args[i]));
}returnsetResult(method, client.httpPost(url, params));
}
@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throwsThrowable {returninvoke(o, method, objects);
}privateObject setResult(Method method, String resText) {
Class> returnType =method.getReturnType();if(returnType.equals(Void.TYPE)) {returnVoid.TYPE;
}
Tuple r =App.tryConvert(resText, returnType);
System.out.println(r.left+ "," + r.right + "=>" + resText + "," +returnType);return r.left ?r.right : JSON.toJavaObject(JSON.parseObject(resText), returnType);
}
}public static T create(Class extends T>restInterface, String baseUrl) {return create(restInterface, baseUrl, null, true);
}public static T create(Class extends T> restInterface, String baseUrl, String proxyHost, booleanbyCglib) {
DynamicProxy handler= newDynamicProxy(baseUrl, proxyHost);return (T) (byCglib ?Enhancer.create(restInterface, handler)
: Proxy.newProxyInstance(handler.getClass().getClassLoader(),newClass[]{restInterface}, handler));
}
}