diff --git a/pom.xml b/pom.xml
index 9201fe2..45b7f4b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
group.flyfish
rest-proxy
- 1.0.6
+ 1.0.7
8
@@ -22,7 +22,7 @@
1.8
4.4
2.6
- 1.0.6
+ 1.0.7
pom
diff --git a/rest-proxy-api/pom.xml b/rest-proxy-api/pom.xml
index d8f176e..27a8d42 100644
--- a/rest-proxy-api/pom.xml
+++ b/rest-proxy-api/pom.xml
@@ -5,7 +5,7 @@
group.flyfish
rest-proxy
- 1.0.6
+ 1.0.7
4.0.0
diff --git a/rest-proxy-core/pom.xml b/rest-proxy-core/pom.xml
index 0c06d33..a94c3bf 100644
--- a/rest-proxy-core/pom.xml
+++ b/rest-proxy-core/pom.xml
@@ -5,7 +5,7 @@
group.flyfish
rest-proxy
- 1.0.6
+ 1.0.7
4.0.0
diff --git a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/RestProxyInvoker.java b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/RestProxyInvoker.java
index 01ebb09..35b0901 100644
--- a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/RestProxyInvoker.java
+++ b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/RestProxyInvoker.java
@@ -2,7 +2,6 @@ package group.flyfish.rest.registry.proxy;
import com.fasterxml.jackson.databind.JavaType;
import group.flyfish.rest.annotation.AutoMapping;
-import group.flyfish.rest.annotation.RestApi;
import group.flyfish.rest.annotation.RestService;
import group.flyfish.rest.configuration.RestClientProperties;
import group.flyfish.rest.configuration.configure.PropertiesConfigurable;
@@ -11,12 +10,14 @@ import group.flyfish.rest.core.client.RestClient;
import group.flyfish.rest.core.client.RestClientBuilder;
import group.flyfish.rest.mapping.RestResultMapping;
import group.flyfish.rest.registry.RestApiRegistry;
+import group.flyfish.rest.registry.proxy.entity.RestMethod;
import group.flyfish.rest.registry.proxy.support.ArgumentResolveContext;
import group.flyfish.rest.registry.proxy.support.RestArgumentResolverComposite;
import group.flyfish.rest.registry.proxy.support.UrlCompiler;
import group.flyfish.rest.registry.wrapper.DefaultRestResultMapping;
import group.flyfish.rest.utils.DataUtils;
import group.flyfish.rest.utils.JacksonUtil;
+import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
@@ -25,14 +26,13 @@ import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import java.beans.Transient;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Map;
-import java.util.stream.Stream;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Rest代理执行器
@@ -42,13 +42,17 @@ import java.util.stream.Stream;
@Slf4j
public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurable {
+ // 方法缓存
+ private final Map methods = new ConcurrentHashMap<>();
// 要代理的目标类
private final Class> targetType;
// 服务映射
private final RestService restService;
// 配置属性
+ @Getter
private RestClientProperties properties;
// 初始的基本路径
+ @Getter
private String baseUrl;
// 超时时间
private RequestConfig config;
@@ -59,6 +63,7 @@ public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurab
// 鉴权提供者
private RestAuthProvider authProvider;
+
/**
* 构造器
*
@@ -103,34 +108,27 @@ public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurab
* 执行rest请求的地方,这里很简单易懂
*
* @param proxy 代理对象
- * @param method 代理方法
+ * @param target 代理方法
* @param args 参数
* @return 结果
* @throws Throwable 可能抛出的异常
*/
@Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // 处理基本方法被代理的情况
- if (AopUtils.isEqualsMethod(method)) {
- Object obj = args[0];
- // The target does not implement the equals(Object) method itself.
- return null != obj && ClassUtils.isAssignable(targetType, obj.getClass());
- } else if (AopUtils.isHashCodeMethod(method)) {
- // The target does not implement the hashCode() method itself.
- return -1;
- }
- // 无视proxy,因为啥也没
- RestApi restApi = AnnotationUtils.findAnnotation(method, RestApi.class);
- if (null == restApi) {
+ public Object invoke(Object proxy, Method target, Object[] args) throws Throwable {
+ // 解析方法,做基本验证
+ RestMethod method = methods.computeIfAbsent(target.hashCode(), k -> RestMethod.resolve(target, this));
+ if (method.isInvalid()) {
throw new IllegalAccessException("【Rest调用】未声明rest配置的方法被调用!请检查代码!");
}
RestArgumentResolverComposite composite = registry.getComposite();
// 第一步就解析参数
- ArgumentResolveContext context = composite.resolve(restApi, method, args);
+ ArgumentResolveContext context = composite.resolve(method, args);
// 构造和调用,这里的restClient不保存状态
- RestClientBuilder builder = RestClient.create().url(determineUrl(restApi, context)).method(restApi.method()).config(config);
+ RestClientBuilder builder = RestClient.create().url(resolveUrl(method.getUrl(), context))
+ .method(method.getMethod())
+ .config(config);
// 需要带cookie的带上
- if (restApi.credentials()) {
+ if (method.isCredentials()) {
builder.withCredential();
}
// 判断情况,赋值参数
@@ -162,7 +160,7 @@ public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurab
// 设置客户端
client.setClient(registry.getProvider());
// 是否对结果进行映射
- boolean map = null != mapping && null == AnnotationUtils.findAnnotation(method, Transient.class);
+ boolean map = null != mapping && method.isBare();
// 执行请求
Object result = execute(client, method, map);
// 结果映射
@@ -177,7 +175,7 @@ public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurab
* @param map 是否映射结果
* @return 结果
*/
- private Object execute(RestClient client, Method method, boolean map) throws IOException {
+ private Object execute(RestClient client, RestMethod method, boolean map) throws IOException {
// 构建带泛型的返回值,自动判断是否是简单类型
JavaType constructed = JacksonUtil.getMapper().constructType(method.getGenericReturnType());
// 特殊处理映射
@@ -236,21 +234,7 @@ public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurab
*
* @return 结果
*/
- private String determineUrl(RestApi restApi, ArgumentResolveContext context) {
- String url;
- // 解析url以支持PathVariable
- if (DataUtils.isNotBlank(restApi.url())) {
- url = restApi.url();
- } else {
- // 构建基础url,优先级从小到大依次找。同时尝试取字典值
- url = Stream.of(restApi.baseUrl(), this.baseUrl)
- .filter(DataUtils::isNotBlank)
- .findFirst()
- // 判定和赋值
- .map(found -> found.startsWith("#") ? properties.getDictUrl(found.substring(1)) : found)
- .map(base -> base + restApi.uri())
- .orElseThrow(() -> new IllegalArgumentException("【Rest调用】未指定url或baseurl,无法调用远端服务器!"));
- }
+ private String resolveUrl(String url, ArgumentResolveContext context) {
// 尝试解析路径参数
return context.hasPathParams() ? UrlCompiler.compile(url, context.getPathParams()) : url;
}
@@ -268,4 +252,25 @@ public class RestProxyInvoker implements InvocationHandler, PropertiesConfigurab
}
return properties.getAuthProvider();
}
+
+ /**
+ * 如果调用到了Object类的方法,则绕行
+ *
+ * @param method 方法
+ * @param args 参数
+ * @return 结果
+ */
+ @Deprecated
+ private Object passObjectMethod(Method method, Object[] args) {
+ // 处理基本方法被代理的情况
+ if (AopUtils.isEqualsMethod(method)) {
+ Object obj = args[0];
+ // The target does not implement the equals(Object) method itself.
+ return null != obj && ClassUtils.isAssignable(targetType, obj.getClass());
+ } else if (AopUtils.isHashCodeMethod(method)) {
+ // The target does not implement the hashCode() method itself.
+ return -1;
+ }
+ return null;
+ }
}
diff --git a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/entity/RestMethod.java b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/entity/RestMethod.java
new file mode 100644
index 0000000..a0eb409
--- /dev/null
+++ b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/entity/RestMethod.java
@@ -0,0 +1,117 @@
+package group.flyfish.rest.registry.proxy.entity;
+
+import group.flyfish.rest.annotation.RestApi;
+import group.flyfish.rest.enums.HttpMethod;
+import group.flyfish.rest.registry.proxy.RestProxyInvoker;
+import group.flyfish.rest.utils.DataUtils;
+import lombok.Getter;
+import org.springframework.core.annotation.AnnotationUtils;
+
+import java.beans.Transient;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
+import java.util.stream.Stream;
+
+/**
+ * 表示单个请求的最小单元
+ *
+ * @author wangyu
+ */
+public class RestMethod {
+
+ // 方法参数缓存,避免clone
+ @Getter
+ private Parameter[] parameters;
+
+ // 解析@Transient注解的结果
+ @Getter
+ private boolean bare;
+
+ // 解析后的路径
+ @Getter
+ private String url;
+
+ // http方法
+ @Getter
+ private HttpMethod method;
+
+ // 是否携带cookie
+ @Getter
+ private boolean credentials;
+
+ // 多个参数时使用合并的body
+ @Getter
+ private boolean mergeBody;
+
+ // 带泛型的返回类型
+ @Getter
+ private Type genericReturnType;
+
+ // 不带泛型的返回类型
+ @Getter
+ private Class> returnType;
+
+ // 是否不可用状态
+ @Getter
+ private boolean invalid;
+
+ private RestMethod(Method method, RestProxyInvoker invoker) {
+ // 执行初始化
+ init(method, invoker);
+ }
+
+ /**
+ * 解析代理方法
+ *
+ * @param method 方法
+ * @return 结果
+ */
+ public static RestMethod resolve(Method method, RestProxyInvoker invoker) {
+ return new RestMethod(method, invoker);
+ }
+
+ /**
+ * 初始化方法
+ */
+ private void init(Method method, RestProxyInvoker invoker) {
+ RestApi restApi = AnnotationUtils.findAnnotation(method, RestApi.class);
+ // 无视proxy,因为啥也没
+ if (null == restApi) {
+ this.invalid = true;
+ return;
+ }
+ this.url = determineUrl(restApi, invoker);
+ this.method = restApi.method();
+ this.credentials = restApi.credentials();
+ this.mergeBody = restApi.mergedBody();
+ this.parameters = method.getParameters();
+ this.bare = null != AnnotationUtils.findAnnotation(method, Transient.class);
+ this.genericReturnType = method.getGenericReturnType();
+ this.returnType = method.getReturnType();
+ }
+
+ /**
+ * 决定基本url,优先级: 方法注解url > 方法注解baseUrl + uri > 全局配置 + uri
+ *
+ * @return 结果
+ */
+ private String determineUrl(RestApi restApi, RestProxyInvoker invoker) {
+ String url;
+ // 解析url以支持PathVariable
+ if (DataUtils.isNotBlank(restApi.url())) {
+ return restApi.url();
+ } else {
+ // 构建基础url,优先级从小到大依次找。同时尝试取字典值
+ return Stream.of(restApi.baseUrl(), invoker.getBaseUrl())
+ .filter(DataUtils::isNotBlank)
+ .findFirst()
+ // 判定和赋值
+ .map(found -> found.startsWith("#") ?
+ invoker.getProperties().getDictUrl(found.substring(1)) : found)
+ .map(base -> base + restApi.uri())
+ .orElseThrow(() -> new IllegalArgumentException("【Rest调用】未指定url或baseurl,无法调用远端服务器!"));
+ }
+ }
+
+}
diff --git a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/ArgumentResolveContext.java b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/ArgumentResolveContext.java
index 8ba537d..07ffb64 100644
--- a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/ArgumentResolveContext.java
+++ b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/ArgumentResolveContext.java
@@ -1,7 +1,7 @@
package group.flyfish.rest.registry.proxy.support;
-import group.flyfish.rest.annotation.RestApi;
import group.flyfish.rest.entity.Multipart;
+import group.flyfish.rest.registry.proxy.entity.RestMethod;
import group.flyfish.rest.utils.DataUtils;
import lombok.Builder;
import lombok.Data;
@@ -18,8 +18,8 @@ import java.util.Map;
@Builder
public class ArgumentResolveContext {
- // 注解
- private RestApi annotation;
+ // 解析的方法
+ private RestMethod method;
// 参数
private Map param;
diff --git a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/RestArgumentResolverComposite.java b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/RestArgumentResolverComposite.java
index 59596fe..e3526ca 100644
--- a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/RestArgumentResolverComposite.java
+++ b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/RestArgumentResolverComposite.java
@@ -1,8 +1,7 @@
package group.flyfish.rest.registry.proxy.support;
-import group.flyfish.rest.annotation.RestApi;
+import group.flyfish.rest.registry.proxy.entity.RestMethod;
-import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.stream.IntStream;
@@ -24,14 +23,13 @@ public class RestArgumentResolverComposite {
/**
* 执行解析
*
- * @param annotation 注解
- * @param method 方法
- * @param args 参数
+ * @param method 方法
+ * @param args 参数
* @return 结果
*/
- public ArgumentResolveContext resolve(RestApi annotation, Method method, Object[] args) {
+ public ArgumentResolveContext resolve(RestMethod method, Object[] args) {
// 上下文
- ArgumentResolveContext context = ArgumentResolveContext.builder().annotation(annotation).build();
+ ArgumentResolveContext context = ArgumentResolveContext.builder().method(method).build();
// 参数元
Parameter[] parameters = method.getParameters();
// 循环处理
diff --git a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/resolvers/RestParamArgumentResolver.java b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/resolvers/RestParamArgumentResolver.java
index 39faf12..271dfb8 100644
--- a/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/resolvers/RestParamArgumentResolver.java
+++ b/rest-proxy-core/src/main/java/group/flyfish/rest/registry/proxy/support/resolvers/RestParamArgumentResolver.java
@@ -53,7 +53,7 @@ public class RestParamArgumentResolver implements RestArgumentResolver {
.filter(DataUtils::isNotBlank)
.orElse(parameter.getName());
// 启用合并请求体,合并入
- if (context.getAnnotation().mergedBody()) {
+ if (context.getMethod().isMergeBody()) {
context.setBody(name, value);
} else {
context.setParam(name, value);