package org.rx.socks.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.commons.lang3.ArrayUtils;
import org.rx.common.Contract;
import org.rx.beans.Tuple; import org.rx.common.App;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.PrioritizedParameterNameDiscoverer; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function; import static org.rx.common.Contract.isNull; public class RestClient {
private static class DynamicProxy implements InvocationHandler, MethodInterceptor {
private String baseUrl, proxyHost;
private ParameterNameDiscoverer parameterNameDiscoverer = new PrioritizedParameterNameDiscoverer(); private DynamicProxy(String baseUrl, String proxyHost) {
this.baseUrl = baseUrl;
this.proxyHost = proxyHost;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass().equals(Object.class)) {
return method.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 = new HttpClient();
client.setProxyHost(proxyHost);
if (App.equals(httpMethod, HttpClient.GetMethod, true)) {
return setResult(method, client.httpGet(url));
} Parameter[] parameters = method.getParameters();
String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
Function<Integer, String> 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 = new JSONObject();
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]);
}
return setResult(method, client.httpPost(url, jsonEntity));
} Map<String, String> 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]));
}
return setResult(method, client.httpPost(url, params));
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return invoke(o, method, objects);
} private Object setResult(Method method, String resText) {
Class<?> returnType = method.getReturnType();
if (returnType.equals(Void.TYPE)) {
return Void.TYPE;
}
Tuple<Boolean, ?> 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> T create(Class<? extends T> restInterface, String baseUrl) {
return create(restInterface, baseUrl, null, true);
} public static <T> T create(Class<? extends T> restInterface, String baseUrl, String proxyHost, boolean byCglib) {
DynamicProxy handler = new DynamicProxy(baseUrl, proxyHost);
return (T) (byCglib ? Enhancer.create(restInterface, handler)
: Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class[]{restInterface}, handler));
}
}
package org.rx.socks.http;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RestMethod {
String value() default ""; String path() default ""; String method() default "POST"; boolean isFormParam() default false;
}
package org.rx.socks.http;

import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RestParam {
String value() default ""; String name() default "";
}

666   网购半价返利 http://f-li.cn

测试

package org.rx.test.bean;

import org.rx.socks.http.RestMethod;

public interface RestApi {
@RestMethod(method = "GET")
void test(); int add(@org.rx.socks.http.RestParam("a") int a, @org.rx.socks.http.RestParam("b") int b); String login(@org.rx.socks.http.RestParam("userId") String uid, @org.rx.socks.http.RestParam("pwd") String pwd); @RestMethod("/add24")
RestResult add2(RestParam param);
}
    @Test
public void testRest() {
String proxy = null;
proxy = "127.0.0.1:8888";
RestApi client = RestClient.create(RestApi.class, "http://localhost:8081", proxy, true);
System.out.println(client.getClass());
client.test();
client.add(1, 1);
client.login("Rocky", "abc123");
RestParam p = new RestParam();
p.setA(12);
p.setB(12);
client.add2(p);
}

java 轻量级 RestClient的更多相关文章

  1. java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)

    概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...

  2. java轻量级IOC框架Guice

    Google-Guice入门介绍(较为清晰的说明了流程):http://blog.csdn.net/derekjiang/article/details/7231490 使用Guice,需要添加第三方 ...

  3. java轻量级Http Server

    lighttpd 官方主页:www.lighttpd.netLighttpd是一个德国人领导的开源软件,其根本的目的是提供一个专门针对高性能网站,安全.快速.兼容性好并且灵活的web server环境 ...

  4. java -- 轻量级锁

    在了解轻量级锁之前,首先要知道什么是CAS CAS--Compare And Swap 比较并交换--通过比较传入的旧值和原内存位置中的值比较,来决定是不是要更新数据. CAS的语义是“我认为V的值应 ...

  5. JAVA轻量级文件监控

    原文地址:http://blog.csdn.net/three_man/article/details/31012903?utm_source=tuicool 介绍 本文主要介绍一种轻量级的文件监控方 ...

  6. java轻量级IOC框架Guice(转)

    出处:http://www.cnblogs.com/whitewolf/p/4185908.html Guice是由Google大牛Bob lee开发的一款绝对轻量级的java IoC容器.其优势在于 ...

  7. Java轻量级业务层框架Spring两大核心IOC和AOP原理

    IoC(Inversion of Control): IOC的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器负责将这些 ...

  8. Restlet+Fastjson 高速构建轻量级 Java RESTful Webservice

    自己入门Java时做过一个小型RESTful Web Service的项目,这里总结一下. 服务的数据交换格式主要採用JSON,服务为REST风格.连接採用Http协议,数据库使用MySQL,OR M ...

  9. 🔥支持 Java 19 的轻量级应用开发框架,Solon v1.10.4 发布

    Java 轻量级应用开发框架.可用来快速开发 Java 应用项目,主框架仅 0.1 MB. 相对于 Spring Boot 和 Spring Cloud 的项目: 启动快 5 - 10 倍. (更快) ...

随机推荐

  1. 手机app安装包apk/ipa放到网上无法下载原因及教程

    做好APP后,APP名为app.apk或app.ipa 上传到根目录后,生成二维码 但还是无法下载,哪按以下教程让服务器apache/iis/nginx支持.apk/ipa文件下载 windows i ...

  2. python的OS模块生成100个txt文件

    #!/user/bin/env/python35 # -*-coding:utf-8-*- # author:Keekuun """ 问题:生成一个文件夹,文件夹下面生成 ...

  3. python自动化之函数封装

    函数最重要的目的是方便我们重复使用相同的一段程序. 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句. 前面一些记录了selenium的各种API ...

  4. ES6数组方法

    ES6数组方法 以下方法添加到了Array.prototype对象上(isArray除外) indexOf 类似字符串的indexOf()方法 stringObject.indexOf(searchv ...

  5. Web RTC + audio API 实现录音,并压缩

    <button onclick="record()">开始录音</button> <button onclick="stopRecord() ...

  6. kafka的简介

    1. kafka是一个分布式消息队列.具有高性能.持久化.多副本备份.横向扩展能力.生产者往队列里写消息,消费者从队列里取消息进行业务逻辑.一般在架构设计中起到解耦.削峰.异步处理的作用. 1.1 b ...

  7. CentOS7 启动docker.service失败

    背景:阿里云服务器安装了docker服务,并且更改了仓库位置 需求:让docker正常启动 方法: 一.修改/etc/docker/daemon.json文件后缀 当向该文件中写入仓库配置时,该文件后 ...

  8. jQuery选择器中空格的问题再探究

    jQuery选择器的空格问题,看似很小,但是差之毫厘谬以千里,让人很是恼火,<锋利的jQuery>书中有个经典的例子,我这里也拷贝下来,再加点自己的想法 <html> < ...

  9. 我的scoi2018

    高一,很尴尬,凉~ -------- 大家好,我是分界线,我弱弱的说本次采用倒序的写作手法 -------- 故事是这样讲的: Day0: 刚刚去那个电科搞的集训,早上才考了一波模拟赛,下午就过来住酒 ...

  10. 2018-8-10-win10-uwp-ApplicationView

    title author date CreateTime categories win10 uwp ApplicationView lindexi 2018-08-10 19:16:53 +0800 ...