feat: 优化核心代码
This commit is contained in:
parent
402bcb120f
commit
4dabcf6ed1
@ -1,6 +1,7 @@
|
|||||||
package group.flyfish.rest.configuration;
|
package group.flyfish.rest.configuration;
|
||||||
|
|
||||||
import group.flyfish.rest.annotation.EnableRestApiProxy;
|
import group.flyfish.rest.core.factory.HttpClientFactoryBean;
|
||||||
|
import group.flyfish.rest.core.factory.HttpClientProvider;
|
||||||
import group.flyfish.rest.mapping.RestResultMapping;
|
import group.flyfish.rest.mapping.RestResultMapping;
|
||||||
import group.flyfish.rest.registry.RestApiRegistry;
|
import group.flyfish.rest.registry.RestApiRegistry;
|
||||||
import group.flyfish.rest.registry.proxy.support.RestArgumentResolver;
|
import group.flyfish.rest.registry.proxy.support.RestArgumentResolver;
|
||||||
@ -10,14 +11,11 @@ import group.flyfish.rest.registry.proxy.support.resolvers.RestHeaderArgumentRes
|
|||||||
import group.flyfish.rest.registry.proxy.support.resolvers.RestParamArgumentResolver;
|
import group.flyfish.rest.registry.proxy.support.resolvers.RestParamArgumentResolver;
|
||||||
import group.flyfish.rest.registry.proxy.support.resolvers.RestPathParamArgumentResolver;
|
import group.flyfish.rest.registry.proxy.support.resolvers.RestPathParamArgumentResolver;
|
||||||
import group.flyfish.rest.utils.DataUtils;
|
import group.flyfish.rest.utils.DataUtils;
|
||||||
import group.flyfish.rest.utils.IocBeans;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -28,9 +26,42 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
@EnableConfigurationProperties(RestClientProperties.class)
|
|
||||||
public class RestClientConfiguration {
|
public class RestClientConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化参数bean
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix = "rest.client", ignoreUnknownFields = false)
|
||||||
|
@Bean
|
||||||
|
public RestClientProperties restClientProperties() {
|
||||||
|
return new RestClientProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http client工厂bean
|
||||||
|
*
|
||||||
|
* @param properties 属性
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(CloseableHttpClient.class)
|
||||||
|
public HttpClientFactoryBean httpClientFactoryBean(RestClientProperties properties) {
|
||||||
|
return new HttpClientFactoryBean(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认的提供者,默认使用factory bean创建的client
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public HttpClientProvider httpClientProvider(CloseableHttpClient client) {
|
||||||
|
return () -> client;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册rest自动代理
|
* 注册rest自动代理
|
||||||
*
|
*
|
||||||
@ -38,25 +69,14 @@ public class RestClientConfiguration {
|
|||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@Lazy
|
@Lazy
|
||||||
public RestApiRegistry restApiRegistry(RestArgumentResolverComposite composite,
|
public RestApiRegistry restApiRegistry(RestArgumentResolverComposite composite, HttpClientProvider provider,
|
||||||
List<RestResultMapping> mappings) {
|
List<RestResultMapping> mappings, RestClientProperties properties) {
|
||||||
// 先注册映射们
|
// 先注册映射们
|
||||||
if (DataUtils.isNotEmpty(mappings)) {
|
if (DataUtils.isNotEmpty(mappings)) {
|
||||||
mappings.forEach(mapping -> RestResultMapping.MAPPINGS.put(mapping.getClass(), mapping));
|
mappings.forEach(mapping -> RestResultMapping.MAPPINGS.put(mapping.getClass(), mapping));
|
||||||
}
|
}
|
||||||
// 最后实例化
|
// 最后实例化
|
||||||
return new RestApiRegistry(composite);
|
return new RestApiRegistry(composite, properties, provider);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IOC容器操作
|
|
||||||
*
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(name = "iocBeans")
|
|
||||||
public IocBeans iocBeans() {
|
|
||||||
return new IocBeans();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package group.flyfish.rest.configuration;
|
package group.flyfish.rest.configuration;
|
||||||
|
|
||||||
import group.flyfish.rest.registry.RestApiRegistry;
|
|
||||||
import group.flyfish.rest.utils.DataUtils;
|
import group.flyfish.rest.utils.DataUtils;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -19,12 +15,8 @@ import java.util.Map;
|
|||||||
* 整合入spring boot,简化配置,提高业务复用性
|
* 整合入spring boot,简化配置,提高业务复用性
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ConfigurationProperties(prefix = "rest.client", ignoreUnknownFields = false)
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RestClientProperties implements InitializingBean {
|
public class RestClientProperties {
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RestApiRegistry restApiRegistry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 超时时间,默认30s
|
* 超时时间,默认30s
|
||||||
@ -58,10 +50,4 @@ public class RestClientProperties implements InitializingBean {
|
|||||||
}
|
}
|
||||||
return urls.get(key);
|
return urls.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
log.info("initialized rest client properties。 baseUrl is:{}", this.baseUrl);
|
|
||||||
restApiRegistry.initialize(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package group.flyfish.rest.core.client;
|
|||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
import group.flyfish.rest.core.exception.RestClientException;
|
import group.flyfish.rest.core.exception.RestClientException;
|
||||||
|
import group.flyfish.rest.core.factory.HttpClientProvider;
|
||||||
import group.flyfish.rest.enums.ResponseType;
|
import group.flyfish.rest.enums.ResponseType;
|
||||||
import group.flyfish.rest.utils.JacksonUtil;
|
import group.flyfish.rest.utils.JacksonUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -47,6 +48,17 @@ final class DefaultRestClient implements RestClient {
|
|||||||
private Class<?> resultClass;
|
private Class<?> resultClass;
|
||||||
private TypeReference<?> typeReference;
|
private TypeReference<?> typeReference;
|
||||||
private JavaType resultType;
|
private JavaType resultType;
|
||||||
|
private HttpClientProvider clientProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部构造方法,不对外公开
|
||||||
|
*
|
||||||
|
* @param request 请求信息
|
||||||
|
*/
|
||||||
|
DefaultRestClient(HttpRequestBase request, HttpClientProvider provider) {
|
||||||
|
this.request = request;
|
||||||
|
this.clientProvider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内部构造方法,不对外公开
|
* 内部构造方法,不对外公开
|
||||||
@ -94,6 +106,16 @@ final class DefaultRestClient implements RestClient {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置客户端提供者
|
||||||
|
*
|
||||||
|
* @param provider 客户端提供者
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setClient(HttpClientProvider provider) {
|
||||||
|
this.clientProvider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标记线程池执行
|
* 标记线程池执行
|
||||||
*
|
*
|
||||||
@ -260,7 +282,7 @@ final class DefaultRestClient implements RestClient {
|
|||||||
*/
|
*/
|
||||||
private <T> T innerExecute() throws IOException {
|
private <T> T innerExecute() throws IOException {
|
||||||
log.info("【Rest Invoke】{} {}", request.getMethod(), request.getURI());
|
log.info("【Rest Invoke】{} {}", request.getMethod(), request.getURI());
|
||||||
try (CloseableHttpResponse response = HttpClientCache.getClient().execute(request)) {
|
try (CloseableHttpResponse response = clientProvider.getClient().execute(request)) {
|
||||||
StatusLine statusLine = response.getStatusLine();
|
StatusLine statusLine = response.getStatusLine();
|
||||||
if (200 == statusLine.getStatusCode()) {
|
if (200 == statusLine.getStatusCode()) {
|
||||||
HttpEntity entity = response.getEntity();
|
HttpEntity entity = response.getEntity();
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
package group.flyfish.rest.core.client;
|
|
||||||
|
|
||||||
import group.flyfish.rest.core.produce.HttpClientProducer;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* http请求客户端缓存
|
|
||||||
*
|
|
||||||
* @author wangyu
|
|
||||||
*/
|
|
||||||
class HttpClientCache {
|
|
||||||
|
|
||||||
private volatile CloseableHttpClient client;
|
|
||||||
|
|
||||||
private static final HttpClientCache INSTANCE = new HttpClientCache();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取共享client
|
|
||||||
*
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
CloseableHttpClient computeClient() throws IOException {
|
|
||||||
if (null == client) {
|
|
||||||
synchronized (INSTANCE) {
|
|
||||||
if (null != client) return client;
|
|
||||||
return client = HttpClientProducer.produce();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CloseableHttpClient getClient() throws IOException {
|
|
||||||
return INSTANCE.computeClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setClient(CloseableHttpClient client) {
|
|
||||||
INSTANCE.client = client;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,9 +3,9 @@ package group.flyfish.rest.core.client;
|
|||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
import group.flyfish.rest.core.exception.RestClientException;
|
import group.flyfish.rest.core.exception.RestClientException;
|
||||||
|
import group.flyfish.rest.core.factory.HttpClientProvider;
|
||||||
import group.flyfish.rest.enums.ResponseType;
|
import group.flyfish.rest.enums.ResponseType;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -37,13 +37,11 @@ public interface RestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置单例的客户端
|
* 设置客户端提供者
|
||||||
*
|
*
|
||||||
* @param client 客户端
|
* @param provider 客户端提供者
|
||||||
*/
|
*/
|
||||||
static void setClient(CloseableHttpClient client) {
|
void setClient(HttpClientProvider provider);
|
||||||
HttpClientCache.setClient(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标记线程池执行
|
* 标记线程池执行
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package group.flyfish.rest.core.produce;
|
package group.flyfish.rest.core.factory;
|
||||||
|
|
||||||
import group.flyfish.rest.configuration.RestClientProperties;
|
import group.flyfish.rest.configuration.RestClientProperties;
|
||||||
import group.flyfish.rest.utils.DataUtils;
|
import group.flyfish.rest.utils.DataUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.ssl.SSLContextBuilder;
|
import org.apache.http.ssl.SSLContextBuilder;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import java.io.NotActiveException;
|
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@ -21,63 +22,22 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class HttpClientProducer {
|
@RequiredArgsConstructor
|
||||||
|
public final class HttpClientFactoryBean implements FactoryBean<CloseableHttpClient> {
|
||||||
|
|
||||||
// 使用非公平锁
|
// 使用非公平锁
|
||||||
private static final ReentrantLock lock = new ReentrantLock();
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
// 客户端实例,单例
|
// 客户端实例,单例
|
||||||
private static volatile CloseableHttpClient client;
|
private static volatile CloseableHttpClient client;
|
||||||
// 配置,配置没进来就不初始化
|
// 配置,配置没进来就不初始化
|
||||||
private static RestClientProperties properties;
|
private final RestClientProperties properties;
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置信息
|
|
||||||
*
|
|
||||||
* @param properties 属性
|
|
||||||
*/
|
|
||||||
public static void configure(RestClientProperties properties) {
|
|
||||||
HttpClientProducer.properties = properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取属性
|
|
||||||
*
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
public static RestClientProperties getProperties() {
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产客户端
|
|
||||||
*
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
public static CloseableHttpClient produce() throws NotActiveException {
|
|
||||||
if (properties == null) {
|
|
||||||
log.warn("【rest客户端】未初始化rest客户端配置,生产者未就绪!将使用默认配置!!!");
|
|
||||||
properties = new RestClientProperties();
|
|
||||||
}
|
|
||||||
if (client == null) {
|
|
||||||
// 非公平锁,二次判定,定位volatile
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
if (client == null) {
|
|
||||||
client = getClient();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建单例的httpClient
|
* 构建单例的httpClient
|
||||||
*
|
*
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
private static CloseableHttpClient getClient() {
|
private CloseableHttpClient getClient() {
|
||||||
return DataUtils.isTrue(properties.getAlwaysTrust()) ? createSSLClient() : HttpClients.createDefault();
|
return DataUtils.isTrue(properties.getAlwaysTrust()) ? createSSLClient() : HttpClients.createDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,4 +58,24 @@ public final class HttpClientProducer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloseableHttpClient getObject() throws Exception {
|
||||||
|
if (client == null) {
|
||||||
|
// 非公平锁,二次判定,定位volatile
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
if (client == null) {
|
||||||
|
client = getClient();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getObjectType() {
|
||||||
|
return CloseableHttpClient.class;
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package group.flyfish.rest.core.factory;
|
||||||
|
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http客户端提供者
|
||||||
|
*
|
||||||
|
* @author wangyu
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface HttpClientProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取client,可以自由替换
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
CloseableHttpClient getClient();
|
||||||
|
}
|
@ -2,12 +2,12 @@ package group.flyfish.rest.registry;
|
|||||||
|
|
||||||
import group.flyfish.rest.annotation.EnableRestApiProxy;
|
import group.flyfish.rest.annotation.EnableRestApiProxy;
|
||||||
import group.flyfish.rest.annotation.RestService;
|
import group.flyfish.rest.annotation.RestService;
|
||||||
import group.flyfish.rest.core.client.RestClient;
|
|
||||||
import group.flyfish.rest.configuration.RestClientProperties;
|
import group.flyfish.rest.configuration.RestClientProperties;
|
||||||
import group.flyfish.rest.core.produce.HttpClientProducer;
|
import group.flyfish.rest.core.factory.HttpClientProvider;
|
||||||
import group.flyfish.rest.registry.proxy.RestProxyInvoker;
|
import group.flyfish.rest.registry.proxy.RestProxyInvoker;
|
||||||
import group.flyfish.rest.registry.proxy.support.RestArgumentResolverComposite;
|
import group.flyfish.rest.registry.proxy.support.RestArgumentResolverComposite;
|
||||||
import group.flyfish.rest.utils.DataUtils;
|
import group.flyfish.rest.utils.DataUtils;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -15,11 +15,11 @@ import org.reflections.Reflections;
|
|||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.*;
|
import org.springframework.beans.factory.support.*;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.io.NotActiveException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -33,20 +33,18 @@ import java.util.Set;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class RestApiRegistry implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware {
|
public class RestApiRegistry implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final RestArgumentResolverComposite composite;
|
private final RestArgumentResolverComposite composite;
|
||||||
|
|
||||||
// 包名
|
@Getter
|
||||||
private final List<String> packageNames = new ArrayList<>();
|
private final RestClientProperties properties;
|
||||||
|
|
||||||
// 注册的执行器们,最终会使用配置进行初始化
|
@Getter
|
||||||
private final List<RestProxyInvoker<?>> invokers = new ArrayList<>();
|
private final HttpClientProvider provider;
|
||||||
|
|
||||||
// bean工厂
|
// bean工厂
|
||||||
private ConfigurableListableBeanFactory beanFactory;
|
private ConfigurableListableBeanFactory beanFactory;
|
||||||
|
|
||||||
// rest请求参数
|
|
||||||
private RestClientProperties properties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态注册bean
|
* 动态注册bean
|
||||||
*
|
*
|
||||||
@ -55,6 +53,8 @@ public class RestApiRegistry implements BeanDefinitionRegistryPostProcessor, Bea
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
||||||
|
// 包名
|
||||||
|
List<String> packageNames = new ArrayList<>();
|
||||||
// 找基本包,找不到立马报错
|
// 找基本包,找不到立马报错
|
||||||
beanFactory.getBeansWithAnnotation(EnableRestApiProxy.class)
|
beanFactory.getBeansWithAnnotation(EnableRestApiProxy.class)
|
||||||
.forEach((key, value) -> {
|
.forEach((key, value) -> {
|
||||||
@ -73,11 +73,7 @@ public class RestApiRegistry implements BeanDefinitionRegistryPostProcessor, Bea
|
|||||||
// 得到Resource注解的类
|
// 得到Resource注解的类
|
||||||
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(RestService.class);
|
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(RestService.class);
|
||||||
// 代理并生成子类,并注册到ioc容器
|
// 代理并生成子类,并注册到ioc容器
|
||||||
classSet.forEach(clazz -> registry.registerBeanDefinition(clazz.getName(),
|
classSet.forEach(clazz -> registry.registerBeanDefinition(clazz.getName(), generate(clazz)));
|
||||||
BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> DataUtils.cast(RestProxyInvoker
|
|
||||||
.produce(clazz, composite, this::bindInvoker)))
|
|
||||||
.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE).getRawBeanDefinition())
|
|
||||||
);
|
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
log.error("初始化Rest映射时出错", e);
|
log.error("初始化Rest映射时出错", e);
|
||||||
}
|
}
|
||||||
@ -87,35 +83,15 @@ public class RestApiRegistry implements BeanDefinitionRegistryPostProcessor, Bea
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化bean们
|
* 生成bean定义
|
||||||
*
|
*
|
||||||
* @param properties 属性
|
* @param clazz 目标类型
|
||||||
* @throws NotActiveException 未活动异常
|
* @return bean定义
|
||||||
*/
|
*/
|
||||||
public void initialize(RestClientProperties properties) throws NotActiveException {
|
private BeanDefinition generate(Class<?> clazz) {
|
||||||
log.info("bean加载完成");
|
return BeanDefinitionBuilder.genericBeanDefinition(clazz,
|
||||||
// 真正加载完成的回调
|
() -> DataUtils.cast(RestProxyInvoker.produce(clazz, this)))
|
||||||
this.properties = properties;
|
.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE).getRawBeanDefinition();
|
||||||
// 配置参数
|
|
||||||
HttpClientProducer.configure(properties);
|
|
||||||
// 最后再配置,生成
|
|
||||||
RestClient.setClient(HttpClientProducer.produce());
|
|
||||||
// 初始化
|
|
||||||
this.invokers.forEach(invoker -> invoker.configure(properties));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 绑定执行器
|
|
||||||
*
|
|
||||||
* @param invoker 执行器
|
|
||||||
* @param <T> 泛型
|
|
||||||
*/
|
|
||||||
private <T> void bindInvoker(RestProxyInvoker<T> invoker) {
|
|
||||||
if (properties == null) {
|
|
||||||
this.invokers.add(invoker);
|
|
||||||
} else {
|
|
||||||
invoker.configure(properties);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
|
@ -8,6 +8,7 @@ import group.flyfish.rest.configuration.RestClientProperties;
|
|||||||
import group.flyfish.rest.core.client.RestClient;
|
import group.flyfish.rest.core.client.RestClient;
|
||||||
import group.flyfish.rest.core.client.RestClientBuilder;
|
import group.flyfish.rest.core.client.RestClientBuilder;
|
||||||
import group.flyfish.rest.mapping.RestResultMapping;
|
import group.flyfish.rest.mapping.RestResultMapping;
|
||||||
|
import group.flyfish.rest.registry.RestApiRegistry;
|
||||||
import group.flyfish.rest.registry.proxy.support.ArgumentResolveContext;
|
import group.flyfish.rest.registry.proxy.support.ArgumentResolveContext;
|
||||||
import group.flyfish.rest.registry.proxy.support.RestArgumentResolverComposite;
|
import group.flyfish.rest.registry.proxy.support.RestArgumentResolverComposite;
|
||||||
import group.flyfish.rest.registry.proxy.support.UrlCompiler;
|
import group.flyfish.rest.registry.proxy.support.UrlCompiler;
|
||||||
@ -18,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
import java.beans.Transient;
|
import java.beans.Transient;
|
||||||
@ -28,7 +30,6 @@ import java.lang.reflect.Proxy;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,31 +42,35 @@ public class RestProxyInvoker<T> implements InvocationHandler {
|
|||||||
|
|
||||||
// 要代理的目标类
|
// 要代理的目标类
|
||||||
private final Class<T> targetType;
|
private final Class<T> targetType;
|
||||||
// 解析集合
|
|
||||||
private final RestArgumentResolverComposite composite;
|
|
||||||
// 服务映射
|
// 服务映射
|
||||||
private final RestService restService;
|
private final RestService restService;
|
||||||
// 初始的基本路径
|
// 初始的基本路径
|
||||||
private String baseUrl;
|
private final String baseUrl;
|
||||||
// 超时时间
|
// 超时时间
|
||||||
private RequestConfig config;
|
private final RequestConfig config;
|
||||||
// 基础url
|
// 注册器,包含基础信息
|
||||||
private RestClientProperties properties;
|
private final RestApiRegistry registry;
|
||||||
// 结果映射
|
// 结果映射
|
||||||
private RestResultMapping mapping;
|
private RestResultMapping mapping;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造器
|
* 构造器
|
||||||
*
|
*
|
||||||
* @param targetType 目标类型
|
* @param targetType 目标类型
|
||||||
* @param composite 解析器
|
* @param registry 注册器
|
||||||
*/
|
*/
|
||||||
public RestProxyInvoker(Class<T> targetType, RestArgumentResolverComposite composite) {
|
private RestProxyInvoker(Class<T> targetType, RestApiRegistry registry) {
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
this.composite = composite;
|
this.registry = registry;
|
||||||
// 注解的优先级高于全局基本路径
|
// 注解的优先级高于全局基本路径
|
||||||
this.restService = AnnotationUtils.findAnnotation(targetType, RestService.class);
|
this.restService = AnnotationUtils.findAnnotation(targetType, RestService.class);
|
||||||
|
Assert.notNull(restService, "当前类尚未添加@RestService注解!");
|
||||||
|
RestClientProperties properties = registry.getProperties();
|
||||||
|
this.config = RequestConfig.custom()
|
||||||
|
.setConnectTimeout((int) properties.getConnectionTimeout().toMillis())
|
||||||
|
.setSocketTimeout(restService.timeout())
|
||||||
|
.build();
|
||||||
|
this.baseUrl = this.findBaseUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,27 +80,11 @@ public class RestProxyInvoker<T> implements InvocationHandler {
|
|||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public static <T> T produce(Class<T> target, RestArgumentResolverComposite composite, Consumer<RestProxyInvoker<T>> consumer) {
|
public static <T> T produce(Class<T> target, RestApiRegistry registry) {
|
||||||
RestProxyInvoker<T> invoker = new RestProxyInvoker<>(target, composite);
|
RestProxyInvoker<T> invoker = new RestProxyInvoker<>(target, registry);
|
||||||
consumer.accept(invoker);
|
|
||||||
return DataUtils.cast(Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, invoker));
|
return DataUtils.cast(Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, invoker));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用配置信息对接口进行配置
|
|
||||||
*
|
|
||||||
* @param properties 配置
|
|
||||||
*/
|
|
||||||
public void configure(RestClientProperties properties) {
|
|
||||||
this.properties = properties;
|
|
||||||
this.config = RequestConfig.custom()
|
|
||||||
.setConnectTimeout((int) properties.getConnectionTimeout().toMillis())
|
|
||||||
.setSocketTimeout(restService.timeout())
|
|
||||||
.build();
|
|
||||||
this.baseUrl = this.findBaseUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行rest请求的地方,这里很简单易懂
|
* 执行rest请求的地方,这里很简单易懂
|
||||||
*
|
*
|
||||||
@ -121,6 +110,7 @@ public class RestProxyInvoker<T> implements InvocationHandler {
|
|||||||
if (null == restApi) {
|
if (null == restApi) {
|
||||||
throw new IllegalAccessException("【Rest调用】未声明rest配置的方法被调用!请检查代码!");
|
throw new IllegalAccessException("【Rest调用】未声明rest配置的方法被调用!请检查代码!");
|
||||||
}
|
}
|
||||||
|
RestArgumentResolverComposite composite = registry.getComposite();
|
||||||
// 第一步就解析参数
|
// 第一步就解析参数
|
||||||
ArgumentResolveContext context = composite.resolve(restApi, method, args);
|
ArgumentResolveContext context = composite.resolve(restApi, method, args);
|
||||||
// 构造和调用,这里的restClient不保存状态
|
// 构造和调用,这里的restClient不保存状态
|
||||||
@ -146,6 +136,8 @@ public class RestProxyInvoker<T> implements InvocationHandler {
|
|||||||
}
|
}
|
||||||
// 赋值头部
|
// 赋值头部
|
||||||
RestClient client = builder.build();
|
RestClient client = builder.build();
|
||||||
|
// 设置客户端
|
||||||
|
client.setClient(registry.getProvider());
|
||||||
// 是否对结果进行映射
|
// 是否对结果进行映射
|
||||||
boolean map = null != mapping && null == AnnotationUtils.findAnnotation(method, Transient.class);
|
boolean map = null != mapping && null == AnnotationUtils.findAnnotation(method, Transient.class);
|
||||||
// 执行请求
|
// 执行请求
|
||||||
@ -188,6 +180,7 @@ public class RestProxyInvoker<T> implements InvocationHandler {
|
|||||||
* 找到配置固化的基本url
|
* 找到配置固化的基本url
|
||||||
*/
|
*/
|
||||||
private String findBaseUrl() {
|
private String findBaseUrl() {
|
||||||
|
RestClientProperties properties = registry.getProperties();
|
||||||
// 当且仅当存在时进入
|
// 当且仅当存在时进入
|
||||||
if (null != restService) {
|
if (null != restService) {
|
||||||
// 注解的路径解析
|
// 注解的路径解析
|
||||||
@ -227,6 +220,7 @@ public class RestProxyInvoker<T> implements InvocationHandler {
|
|||||||
if (DataUtils.isNotBlank(restApi.url())) {
|
if (DataUtils.isNotBlank(restApi.url())) {
|
||||||
url = restApi.url();
|
url = restApi.url();
|
||||||
} else {
|
} else {
|
||||||
|
RestClientProperties properties = registry.getProperties();
|
||||||
// 构建基础url,优先级从小到大依次找。同时尝试取字典值
|
// 构建基础url,优先级从小到大依次找。同时尝试取字典值
|
||||||
Optional<String> baseUrl = Stream.of(restApi.baseUrl(), this.baseUrl)
|
Optional<String> baseUrl = Stream.of(restApi.baseUrl(), this.baseUrl)
|
||||||
.filter(DataUtils::isNotBlank)
|
.filter(DataUtils::isNotBlank)
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
package group.flyfish.rest.utils;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class IocBeans implements ApplicationContextAware {
|
|
||||||
|
|
||||||
private static IocBeans instance;
|
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
public IocBeans() {
|
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IocBeans sharedInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IocBeans sharedInstance(ApplicationContext applicationContext) {
|
|
||||||
if (null != instance && null == instance.applicationContext) {
|
|
||||||
instance.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册bean
|
|
||||||
*
|
|
||||||
* @param name bean的名称
|
|
||||||
* @param beanClass bean的类
|
|
||||||
* @param beanSupplier bean实例化
|
|
||||||
*/
|
|
||||||
public static <T> T registerBean(String name, Class<T> beanClass, Supplier<T> beanSupplier) {
|
|
||||||
return sharedInstance().register(name, beanClass, beanSupplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册bean
|
|
||||||
*
|
|
||||||
* @param name bean的名称
|
|
||||||
* @param beanClass bean的类
|
|
||||||
* @param beanSupplier bean实例化
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> T register(String name, Class<T> beanClass, Supplier<T> beanSupplier) {
|
|
||||||
// 已经包含bean
|
|
||||||
if (applicationContext.containsBean(name)) {
|
|
||||||
Object wired = applicationContext.getBean(name);
|
|
||||||
if (wired.getClass().isAssignableFrom(beanClass)) {
|
|
||||||
return (T) wired;
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("注册RMI实例出错,Bean名称重复:" + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 构建bean定义
|
|
||||||
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(beanClass, beanSupplier)
|
|
||||||
.getRawBeanDefinition();
|
|
||||||
// 写入
|
|
||||||
return Optional.ofNullable(getBeanFactory())
|
|
||||||
.map(factory -> {
|
|
||||||
factory.registerBeanDefinition(name, beanDefinition);
|
|
||||||
return applicationContext.getBean(name, beanClass);
|
|
||||||
}).orElseThrow(() -> new RuntimeException("注册RMI实例出错,BeanFactory不存在!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取beanFactory
|
|
||||||
*
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public DefaultListableBeanFactory getBeanFactory() {
|
|
||||||
BeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
|
|
||||||
if (beanFactory == null) {
|
|
||||||
beanFactory = applicationContext.getParentBeanFactory();
|
|
||||||
}
|
|
||||||
return (DefaultListableBeanFactory) beanFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user