diff --git a/README.md b/README.md index 69ebff8..72c87c4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

Build Status - Coverage Status - Downloads + Coverage Status + Downloads

## SpringBlade微服务开发平台 @@ -14,7 +14,7 @@ * 极简封装了多租户底层,用更少的代码换来拓展性更强的SaaS多租户系统。 * 借鉴OAuth2,实现了多终端认证系统,可控制子系统的token权限互相隔离。 * 借鉴Security,封装了Secure模块,采用JWT做Token认证,可拓展集成Redis等细颗粒度控制方案。 -* 稳定生产了一年,经历了从Camden -> Greenwich的技术架构,也经历了从fat jar -> docker -> k8s + jenkins的部署架构 +* 稳定生产了一年,经历了从 Camden -> Hoxton -> 2020 的技术架构,也经历了从fat jar -> docker -> k8s + jenkins的部署架构 * 项目分包明确,规范微服务的开发模式,使包与包之间的分工清晰。 ## 架构图 diff --git a/blade-core-boot/pom.xml b/blade-core-boot/pom.xml index 2f8dd02..e972551 100644 --- a/blade-core-boot/pom.xml +++ b/blade-core-boot/pom.xml @@ -5,7 +5,7 @@ org.springblade blade-tool - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeBootAutoConfiguration.java b/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeBootAutoConfiguration.java index 7cd56b3..25308a9 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeBootAutoConfiguration.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeBootAutoConfiguration.java @@ -30,7 +30,7 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy; * @author Chill */ @Slf4j -@Configuration +@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({ BladeProperties.class }) diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeWebMvcConfiguration.java b/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeWebMvcConfiguration.java index 969597b..a875ada 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeWebMvcConfiguration.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/config/BladeWebMvcConfiguration.java @@ -31,7 +31,7 @@ import java.util.List; * @author Chill */ @Slf4j -@Configuration +@Configuration(proxyBeanMethods = false) @EnableCaching @Order(Ordered.HIGHEST_PRECEDENCE) public class BladeWebMvcConfiguration implements WebMvcConfigurer { diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/config/MybatisPlusConfiguration.java b/blade-core-boot/src/main/java/org/springblade/core/boot/config/MybatisPlusConfiguration.java index abcf4d6..ac34e87 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/config/MybatisPlusConfiguration.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/config/MybatisPlusConfiguration.java @@ -33,7 +33,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @MapperScan("org.springblade.**.mapper.**") public class MybatisPlusConfiguration { diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/config/RetryConfiguration.java b/blade-core-boot/src/main/java/org/springblade/core/boot/config/RetryConfiguration.java index 8530cf6..659d3fb 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/config/RetryConfiguration.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/config/RetryConfiguration.java @@ -28,7 +28,7 @@ import org.springframework.retry.interceptor.RetryOperationsInterceptor; * @author Chill */ @Slf4j -@Configuration +@Configuration(proxyBeanMethods = false) public class RetryConfiguration { @Bean diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/logger/RequestLogAspect.java b/blade-core-boot/src/main/java/org/springblade/core/boot/logger/RequestLogAspect.java index c36e446..6e9008d 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/logger/RequestLogAspect.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/logger/RequestLogAspect.java @@ -36,7 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean; */ @Slf4j @Aspect -@Configuration +@Configuration(proxyBeanMethods = false) @Profile({AppConstant.DEV_CODE, AppConstant.TEST_CODE}) public class RequestLogAspect { diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/tenant/TenantConfiguration.java b/blade-core-boot/src/main/java/org/springblade/core/boot/tenant/TenantConfiguration.java index 6cd8170..7693888 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/tenant/TenantConfiguration.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/tenant/TenantConfiguration.java @@ -29,7 +29,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @AutoConfigureBefore(MybatisPlusConfiguration.class) @EnableConfigurationProperties(BladeTenantProperties.class) diff --git a/blade-core-boot/src/main/resources/bootstrap.yml b/blade-core-boot/src/main/resources/bootstrap.yml index 2b3841f..238a42d 100644 --- a/blade-core-boot/src/main/resources/bootstrap.yml +++ b/blade-core-boot/src/main/resources/bootstrap.yml @@ -97,7 +97,7 @@ mybatis-plus: swagger: title: SpringBlade 接口文档系统 description: SpringBlade 接口文档系统 - version: 2.8.0 + version: 3.0.0 license: Powered By SpringBlade licenseUrl: https://bladex.vip terms-of-service-url: https://bladex.vip diff --git a/blade-core-cloud/pom.xml b/blade-core-cloud/pom.xml index 9572333..fbbfaa0 100644 --- a/blade-core-cloud/pom.xml +++ b/blade-core-cloud/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 @@ -22,42 +22,22 @@ blade-core-secure ${blade.tool.version} - - - org.springframework.retry - spring-retry - - - io.github.openfeign - feign-okhttp - 10.4.0 - org.springframework.cloud spring-cloud-starter-openfeign - - - commons-logging - commons-logging - - - + + io.github.openfeign + feign-okhttp + org.springframework.cloud - spring-cloud-starter-netflix-hystrix - - - commons-logging - commons-logging - - + spring-cloud-starter-loadbalancer - - org.springframework.boot - spring-boot-starter-actuator + org.springframework.cloud + spring-cloud-starter-bootstrap diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/client/BladeCloudApplication.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/client/BladeCloudApplication.java new file mode 100644 index 0000000..effe1d4 --- /dev/null +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/client/BladeCloudApplication.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.core.cloud.client; + +import org.springblade.core.launch.constant.AppConstant; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; +import org.springframework.cloud.openfeign.EnableFeignClients; + +import java.lang.annotation.*; + +/** + * Cloud启动注解配置 + * + * @author Chill + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@EnableDiscoveryClient +@EnableCircuitBreaker +@EnableFeignClients(AppConstant.BASE_PACKAGES) +@SpringBootApplication(exclude = RibbonAutoConfiguration.class) +public @interface BladeCloudApplication { + +} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/config/BladeCloudAutoConfiguration.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/config/BladeCloudAutoConfiguration.java new file mode 100644 index 0000000..e622088 --- /dev/null +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/config/BladeCloudAutoConfiguration.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.core.cloud.config; + +import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration; +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; +import feign.Feign; +import org.springblade.core.cloud.feign.BladeFeignSentinel; +import org.springblade.core.cloud.sentinel.BladeBlockExceptionHandler; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + + +/** + * blade cloud 增强配置 + * + * @author Chill + */ +@Configuration(proxyBeanMethods = false) +@AutoConfigureBefore(SentinelFeignAutoConfiguration.class) +public class BladeCloudAutoConfiguration { + + @Bean + @Scope("prototype") + @ConditionalOnMissingBean + @ConditionalOnProperty(name = "feign.sentinel.enabled") + public Feign.Builder feignSentinelBuilder() { + return BladeFeignSentinel.builder(); + } + + @Bean + @ConditionalOnMissingBean + public BlockExceptionHandler blockExceptionHandler() { + return new BladeBlockExceptionHandler(); + } + +} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFallbackFactory.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFallbackFactory.java index b6a524d..683fd5f 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFallbackFactory.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFallbackFactory.java @@ -16,9 +16,9 @@ package org.springblade.core.cloud.feign; import feign.Target; -import feign.hystrix.FallbackFactory; import lombok.AllArgsConstructor; import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cloud.openfeign.FallbackFactory; /** * 默认 Fallback,避免写过多fallback类 diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignAutoConfiguration.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignAutoConfiguration.java deleted file mode 100644 index 9f0315d..0000000 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignAutoConfiguration.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2013-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springblade.core.cloud.feign; - -import com.netflix.hystrix.HystrixCommand; -import feign.Contract; -import feign.Feign; -import feign.RequestInterceptor; -import feign.hystrix.HystrixFeign; -import org.springblade.core.tool.convert.EnumToStringConverter; -import org.springblade.core.tool.convert.StringToEnumConverter; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.openfeign.BladeFeignClientsRegistrar; -import org.springframework.cloud.openfeign.BladeHystrixTargeter; -import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.cloud.openfeign.Targeter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Scope; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.converter.ConverterRegistry; - -import java.util.ArrayList; - - -/** - * blade feign 增强配置 - * - * @author L.cm - */ -@Configuration -@ConditionalOnClass(Feign.class) -@Import(BladeFeignClientsRegistrar.class) -@AutoConfigureAfter(EnableFeignClients.class) -public class BladeFeignAutoConfiguration { - - @Bean - @ConditionalOnMissingBean(Targeter.class) - public Targeter bladeFeignTargeter() { - return new BladeHystrixTargeter(); - } - - @Configuration("hystrixFeignConfiguration") - @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class }) - protected static class HystrixFeignConfiguration { - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - @ConditionalOnProperty("feign.hystrix.enabled") - public Feign.Builder feignHystrixBuilder( - RequestInterceptor requestInterceptor, Contract feignContract) { - return HystrixFeign.builder() - .contract(feignContract) - .decode404() - .requestInterceptor(requestInterceptor); - } - - @Bean - @ConditionalOnMissingBean - public RequestInterceptor requestInterceptor() { - return new BladeFeignRequestHeaderInterceptor(); - } - } - - /** - * blade enum 《-》 String 转换配置 - * @param conversionService ConversionService - * @return SpringMvcContract - */ - @Bean - public Contract feignContract(@Qualifier("mvcConversionService") ConversionService conversionService) { - ConverterRegistry converterRegistry = ((ConverterRegistry) conversionService); - converterRegistry.addConverter(new EnumToStringConverter()); - converterRegistry.addConverter(new StringToEnumConverter()); - return new BladeSpringMvcContract(new ArrayList<>(), conversionService); - } -} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignFallback.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignFallback.java index 17c51c3..a31c9de 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignFallback.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignFallback.java @@ -41,7 +41,7 @@ public class BladeFeignFallback implements MethodInterceptor { private final Class targetType; private final String targetName; private final Throwable cause; - private final String code = "code"; + private final static String CODE = "code"; @Nullable @Override @@ -66,7 +66,7 @@ public class BladeFeignFallback implements MethodInterceptor { // 转换成 jsonNode 读取,因为直接转换,可能 对方放回的并 不是 R 的格式。 JsonNode resultNode = JsonUtil.readTree(content); // 判断是否 R 格式 返回体 - if (resultNode.has(code)) { + if (resultNode.has(CODE)) { return JsonUtil.getInstance().convertValue(resultNode, R.class); } return R.fail(resultNode.toString()); diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignSentinel.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignSentinel.java new file mode 100644 index 0000000..8427eab --- /dev/null +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignSentinel.java @@ -0,0 +1,136 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.core.cloud.feign; + +import com.alibaba.cloud.sentinel.feign.SentinelContractHolder; +import feign.Contract; +import feign.Feign; +import feign.InvocationHandlerFactory; +import feign.Target; +import lombok.SneakyThrows; +import org.springblade.core.cloud.sentinel.BladeSentinelInvocationHandler; +import org.springframework.beans.BeansException; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.cloud.openfeign.FeignContext; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Map; + +/** + * feign集成sentinel自动配置 + * 重写 {@link com.alibaba.cloud.sentinel.feign.SentinelFeign} 适配最新API + * + * @author Chill + */ +public class BladeFeignSentinel { + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder extends Feign.Builder + implements ApplicationContextAware { + private Contract contract = new Contract.Default(); + private ApplicationContext applicationContext; + private FeignContext feignContext; + + @Override + public Feign.Builder invocationHandlerFactory( + InvocationHandlerFactory invocationHandlerFactory) { + throw new UnsupportedOperationException(); + } + + @Override + public Builder contract(Contract contract) { + this.contract = contract; + return this; + } + + @Override + public Feign build() { + super.invocationHandlerFactory(new InvocationHandlerFactory() { + @SneakyThrows + @Override + public InvocationHandler create(Target target, + Map dispatch) { + Object feignClientFactoryBean = Builder.this.applicationContext.getBean("&" + target.type().getName()); + + Class fallback = (Class) getFieldValue(feignClientFactoryBean, "fallback"); + Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean, "fallbackFactory"); + String name = (String) getFieldValue(feignClientFactoryBean, "name"); + + Object fallbackInstance; + FallbackFactory fallbackFactoryInstance; + // 判断fallback类型 + if (void.class != fallback) { + fallbackInstance = getFromContext(name, "fallback", fallback, target.type()); + return new BladeSentinelInvocationHandler(target, dispatch, new FallbackFactory.Default(fallbackInstance)); + } + if (void.class != fallbackFactory) { + fallbackFactoryInstance = (FallbackFactory) getFromContext(name, "fallbackFactory", fallbackFactory, FallbackFactory.class); + return new BladeSentinelInvocationHandler(target, dispatch, fallbackFactoryInstance); + } + // 默认fallbackFactory + BladeFallbackFactory bladeFallbackFactory = new BladeFallbackFactory(target); + return new BladeSentinelInvocationHandler(target, dispatch, bladeFallbackFactory); + } + + private Object getFromContext(String name, String type, Class fallbackType, Class targetType) { + Object fallbackInstance = feignContext.getInstance(name, fallbackType); + if (fallbackInstance == null) { + throw new IllegalStateException( + String.format("No %s instance of type %s found for feign client %s", + type, fallbackType, name) + ); + } + + if (!targetType.isAssignableFrom(fallbackType)) { + throw new IllegalStateException( + String.format("Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s", + type, fallbackType, targetType, name) + ); + } + return fallbackInstance; + } + }); + super.contract(new SentinelContractHolder(contract)); + return super.build(); + } + + private Object getFieldValue(Object instance, String fieldName) { + Field field = ReflectionUtils.findField(instance.getClass(), fieldName); + field.setAccessible(true); + try { + return field.get(instance); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + feignContext = this.applicationContext.getBean(FeignContext.class); + } + } + +} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/EnableBladeFeign.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/EnableBladeFeign.java index c29b5b4..30f9619 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/EnableBladeFeign.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/EnableBladeFeign.java @@ -18,6 +18,8 @@ package org.springblade.core.cloud.feign; import org.springblade.core.launch.constant.AppConstant; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import org.springframework.cloud.openfeign.EnableFeignClients; import java.lang.annotation.*; @@ -31,6 +33,7 @@ import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @EnableFeignClients(AppConstant.BASE_PACKAGES) +@EnableAutoConfiguration(exclude = RibbonAutoConfiguration.class) public @interface EnableBladeFeign { /** * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeAccountGetter.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeAccountGetter.java similarity index 91% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeAccountGetter.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeAccountGetter.java index 43c967c..115cee2 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeAccountGetter.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeAccountGetter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springblade.core.cloud.hystrix; +package org.springblade.core.cloud.header; import org.springblade.core.secure.BladeUser; import org.springblade.core.secure.utils.SecureUtil; @@ -27,7 +27,7 @@ import javax.servlet.http.HttpServletRequest; * * @author Chill */ -public class BladeAccountGetter implements BladeHystrixAccountGetter { +public class BladeAccountGetter implements BladeFeignAccountGetter { @Override public String get(HttpServletRequest request) { diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixAccountGetter.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeFeignAccountGetter.java similarity index 91% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixAccountGetter.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeFeignAccountGetter.java index 57952de..0f086a4 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixAccountGetter.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeFeignAccountGetter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springblade.core.cloud.hystrix; +package org.springblade.core.cloud.header; import org.springframework.lang.Nullable; @@ -25,7 +25,7 @@ import javax.servlet.http.HttpServletRequest; * * @author L.cm */ -public interface BladeHystrixAccountGetter { +public interface BladeFeignAccountGetter { /** * 账号信息获取器 diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignRequestHeaderInterceptor.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeFeignRequestHeaderInterceptor.java similarity index 92% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignRequestHeaderInterceptor.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeFeignRequestHeaderInterceptor.java index 1960d0d..d5b2649 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeFeignRequestHeaderInterceptor.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeFeignRequestHeaderInterceptor.java @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springblade.core.cloud.feign; +package org.springblade.core.cloud.header; import feign.RequestInterceptor; import feign.RequestTemplate; -import org.springblade.core.cloud.hystrix.BladeHttpHeadersContextHolder; import org.springframework.http.HttpHeaders; /** diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHttpHeadersCallable.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeHttpHeadersCallable.java similarity index 86% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHttpHeadersCallable.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeHttpHeadersCallable.java index 2bd1d02..831f2c0 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHttpHeadersCallable.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeHttpHeadersCallable.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springblade.core.cloud.hystrix; +package org.springblade.core.cloud.header; -import org.springblade.core.cloud.props.BladeHystrixHeadersProperties; +import org.springblade.core.cloud.props.BladeFeignHeadersProperties; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; @@ -33,8 +33,8 @@ public class BladeHttpHeadersCallable implements Callable { private HttpHeaders httpHeaders; public BladeHttpHeadersCallable(Callable delegate, - @Nullable BladeHystrixAccountGetter accountGetter, - BladeHystrixHeadersProperties properties) { + @Nullable BladeFeignAccountGetter accountGetter, + BladeFeignHeadersProperties properties) { this.delegate = delegate; this.httpHeaders = BladeHttpHeadersContextHolder.toHeaders(accountGetter, properties); } diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHttpHeadersContextHolder.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeHttpHeadersContextHolder.java similarity index 91% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHttpHeadersContextHolder.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeHttpHeadersContextHolder.java index 0712098..d9e323c 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHttpHeadersContextHolder.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/header/BladeHttpHeadersContextHolder.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springblade.core.cloud.hystrix; +package org.springblade.core.cloud.header; -import org.springblade.core.cloud.props.BladeHystrixHeadersProperties; +import org.springblade.core.cloud.props.BladeFeignHeadersProperties; import org.springblade.core.tool.utils.StringUtil; import org.springblade.core.tool.utils.WebUtil; import org.springframework.core.NamedThreadLocal; @@ -35,7 +35,7 @@ import java.util.List; * @author L.cm */ public class BladeHttpHeadersContextHolder { - private static final ThreadLocal HTTP_HEADERS_HOLDER = new NamedThreadLocal<>("Blade hystrix HttpHeaders"); + private static final ThreadLocal HTTP_HEADERS_HOLDER = new NamedThreadLocal<>("Blade Feign HttpHeaders"); /** * 请求和转发的ip @@ -59,8 +59,8 @@ public class BladeHttpHeadersContextHolder { @Nullable public static HttpHeaders toHeaders( - @Nullable BladeHystrixAccountGetter accountGetter, - BladeHystrixHeadersProperties properties) { + @Nullable BladeFeignAccountGetter accountGetter, + BladeFeignHeadersProperties properties) { HttpServletRequest request = WebUtil.getRequest(); if (request == null) { return null; diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateConfiguration.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateConfiguration.java index cc4f8e0..beaf20f 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateConfiguration.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateConfiguration.java @@ -18,12 +18,13 @@ package org.springblade.core.cloud.http; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; -import org.springblade.core.cloud.hystrix.BladeHystrixAccountGetter; -import org.springblade.core.cloud.props.BladeHystrixHeadersProperties; +import org.springblade.core.cloud.header.BladeFeignAccountGetter; +import org.springblade.core.cloud.props.BladeFeignHeadersProperties; import org.springblade.core.tool.utils.Charsets; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory; import org.springframework.cloud.commons.httpclient.OkHttpClientFactory; @@ -47,9 +48,10 @@ import java.util.concurrent.TimeUnit; * * @author L.cm */ -@Configuration -@ConditionalOnClass(okhttp3.OkHttpClient.class) +@Configuration(proxyBeanMethods = false) @AllArgsConstructor +@ConditionalOnClass(okhttp3.OkHttpClient.class) +@EnableConfigurationProperties(BladeFeignHeadersProperties.class) public class RestTemplateConfiguration { private final ObjectMapper objectMapper; @@ -135,8 +137,8 @@ public class RestTemplateConfiguration { @Bean public RestTemplateHeaderInterceptor requestHeaderInterceptor( - @Autowired(required = false) @Nullable BladeHystrixAccountGetter accountGetter, - BladeHystrixHeadersProperties properties) { + @Autowired(required = false) @Nullable BladeFeignAccountGetter accountGetter, + BladeFeignHeadersProperties properties) { return new RestTemplateHeaderInterceptor(accountGetter,properties); } diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateHeaderInterceptor.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateHeaderInterceptor.java index 2950676..4934758 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateHeaderInterceptor.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/http/RestTemplateHeaderInterceptor.java @@ -16,9 +16,9 @@ package org.springblade.core.cloud.http; import lombok.AllArgsConstructor; -import org.springblade.core.cloud.hystrix.BladeHttpHeadersContextHolder; -import org.springblade.core.cloud.hystrix.BladeHystrixAccountGetter; -import org.springblade.core.cloud.props.BladeHystrixHeadersProperties; +import org.springblade.core.cloud.header.BladeHttpHeadersContextHolder; +import org.springblade.core.cloud.header.BladeFeignAccountGetter; +import org.springblade.core.cloud.props.BladeFeignHeadersProperties; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; @@ -36,8 +36,8 @@ import java.io.IOException; @AllArgsConstructor public class RestTemplateHeaderInterceptor implements ClientHttpRequestInterceptor { @Nullable - private final BladeHystrixAccountGetter accountGetter; - private final BladeHystrixHeadersProperties properties; + private final BladeFeignAccountGetter accountGetter; + private final BladeFeignHeadersProperties properties; @Override public ClientHttpResponse intercept( diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixAutoConfiguration.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixAutoConfiguration.java deleted file mode 100644 index 9462c8a..0000000 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixAutoConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com). - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springblade.core.cloud.hystrix; - -import com.netflix.hystrix.Hystrix; -import com.netflix.hystrix.strategy.HystrixPlugins; -import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; -import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; -import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; -import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; -import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; -import org.springblade.core.cloud.props.BladeHystrixHeadersProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; -import org.springframework.lang.Nullable; - -import javax.annotation.PostConstruct; - -/** - * Hystrix 配置 - * - * @author L.cm - */ -@Configuration -@ConditionalOnClass(Hystrix.class) -@EnableConfigurationProperties(BladeHystrixHeadersProperties.class) -public class BladeHystrixAutoConfiguration { - @Nullable - @Autowired(required = false) - private HystrixConcurrencyStrategy existingConcurrencyStrategy; - @Nullable - @Autowired(required = false) - private BladeHystrixAccountGetter accountGetter; - @Autowired - private BladeHystrixHeadersProperties properties; - - @PostConstruct - public void init() { - // Keeps references of existing Hystrix plugins. - HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier(); - HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher(); - HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy(); - HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook(); - - HystrixPlugins.reset(); - - // Registers existing plugins excepts the Concurrent Strategy plugin. - HystrixConcurrencyStrategy strategy = new BladeHystrixConcurrencyStrategy(existingConcurrencyStrategy, accountGetter, properties); - HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); - HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); - HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); - HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); - HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); - } - -} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixConcurrencyStrategy.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixConcurrencyStrategy.java deleted file mode 100644 index 76c1fa5..0000000 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/hystrix/BladeHystrixConcurrencyStrategy.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com). - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springblade.core.cloud.hystrix; - -import com.netflix.hystrix.HystrixThreadPoolKey; -import com.netflix.hystrix.HystrixThreadPoolProperties; -import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; -import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable; -import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle; -import com.netflix.hystrix.strategy.properties.HystrixProperty; -import lombok.AllArgsConstructor; -import org.springblade.core.cloud.props.BladeHystrixHeadersProperties; -import org.springframework.lang.Nullable; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Hystrix传递ThreaLocal中的一些变量 - * - *

- * https://github.com/Netflix/Hystrix/issues/92#issuecomment-260548068 - * https://github.com/spring-cloud/spring-cloud-sleuth/issues/39 - * https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/security - * https://github.com/spring-projects/spring-security/blob/master/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextCallable.java - *

- * - * @author L.cm - */ -@AllArgsConstructor -public class BladeHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { - @Nullable - private final HystrixConcurrencyStrategy existingConcurrencyStrategy; - @Nullable - private final BladeHystrixAccountGetter accountGetter; - private final BladeHystrixHeadersProperties properties; - - @Override - public BlockingQueue getBlockingQueue(int maxQueueSize) { - return existingConcurrencyStrategy != null - ? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize) - : super.getBlockingQueue(maxQueueSize); - } - - @Override - public HystrixRequestVariable getRequestVariable( - HystrixRequestVariableLifecycle rv) { - return existingConcurrencyStrategy != null - ? existingConcurrencyStrategy.getRequestVariable(rv) - : super.getRequestVariable(rv); - } - - @Override - public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, - HystrixProperty corePoolSize, - HystrixProperty maximumPoolSize, - HystrixProperty keepAliveTime, TimeUnit unit, - BlockingQueue workQueue) { - return existingConcurrencyStrategy != null - ? existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue) - : super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); - } - - @Override - public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) { - return existingConcurrencyStrategy != null - ? existingConcurrencyStrategy.getThreadPool(threadPoolKey, threadPoolProperties) - : super.getThreadPool(threadPoolKey, threadPoolProperties); - } - - @Override - public Callable wrapCallable(Callable callable) { - Callable wrapCallable = new BladeHttpHeadersCallable<>(callable, accountGetter, properties); - return existingConcurrencyStrategy != null - ? existingConcurrencyStrategy.wrapCallable(wrapCallable) - : super.wrapCallable(wrapCallable); - } -} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/props/BladeHystrixHeadersProperties.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/props/BladeFeignHeadersProperties.java similarity index 94% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/props/BladeHystrixHeadersProperties.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/props/BladeFeignHeadersProperties.java index a9364fd..b9e351a 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/props/BladeHystrixHeadersProperties.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/props/BladeFeignHeadersProperties.java @@ -32,8 +32,8 @@ import java.util.List; @Getter @Setter @RefreshScope -@ConfigurationProperties("blade.hystrix.headers") -public class BladeHystrixHeadersProperties { +@ConfigurationProperties("blade.feign.headers") +public class BladeFeignHeadersProperties { /** * 用于 聚合层 向调用层传递用户信息 的请求头,默认:x-blade-account diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/sentinel/BladeBlockExceptionHandler.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/sentinel/BladeBlockExceptionHandler.java new file mode 100644 index 0000000..12ddec4 --- /dev/null +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/sentinel/BladeBlockExceptionHandler.java @@ -0,0 +1,26 @@ +package org.springblade.core.cloud.sentinel; + +import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import org.springblade.core.tool.api.R; +import org.springblade.core.tool.jackson.JsonUtil; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Sentinel统一限流策略 + * + * @author Chill + */ +public class BladeBlockExceptionHandler implements BlockExceptionHandler { + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception { + // Return 429 (Too Many Requests) by default. + response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.getWriter().print(JsonUtil.toJson(R.fail(e.getMessage()))); + } +} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/sentinel/BladeSentinelInvocationHandler.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/sentinel/BladeSentinelInvocationHandler.java new file mode 100644 index 0000000..b386843 --- /dev/null +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/sentinel/BladeSentinelInvocationHandler.java @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springblade.core.cloud.sentinel; + +import com.alibaba.cloud.sentinel.feign.SentinelContractHolder; +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.Tracer; +import com.alibaba.csp.sentinel.context.ContextUtil; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import feign.Feign; +import feign.InvocationHandlerFactory; +import feign.MethodMetadata; +import feign.Target; +import org.springframework.cloud.openfeign.FallbackFactory; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.LinkedHashMap; +import java.util.Map; + +import static feign.Util.checkNotNull; + +/** + * 重写SentinelInvocationHandler适配最新API + * + * @author Chill + */ +public class BladeSentinelInvocationHandler implements InvocationHandler { + + private final Target target; + + private final Map dispatch; + + private FallbackFactory fallbackFactory; + + private Map fallbackMethodMap; + + public BladeSentinelInvocationHandler(Target target, Map dispatch, + FallbackFactory fallbackFactory) { + this.target = checkNotNull(target, "target"); + this.dispatch = checkNotNull(dispatch, "dispatch"); + this.fallbackFactory = fallbackFactory; + this.fallbackMethodMap = toFallbackMethod(dispatch); + } + + public BladeSentinelInvocationHandler(Target target, Map dispatch) { + this.target = checkNotNull(target, "target"); + this.dispatch = checkNotNull(dispatch, "dispatch"); + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) + throws Throwable { + if ("equals".equals(method.getName())) { + try { + Object otherHandler = args.length > 0 && args[0] != null + ? Proxy.getInvocationHandler(args[0]) : null; + return equals(otherHandler); + } catch (IllegalArgumentException e) { + return false; + } + } else if ("hashCode".equals(method.getName())) { + return hashCode(); + } else if ("toString".equals(method.getName())) { + return toString(); + } + + Object result; + InvocationHandlerFactory.MethodHandler methodHandler = this.dispatch.get(method); + // only handle by HardCodedTarget + if (target instanceof Target.HardCodedTarget) { + Target.HardCodedTarget hardCodedTarget = (Target.HardCodedTarget) target; + MethodMetadata methodMetadata = SentinelContractHolder.METADATA_MAP + .get(hardCodedTarget.type().getName() + + Feign.configKey(hardCodedTarget.type(), method)); + // resource default is HttpMethod:protocol://url + if (methodMetadata == null) { + result = methodHandler.invoke(args); + } else { + String resourceName = methodMetadata.template().method().toUpperCase() + + ":" + hardCodedTarget.url() + methodMetadata.template().path(); + Entry entry = null; + try { + ContextUtil.enter(resourceName); + entry = SphU.entry(resourceName, EntryType.OUT, 1, args); + result = methodHandler.invoke(args); + } catch (Throwable ex) { + // fallback handle + if (!BlockException.isBlockException(ex)) { + Tracer.trace(ex); + } + if (fallbackFactory != null) { + try { + Object fallbackResult = fallbackMethodMap.get(method) + .invoke(fallbackFactory.create(ex), args); + return fallbackResult; + } catch (IllegalAccessException e) { + // shouldn't happen as method is public due to being an + // interface + throw new AssertionError(e); + } catch (InvocationTargetException e) { + throw new AssertionError(e.getCause()); + } + } else { + // throw exception if fallbackFactory is null + throw ex; + } + } finally { + if (entry != null) { + entry.exit(1, args); + } + ContextUtil.exit(); + } + } + } else { + // other target type using default strategy + result = methodHandler.invoke(args); + } + + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BladeSentinelInvocationHandler) { + BladeSentinelInvocationHandler other = (BladeSentinelInvocationHandler) obj; + return target.equals(other.target); + } + return false; + } + + @Override + public int hashCode() { + return target.hashCode(); + } + + @Override + public String toString() { + return target.toString(); + } + + static Map toFallbackMethod(Map dispatch) { + Map result = new LinkedHashMap<>(); + for (Method method : dispatch.keySet()) { + method.setAccessible(true); + result.put(method, method); + } + return result; + } + +} diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeSpringMvcContract.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/version/BladeSpringMvcContract.java similarity index 97% rename from blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeSpringMvcContract.java rename to blade-core-cloud/src/main/java/org/springblade/core/cloud/version/BladeSpringMvcContract.java index 10cf4b7..507629e 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/feign/BladeSpringMvcContract.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/version/BladeSpringMvcContract.java @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springblade.core.cloud.feign; +package org.springblade.core.cloud.version; import feign.MethodMetadata; import org.springblade.core.cloud.annotation.ApiVersion; import org.springblade.core.cloud.annotation.UrlVersion; -import org.springblade.core.cloud.version.BladeMediaType; import org.springblade.core.tool.utils.StringPool; import org.springblade.core.tool.utils.StringUtil; import org.springframework.cloud.openfeign.AnnotatedParameterProcessor; diff --git a/blade-core-cloud/src/main/java/org/springblade/core/cloud/version/VersionMappingAutoConfiguration.java b/blade-core-cloud/src/main/java/org/springblade/core/cloud/version/VersionMappingAutoConfiguration.java index 2276e23..087caa3 100644 --- a/blade-core-cloud/src/main/java/org/springblade/core/cloud/version/VersionMappingAutoConfiguration.java +++ b/blade-core-cloud/src/main/java/org/springblade/core/cloud/version/VersionMappingAutoConfiguration.java @@ -27,7 +27,7 @@ import org.springframework.context.annotation.Configuration; * * @author L.cm */ -@Configuration +@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication public class VersionMappingAutoConfiguration { @Bean diff --git a/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/BladeFeignClientsRegistrar.java b/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/BladeFeignClientsRegistrar.java deleted file mode 100644 index b6c635c..0000000 --- a/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/BladeFeignClientsRegistrar.java +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com). - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.cloud.openfeign; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springblade.core.cloud.feign.BladeFeignAutoConfiguration; -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.context.EnvironmentAware; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.env.Environment; -import org.springframework.core.io.support.SpringFactoriesLoader; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.lang.Nullable; -import org.springframework.util.StringUtils; - -import java.util.List; -import java.util.Map; - -/** - * feign 自动配置 - * - * @author L.cm - */ -@NoArgsConstructor -public class BladeFeignClientsRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware { - @Getter - private ClassLoader beanClassLoader; - @Getter - private Environment environment; - - @Override - public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { - registerFeignClients(metadata, registry); - } - - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.beanClassLoader = classLoader; - } - - private void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { - List feignClients = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); - // 如果 spring.factories 里为空 - if (feignClients.isEmpty()) { - return; - } - for (String className : feignClients) { - try { - Class clazz = beanClassLoader.loadClass(className); - AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz, FeignClient.class); - if (attributes == null) { - continue; - } - // 如果已经存在该 bean,支持原生的 Feign - if (registry.containsBeanDefinition(className)) { - continue; - } - registerClientConfiguration(registry, getClientName(attributes), attributes.get("configuration")); - - validate(attributes); - BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class); - definition.addPropertyValue("url", getUrl(attributes)); - definition.addPropertyValue("path", getPath(attributes)); - String name = getName(attributes); - definition.addPropertyValue("name", name); - - // 兼容最新版本的 spring-cloud-openfeign,尚未发布 - StringBuilder aliasBuilder = new StringBuilder(18); - if (attributes.containsKey("contextId")) { - String contextId = getContextId(attributes); - aliasBuilder.append(contextId); - definition.addPropertyValue("contextId", contextId); - } else { - aliasBuilder.append(name); - } - - definition.addPropertyValue("type", className); - definition.addPropertyValue("decode404", attributes.get("decode404")); - definition.addPropertyValue("fallback", attributes.get("fallback")); - definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory")); - definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - - AbstractBeanDefinition beanDefinition = definition.getBeanDefinition(); - - // alias - String alias = aliasBuilder.append("FeignClient").toString(); - - // has a default, won't be null - boolean primary = (Boolean)attributes.get("primary"); - - beanDefinition.setPrimary(primary); - - String qualifier = getQualifier(attributes); - if (StringUtils.hasText(qualifier)) { - alias = qualifier; - } - - BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[] { alias }); - BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); - - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - } - - /** - * Return the class used by {@link SpringFactoriesLoader} to load configuration - * candidates. - * @return the factory class - */ - private Class getSpringFactoriesLoaderFactoryClass() { - return BladeFeignAutoConfiguration.class; - } - - private void validate(Map attributes) { - AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes); - // This blows up if an aliased property is overspecified - // FIXME annotation.getAliasedString("name", FeignClient.class, null); - FeignClientsRegistrar.validateFallback(annotation.getClass("fallback")); - FeignClientsRegistrar.validateFallbackFactory(annotation.getClass("fallbackFactory")); - } - - private String getName(Map attributes) { - String name = (String) attributes.get("serviceId"); - if (!StringUtils.hasText(name)) { - name = (String) attributes.get("name"); - } - if (!StringUtils.hasText(name)) { - name = (String) attributes.get("value"); - } - name = resolve(name); - return FeignClientsRegistrar.getName(name); - } - - private String getContextId(Map attributes) { - String contextId = (String) attributes.get("contextId"); - if (!StringUtils.hasText(contextId)) { - return getName(attributes); - } - - contextId = resolve(contextId); - return FeignClientsRegistrar.getName(contextId); - } - - private String resolve(String value) { - if (StringUtils.hasText(value)) { - return this.environment.resolvePlaceholders(value); - } - return value; - } - - private String getUrl(Map attributes) { - String url = resolve((String) attributes.get("url")); - return FeignClientsRegistrar.getUrl(url); - } - - private String getPath(Map attributes) { - String path = resolve((String) attributes.get("path")); - return FeignClientsRegistrar.getPath(path); - } - - @Nullable - private String getQualifier(@Nullable Map client) { - if (client == null) { - return null; - } - String qualifier = (String) client.get("qualifier"); - if (StringUtils.hasText(qualifier)) { - return qualifier; - } - return null; - } - - @Nullable - private String getClientName(@Nullable Map client) { - if (client == null) { - return null; - } - String value = (String) client.get("contextId"); - if (!StringUtils.hasText(value)) { - value = (String) client.get("value"); - } - if (!StringUtils.hasText(value)) { - value = (String) client.get("name"); - } - if (!StringUtils.hasText(value)) { - value = (String) client.get("serviceId"); - } - if (StringUtils.hasText(value)) { - return value; - } - - throw new IllegalStateException("Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName()); - } - - private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class); - builder.addConstructorArgValue(name); - builder.addConstructorArgValue(configuration); - registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition()); - } - - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } - -} diff --git a/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/BladeHystrixTargeter.java b/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/BladeHystrixTargeter.java deleted file mode 100644 index f875cdd..0000000 --- a/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/BladeHystrixTargeter.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.springframework.cloud.openfeign; - -import feign.Feign; -import feign.Target; -import feign.hystrix.FallbackFactory; -import feign.hystrix.HystrixFeign; -import feign.hystrix.SetterFactory; -import org.springblade.core.cloud.feign.BladeFallbackFactory; -import org.springframework.lang.Nullable; - -/** - * 添加 blade 默认的 fallbackFactory L.cm 2019.01.19 - * - * @author L.cm - * @author Spencer Gibb - * @author Erik Kringen - */ -@SuppressWarnings("unchecked") -public class BladeHystrixTargeter implements Targeter { - - @Override - public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, - Target.HardCodedTarget target) { - if (!(feign instanceof HystrixFeign.Builder)) { - return feign.target(target); - } - HystrixFeign.Builder builder = (HystrixFeign.Builder) feign; - SetterFactory setterFactory = getOptional(factory.getName(), context, SetterFactory.class); - if (setterFactory != null) { - builder.setterFactory(setterFactory); - } - Class fallback = factory.getFallback(); - if (fallback != void.class) { - return targetWithFallback(factory.getName(), context, target, builder, fallback); - } - Class fallbackFactory = factory.getFallbackFactory(); - if (fallbackFactory != void.class) { - return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory); - } - // blade 默认的 fallbackFactory - BladeFallbackFactory bladeFallbackFactory = new BladeFallbackFactory(target); - return (T) builder.target(target, bladeFallbackFactory); - } - - private T targetWithFallbackFactory(String feignClientName, FeignContext context, - Target.HardCodedTarget target, - HystrixFeign.Builder builder, - Class fallbackFactoryClass) { - FallbackFactory fallbackFactory = (FallbackFactory) - getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class); - return builder.target(target, fallbackFactory); - } - - - private T targetWithFallback(String feignClientName, FeignContext context, - Target.HardCodedTarget target, - HystrixFeign.Builder builder, Class fallback) { - T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type()); - return builder.target(target, fallbackInstance); - } - - private T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context, Class beanType, - Class targetType) { - Object fallbackInstance = context.getInstance(feignClientName, beanType); - if (fallbackInstance == null) { - throw new IllegalStateException(String.format("No " + fallbackMechanism + - " instance of type %s found for feign client %s", beanType, feignClientName)); - } - - if (!targetType.isAssignableFrom(beanType)) { - throw new IllegalStateException(String.format( - "Incompatible " + fallbackMechanism + " instance. Fallback/fallbackFactory of " + - "type %s is not assignable to %s for feign client %s", beanType, targetType, feignClientName)); - } - return (T) fallbackInstance; - } - - @Nullable - private T getOptional(String feignClientName, FeignContext context, Class beanType) { - return context.getInstance(feignClientName, beanType); - } -} diff --git a/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/Targeter.java b/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/Targeter.java deleted file mode 100644 index bb49bd2..0000000 --- a/blade-core-cloud/src/main/java/org/springframework/cloud/openfeign/Targeter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.springframework.cloud.openfeign; - -import feign.Feign; -import feign.Target; - -/** - * @author Spencer Gibb - */ -public interface Targeter { - /** - * target - * - * @param factory - * @param feign - * @param context - * @param target - * @param - * @return T - */ - T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, - Target.HardCodedTarget target); -} diff --git a/blade-core-develop/pom.xml b/blade-core-develop/pom.xml index c9fcc45..ebbe868 100644 --- a/blade-core-develop/pom.xml +++ b/blade-core-develop/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-launch/pom.xml b/blade-core-launch/pom.xml index 2109d38..991c6b3 100644 --- a/blade-core-launch/pom.xml +++ b/blade-core-launch/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-launch/src/main/java/org/springblade/core/launch/StartEventListener.java b/blade-core-launch/src/main/java/org/springblade/core/launch/StartEventListener.java index f0b3f8a..34d31a8 100644 --- a/blade-core-launch/src/main/java/org/springblade/core/launch/StartEventListener.java +++ b/blade-core-launch/src/main/java/org/springblade/core/launch/StartEventListener.java @@ -30,7 +30,7 @@ import org.springframework.util.StringUtils; * @author Chill */ @Slf4j -@Configuration +@Configuration(proxyBeanMethods = false) public class StartEventListener { @Async diff --git a/blade-core-launch/src/main/java/org/springblade/core/launch/config/BladeLaunchConfiguration.java b/blade-core-launch/src/main/java/org/springblade/core/launch/config/BladeLaunchConfiguration.java index 38dd054..9bbb5c2 100644 --- a/blade-core-launch/src/main/java/org/springblade/core/launch/config/BladeLaunchConfiguration.java +++ b/blade-core-launch/src/main/java/org/springblade/core/launch/config/BladeLaunchConfiguration.java @@ -27,7 +27,7 @@ import org.springframework.core.annotation.Order; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @Order(Ordered.HIGHEST_PRECEDENCE) @EnableConfigurationProperties({ diff --git a/blade-core-launch/src/main/java/org/springblade/core/launch/constant/AppConstant.java b/blade-core-launch/src/main/java/org/springblade/core/launch/constant/AppConstant.java index 3d00ded..bcf650a 100644 --- a/blade-core-launch/src/main/java/org/springblade/core/launch/constant/AppConstant.java +++ b/blade-core-launch/src/main/java/org/springblade/core/launch/constant/AppConstant.java @@ -25,7 +25,7 @@ public interface AppConstant { /** * 应用版本 */ - String APPLICATION_VERSION = "2.8.0"; + String APPLICATION_VERSION = "3.0.0"; /** * 基础包 diff --git a/blade-core-launch/src/main/java/org/springblade/core/launch/server/ServerInfo.java b/blade-core-launch/src/main/java/org/springblade/core/launch/server/ServerInfo.java index 3f989b6..176db96 100644 --- a/blade-core-launch/src/main/java/org/springblade/core/launch/server/ServerInfo.java +++ b/blade-core-launch/src/main/java/org/springblade/core/launch/server/ServerInfo.java @@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration; * @author Chill */ @Getter -@Configuration +@Configuration(proxyBeanMethods = false) public class ServerInfo implements SmartInitializingSingleton { private final ServerProperties serverProperties; private String hostName; diff --git a/blade-core-log/pom.xml b/blade-core-log/pom.xml index 9c30b95..c7582d7 100644 --- a/blade-core-log/pom.xml +++ b/blade-core-log/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-log/src/main/java/org/springblade/core/log/config/BladeErrorMvcAutoConfiguration.java b/blade-core-log/src/main/java/org/springblade/core/log/config/BladeErrorMvcAutoConfiguration.java index 2e2a72d..5221f11 100644 --- a/blade-core-log/src/main/java/org/springblade/core/log/config/BladeErrorMvcAutoConfiguration.java +++ b/blade-core-log/src/main/java/org/springblade/core/log/config/BladeErrorMvcAutoConfiguration.java @@ -41,7 +41,7 @@ import javax.servlet.Servlet; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @ConditionalOnWebApplication @AutoConfigureBefore(ErrorMvcAutoConfiguration.class) diff --git a/blade-core-log/src/main/java/org/springblade/core/log/config/BladeLogToolAutoConfiguration.java b/blade-core-log/src/main/java/org/springblade/core/log/config/BladeLogToolAutoConfiguration.java index c0e9dd3..062a655 100644 --- a/blade-core-log/src/main/java/org/springblade/core/log/config/BladeLogToolAutoConfiguration.java +++ b/blade-core-log/src/main/java/org/springblade/core/log/config/BladeLogToolAutoConfiguration.java @@ -34,7 +34,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @ConditionalOnWebApplication public class BladeLogToolAutoConfiguration { diff --git a/blade-core-log/src/main/java/org/springblade/core/log/error/BladeErrorController.java b/blade-core-log/src/main/java/org/springblade/core/log/error/BladeErrorController.java index 6fd6e48..2daffea 100644 --- a/blade-core-log/src/main/java/org/springblade/core/log/error/BladeErrorController.java +++ b/blade-core-log/src/main/java/org/springblade/core/log/error/BladeErrorController.java @@ -18,6 +18,7 @@ package org.springblade.core.log.error; import org.springblade.core.tool.jackson.JsonUtil; import org.springframework.boot.autoconfigure.web.ErrorProperties; import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.error.ErrorAttributeOptions; import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -41,12 +42,13 @@ public class BladeErrorController extends BasicErrorController { @Override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { - Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); + boolean includeStackTrace = isIncludeStackTrace(request, MediaType.ALL); + Map body = getErrorAttributes(request, (includeStackTrace) ? ErrorAttributeOptions.of(ErrorAttributeOptions.Include.STACK_TRACE) : ErrorAttributeOptions.defaults()); HttpStatus status = getStatus(request); response.setStatus(status.value()); MappingJackson2JsonView view = new MappingJackson2JsonView(); view.setObjectMapper(JsonUtil.getInstance()); - view.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + view.setContentType(MediaType.APPLICATION_JSON_VALUE); return new ModelAndView(view, body); } diff --git a/blade-core-log/src/main/java/org/springblade/core/log/error/BladeRestExceptionTranslator.java b/blade-core-log/src/main/java/org/springblade/core/log/error/BladeRestExceptionTranslator.java index bc551be..cdee69e 100644 --- a/blade-core-log/src/main/java/org/springblade/core/log/error/BladeRestExceptionTranslator.java +++ b/blade-core-log/src/main/java/org/springblade/core/log/error/BladeRestExceptionTranslator.java @@ -55,7 +55,7 @@ import java.util.Set; * @author Chill */ @Slf4j -@Configuration +@Configuration(proxyBeanMethods = false) @ConditionalOnClass({Servlet.class, DispatcherServlet.class}) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @RestControllerAdvice diff --git a/blade-core-mybatis/pom.xml b/blade-core-mybatis/pom.xml index c314c6f..87301ca 100644 --- a/blade-core-mybatis/pom.xml +++ b/blade-core-mybatis/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-oss/pom.xml b/blade-core-oss/pom.xml index 2e7b7a7..2da6e65 100644 --- a/blade-core-oss/pom.xml +++ b/blade-core-oss/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-oss/src/main/java/org/springblade/core/oss/config/AliossConfiguration.java b/blade-core-oss/src/main/java/org/springblade/core/oss/config/AliossConfiguration.java index 29d3152..cc9f8d6 100644 --- a/blade-core-oss/src/main/java/org/springblade/core/oss/config/AliossConfiguration.java +++ b/blade-core-oss/src/main/java/org/springblade/core/oss/config/AliossConfiguration.java @@ -37,7 +37,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @AutoConfigureAfter(QiniuConfiguration.class) @EnableConfigurationProperties(OssProperties.class) diff --git a/blade-core-oss/src/main/java/org/springblade/core/oss/config/QiniuConfiguration.java b/blade-core-oss/src/main/java/org/springblade/core/oss/config/QiniuConfiguration.java index 52ab32a..ac37297 100644 --- a/blade-core-oss/src/main/java/org/springblade/core/oss/config/QiniuConfiguration.java +++ b/blade-core-oss/src/main/java/org/springblade/core/oss/config/QiniuConfiguration.java @@ -36,7 +36,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @EnableConfigurationProperties(OssProperties.class) @ConditionalOnProperty(value = "oss.name", havingValue = "qiniu") diff --git a/blade-core-report/pom.xml b/blade-core-report/pom.xml index 478351d..22bd9e6 100644 --- a/blade-core-report/pom.xml +++ b/blade-core-report/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-report/src/main/java/org/springblade/core/report/config/ReportConfiguration.java b/blade-core-report/src/main/java/org/springblade/core/report/config/ReportConfiguration.java index ef28971..18f5d68 100644 --- a/blade-core-report/src/main/java/org/springblade/core/report/config/ReportConfiguration.java +++ b/blade-core-report/src/main/java/org/springblade/core/report/config/ReportConfiguration.java @@ -40,7 +40,7 @@ import javax.servlet.Servlet; * @author Chill */ @Order -@Configuration +@Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = "report.enabled", havingValue = "true", matchIfMissing = true) @EnableConfigurationProperties({ReportProperties.class, ReportDatabaseProperties.class}) @ImportResource("classpath:ureport-console-context.xml") diff --git a/blade-core-secure/pom.xml b/blade-core-secure/pom.xml index 0593b60..9f64081 100644 --- a/blade-core-secure/pom.xml +++ b/blade-core-secure/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-secure/src/main/java/org/springblade/core/secure/config/RegistryConfiguration.java b/blade-core-secure/src/main/java/org/springblade/core/secure/config/RegistryConfiguration.java index 5c7fa37..d3b5a23 100644 --- a/blade-core-secure/src/main/java/org/springblade/core/secure/config/RegistryConfiguration.java +++ b/blade-core-secure/src/main/java/org/springblade/core/secure/config/RegistryConfiguration.java @@ -29,7 +29,7 @@ import org.springframework.core.annotation.Order; * @author Chill */ @Order -@Configuration +@Configuration(proxyBeanMethods = false) @AutoConfigureBefore(SecureConfiguration.class) public class RegistryConfiguration { diff --git a/blade-core-secure/src/main/java/org/springblade/core/secure/config/SecureConfiguration.java b/blade-core-secure/src/main/java/org/springblade/core/secure/config/SecureConfiguration.java index a77de31..5334ccf 100644 --- a/blade-core-secure/src/main/java/org/springblade/core/secure/config/SecureConfiguration.java +++ b/blade-core-secure/src/main/java/org/springblade/core/secure/config/SecureConfiguration.java @@ -39,7 +39,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; * @author Chill */ @Order -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @EnableConfigurationProperties({BladeSecureProperties.class}) public class SecureConfiguration implements WebMvcConfigurer { diff --git a/blade-core-social/pom.xml b/blade-core-social/pom.xml index b1f44bc..b9cea42 100644 --- a/blade-core-social/pom.xml +++ b/blade-core-social/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-social/src/main/java/org/springblade/core/social/config/SocialConfiguration.java b/blade-core-social/src/main/java/org/springblade/core/social/config/SocialConfiguration.java index 10bd116..b6d93b6 100644 --- a/blade-core-social/src/main/java/org/springblade/core/social/config/SocialConfiguration.java +++ b/blade-core-social/src/main/java/org/springblade/core/social/config/SocialConfiguration.java @@ -29,7 +29,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(SocialProperties.class) public class SocialConfiguration { diff --git a/blade-core-swagger/pom.xml b/blade-core-swagger/pom.xml index 5951fe1..f51669f 100644 --- a/blade-core-swagger/pom.xml +++ b/blade-core-swagger/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerAutoConfiguration.java b/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerAutoConfiguration.java index 34dcf05..3a22ef8 100644 --- a/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerAutoConfiguration.java +++ b/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerAutoConfiguration.java @@ -41,7 +41,7 @@ import java.util.List; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @EnableSwagger @EnableConfigurationProperties(SwaggerProperties.class) @Import(BeanValidatorPluginsConfiguration.class) diff --git a/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerProperties.java b/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerProperties.java index b53eeb1..d032e86 100644 --- a/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerProperties.java +++ b/blade-core-swagger/src/main/java/org/springblade/core/swagger/SwaggerProperties.java @@ -55,7 +55,7 @@ public class SwaggerProperties { /** * 版本 **/ - private String version = "2.8.0"; + private String version = "3.0.0"; /** * 许可证 **/ diff --git a/blade-core-test/pom.xml b/blade-core-test/pom.xml index 3c4b8ca..49a7863 100644 --- a/blade-core-test/pom.xml +++ b/blade-core-test/pom.xml @@ -5,7 +5,7 @@ org.springblade blade-tool - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-test/src/main/java/org/springblade/core/test/BladeBaseTest.java b/blade-core-test/src/main/java/org/springblade/core/test/BladeBaseTest.java deleted file mode 100644 index 67c830d..0000000 --- a/blade-core-test/src/main/java/org/springblade/core/test/BladeBaseTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com). - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springblade.core.test; - -import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; - -/** - * boot test 基类 - * - * @author L.cm - */ -@RunWith(BladeSpringRunner.class) -public abstract class BladeBaseTest extends AbstractJUnit4SpringContextTests { - -} diff --git a/blade-core-test/src/main/java/org/springblade/core/test/BladeBootTest.java b/blade-core-test/src/main/java/org/springblade/core/test/BladeBootTest.java index d6d4760..3c3f68b 100644 --- a/blade-core-test/src/main/java/org/springblade/core/test/BladeBootTest.java +++ b/blade-core-test/src/main/java/org/springblade/core/test/BladeBootTest.java @@ -16,6 +16,7 @@ package org.springblade.core.test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.core.annotation.AliasFor; @@ -31,6 +32,7 @@ import java.lang.annotation.*; @Documented @Inherited @SpringBootTest +@ExtendWith(BladeSpringExtension.class) public @interface BladeBootTest { /** * 服务名:appName diff --git a/blade-core-test/src/main/java/org/springblade/core/test/BladeSpringRunner.java b/blade-core-test/src/main/java/org/springblade/core/test/BladeSpringExtension.java similarity index 84% rename from blade-core-test/src/main/java/org/springblade/core/test/BladeSpringRunner.java rename to blade-core-test/src/main/java/org/springblade/core/test/BladeSpringExtension.java index bb456c0..8f11c31 100644 --- a/blade-core-test/src/main/java/org/springblade/core/test/BladeSpringRunner.java +++ b/blade-core-test/src/main/java/org/springblade/core/test/BladeSpringExtension.java @@ -17,7 +17,7 @@ package org.springblade.core.test; -import org.junit.runners.model.InitializationError; +import org.junit.jupiter.api.extension.ExtensionContext; import org.springblade.core.launch.BladeApplication; import org.springblade.core.launch.constant.AppConstant; import org.springblade.core.launch.constant.NacosConstant; @@ -25,7 +25,8 @@ import org.springblade.core.launch.constant.SentinelConstant; import org.springblade.core.launch.service.LauncherService; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.lang.NonNull; +import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.*; import java.util.stream.Collectors; @@ -35,14 +36,16 @@ import java.util.stream.Collectors; * * @author L.cm */ -public class BladeSpringRunner extends SpringJUnit4ClassRunner { +public class BladeSpringExtension extends SpringExtension { - public BladeSpringRunner(Class clazz) throws InitializationError { - super(clazz); - setUpTestClass(clazz); + @Override + public void beforeAll(@NonNull ExtensionContext context) throws Exception { + super.beforeAll(context); + setUpTestClass(context); } - private void setUpTestClass(Class clazz) { + private void setUpTestClass(ExtensionContext context) { + Class clazz = context.getRequiredTestClass(); BladeBootTest bladeBootTest = AnnotationUtils.getAnnotation(clazz, BladeBootTest.class); if (bladeBootTest == null) { throw new BladeBootTestException(String.format("%s must be @BladeBootTest .", clazz)); @@ -74,7 +77,7 @@ public class BladeSpringRunner extends SpringJUnit4ClassRunner { launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList()) .forEach(launcherService -> launcherService.launcher(builder, appName, profile)); } - System.err.println(String.format("---[junit.test]:[%s]---启动中,读取到的环境变量:[%s]", appName, profile)); + System.err.printf("---[junit.test]:[%s]---启动中,读取到的环境变量:[%s]%n", appName, profile); } } diff --git a/blade-core-tool/pom.xml b/blade-core-tool/pom.xml index 90f8d10..5d6fc4e 100644 --- a/blade-core-tool/pom.xml +++ b/blade-core-tool/pom.xml @@ -6,7 +6,7 @@ org.springblade blade-tool - 2.8.0 + 3.0.0 4.0.0 diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/config/JacksonConfiguration.java b/blade-core-tool/src/main/java/org/springblade/core/tool/config/JacksonConfiguration.java index f1216eb..a5b0058 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/config/JacksonConfiguration.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/config/JacksonConfiguration.java @@ -41,7 +41,7 @@ import java.util.TimeZone; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @ConditionalOnClass(ObjectMapper.class) @AutoConfigureBefore(JacksonAutoConfiguration.class) diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/config/MessageConfiguration.java b/blade-core-tool/src/main/java/org/springblade/core/tool/config/MessageConfiguration.java index c3f3344..51fb28c 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/config/MessageConfiguration.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/config/MessageConfiguration.java @@ -34,7 +34,7 @@ import java.util.List; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @Order(Ordered.HIGHEST_PRECEDENCE) public class MessageConfiguration implements WebMvcConfigurer { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/config/RedisTemplateConfiguration.java b/blade-core-tool/src/main/java/org/springblade/core/tool/config/RedisTemplateConfiguration.java index 0647573..5f0ee66 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/config/RedisTemplateConfiguration.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/config/RedisTemplateConfiguration.java @@ -41,7 +41,7 @@ import java.time.Duration; * @author Chill */ @EnableCaching -@Configuration +@Configuration(proxyBeanMethods = false) @AutoConfigureBefore(RedisAutoConfiguration.class) public class RedisTemplateConfiguration { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/config/ToolConfiguration.java b/blade-core-tool/src/main/java/org/springblade/core/tool/config/ToolConfiguration.java index b0346dc..9dfc257 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/config/ToolConfiguration.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/config/ToolConfiguration.java @@ -28,7 +28,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @Order(Ordered.HIGHEST_PRECEDENCE) public class ToolConfiguration implements WebMvcConfigurer { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/config/XssConfiguration.java b/blade-core-tool/src/main/java/org/springblade/core/tool/config/XssConfiguration.java index 84c6eca..cf3995a 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/config/XssConfiguration.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/config/XssConfiguration.java @@ -33,7 +33,7 @@ import javax.servlet.DispatcherType; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) @AllArgsConstructor @ConditionalOnProperty(value = "blade.xss.enabled", havingValue = "true") @EnableConfigurationProperties({XssProperties.class, XssUrlProperties.class}) diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RedisUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RedisUtil.java index 8f67226..ea095f2 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RedisUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RedisUtil.java @@ -3,6 +3,7 @@ package org.springblade.core.tool.utils; import lombok.AllArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; @@ -69,13 +70,12 @@ public class RedisUtil { * * @param key 可以传一个值 或多个 */ - @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { - redisTemplate.delete(CollectionUtil.arrayToList(key)); + redisTemplate.delete(Arrays.asList(key)); } } } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java index bab680a..8259090 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java @@ -127,7 +127,7 @@ public class WebUtil extends org.springframework.web.util.WebUtils { * @param result 结果对象 */ public static void renderJson(HttpServletResponse response, Object result) { - renderJson(response, result, MediaType.APPLICATION_JSON_UTF8_VALUE); + renderJson(response, result, MediaType.APPLICATION_JSON_VALUE); } /** diff --git a/blade-core-transaction/pom.xml b/blade-core-transaction/pom.xml index 1ee758c..0828955 100644 --- a/blade-core-transaction/pom.xml +++ b/blade-core-transaction/pom.xml @@ -5,7 +5,7 @@ blade-tool org.springblade - 2.8.0 + 3.0.0 4.0.0 @@ -15,11 +15,17 @@ jar + org.springblade blade-core-mybatis ${blade.tool.version} + + org.springblade + blade-core-cloud + ${blade.tool.version} + org.springframework.cloud diff --git a/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java new file mode 100644 index 0000000..2bf6c56 --- /dev/null +++ b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignBlockingLoadBalancerClient.java @@ -0,0 +1,33 @@ +package com.alibaba.cloud.seata.feign; + +import feign.Client; +import feign.Request; +import feign.Response; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; + +import java.io.IOException; + +/** + * 重写SeataFeignBlockingLoadBalancerClient以适配最新API + * + * @author Chill + */ +public class SeataFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient { + + public SeataFeignBlockingLoadBalancerClient(Client delegate, + BlockingLoadBalancerClient loadBalancerClient, + SeataFeignObjectWrapper seataFeignObjectWrapper, + LoadBalancerProperties properties, + LoadBalancerClientFactory loadBalancerClientFactory) { + super((Client) seataFeignObjectWrapper.wrap(delegate), loadBalancerClient, properties, loadBalancerClientFactory); + } + + @Override + public Response execute(Request request, Request.Options options) throws IOException { + return super.execute(request, options); + } + +} diff --git a/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java new file mode 100644 index 0000000..d0fc70f --- /dev/null +++ b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.cloud.seata.feign; + +import feign.Client; +import feign.Feign; +import feign.Retryer; +import lombok.RequiredArgsConstructor; +import org.springblade.core.cloud.feign.BladeFeignSentinel; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.openfeign.FeignAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +/** + * 重写SeataFeignClientAutoConfiguration以适配最新API + * + * @author Chill + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass(Client.class) +@AutoConfigureBefore(FeignAutoConfiguration.class) +public class SeataFeignClientAutoConfiguration { + + @Bean + @Scope("prototype") + @ConditionalOnClass(name = "com.alibaba.csp.sentinel.SphU") + @ConditionalOnProperty(name = "feign.sentinel.enabled", havingValue = "true") + Feign.Builder feignSentinelBuilder(BeanFactory beanFactory) { + return BladeFeignSentinel.builder().retryer(Retryer.NEVER_RETRY) + .client(new SeataFeignClient(beanFactory)); + } + + @Bean + @ConditionalOnMissingBean + @Scope("prototype") + Feign.Builder feignBuilder(BeanFactory beanFactory) { + return SeataFeignBuilder.builder(beanFactory); + } + + @Configuration(proxyBeanMethods = false) + @RequiredArgsConstructor + protected static class FeignBeanPostProcessorConfiguration { + private final LoadBalancedRetryFactory loadBalancedRetryFactory; + private final LoadBalancerProperties properties; + private final LoadBalancerClientFactory loadBalancerClientFactory; + + @Bean + SeataBeanPostProcessor seataBeanPostProcessor(SeataFeignObjectWrapper seataFeignObjectWrapper) { + return new SeataBeanPostProcessor(seataFeignObjectWrapper); + } + + @Bean + SeataContextBeanPostProcessor seataContextBeanPostProcessor(BeanFactory beanFactory) { + return new SeataContextBeanPostProcessor(beanFactory); + } + + @Bean + SeataFeignObjectWrapper seataFeignObjectWrapper(BeanFactory beanFactory) { + return new SeataFeignObjectWrapper(beanFactory, loadBalancedRetryFactory, properties, loadBalancerClientFactory); + } + + } +} diff --git a/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java new file mode 100644 index 0000000..436300f --- /dev/null +++ b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.cloud.seata.feign; + +import feign.Client; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; +import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient; + +/** + * 重写SeataFeignObjectWrapper以适配最新API + * + * @author Chill + */ +public class SeataFeignObjectWrapper { + + private final BeanFactory beanFactory; + private final LoadBalancedRetryFactory loadBalancedRetryFactory; + private final LoadBalancerProperties properties; + private final LoadBalancerClientFactory loadBalancerClientFactory; + + private SpringClientFactory springClientFactory; + + SeataFeignObjectWrapper(BeanFactory beanFactory, LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerProperties properties, LoadBalancerClientFactory loadBalancerClientFactory) { + this.beanFactory = beanFactory; + this.loadBalancedRetryFactory = loadBalancedRetryFactory; + this.properties = properties; + this.loadBalancerClientFactory = loadBalancerClientFactory; + } + + Object wrap(Object bean) { + if (bean instanceof Client && !(bean instanceof SeataFeignClient)) { + if (bean instanceof FeignBlockingLoadBalancerClient) { + FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean; + return new SeataFeignBlockingLoadBalancerClient(client.getDelegate(), + beanFactory.getBean(BlockingLoadBalancerClient.class), this, properties, loadBalancerClientFactory); + } + if (bean instanceof RetryableFeignBlockingLoadBalancerClient) { + RetryableFeignBlockingLoadBalancerClient client = (RetryableFeignBlockingLoadBalancerClient) bean; + return new SeataRetryableFeignBlockingLoadBalancerClient(client.getDelegate(), + beanFactory.getBean(BlockingLoadBalancerClient.class), this, loadBalancedRetryFactory, properties, loadBalancerClientFactory); + } + return new SeataFeignClient(this.beanFactory, (Client) bean); + } + return bean; + } + + SpringClientFactory clientFactory() { + if (this.springClientFactory == null) { + this.springClientFactory = this.beanFactory + .getBean(SpringClientFactory.class); + } + return this.springClientFactory; + } + +} diff --git a/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataRetryableFeignBlockingLoadBalancerClient.java b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataRetryableFeignBlockingLoadBalancerClient.java new file mode 100644 index 0000000..31cc2dc --- /dev/null +++ b/blade-core-transaction/src/main/java/com/alibaba/cloud/seata/feign/SeataRetryableFeignBlockingLoadBalancerClient.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.cloud.seata.feign; + +import feign.Client; +import feign.Request; +import feign.Response; +import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient; + +import java.io.IOException; + +/** + * 拓展SeataRetryableFeignBlockingLoadBalancerClient以适配最新API + * + * @author Chill + */ +public class SeataRetryableFeignBlockingLoadBalancerClient extends RetryableFeignBlockingLoadBalancerClient { + + public SeataRetryableFeignBlockingLoadBalancerClient(Client delegate, + BlockingLoadBalancerClient loadBalancerClient, + SeataFeignObjectWrapper seataFeignObjectWrapper, + LoadBalancedRetryFactory loadBalancedRetryFactory, + LoadBalancerProperties properties, + LoadBalancerClientFactory loadBalancerClientFactory) { + super((Client) seataFeignObjectWrapper.wrap(delegate), loadBalancerClient, loadBalancedRetryFactory, properties, loadBalancerClientFactory); + } + + @Override + public Response execute(Request request, Request.Options options) throws IOException { + return super.execute(request, options); + } +} diff --git a/blade-core-transaction/src/main/java/org/springblade/core/transaction/annotation/SeataCloudApplication.java b/blade-core-transaction/src/main/java/org/springblade/core/transaction/annotation/SeataCloudApplication.java index 2a9ed85..edc3566 100644 --- a/blade-core-transaction/src/main/java/org/springblade/core/transaction/annotation/SeataCloudApplication.java +++ b/blade-core-transaction/src/main/java/org/springblade/core/transaction/annotation/SeataCloudApplication.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2028, lengleng (wangiegie@gmail.com). + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). *

* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import java.lang.annotation.*; @@ -33,7 +34,7 @@ import java.lang.annotation.*; @Inherited @EnableDiscoveryClient @EnableCircuitBreaker -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, RibbonAutoConfiguration.class}) public @interface SeataCloudApplication { } diff --git a/blade-core-transaction/src/main/java/org/springblade/core/transaction/config/DataSourceConfiguration.java b/blade-core-transaction/src/main/java/org/springblade/core/transaction/config/DataSourceConfiguration.java index 2d6424e..a6cfb48 100644 --- a/blade-core-transaction/src/main/java/org/springblade/core/transaction/config/DataSourceConfiguration.java +++ b/blade-core-transaction/src/main/java/org/springblade/core/transaction/config/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2028, lengleng (wangiegie@gmail.com). + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). *

* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import org.springframework.context.annotation.Configuration; * * @author Chill */ -@Configuration +@Configuration(proxyBeanMethods = false) public class DataSourceConfiguration { } diff --git a/pom.xml b/pom.xml index a610c2d..8d90a88 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springblade blade-tool - 2.8.0 + 3.0.0 pom blade-tool @@ -36,24 +36,24 @@ - 2.8.0 + 3.0.0 1.8 3.8.0 2.10.5 1.6.2 - 2.0.6 - 3.4.0 + 2.0.8 + 3.4.1 1.6.0 3.4.2 - 2.3.0 + 2.3.1 1.2.5 2.2.3.RELEASE - 1.3.0 + 1.4.1 2.0.0.RELEASE - 2.2.11.RELEASE - Hoxton.SR8 + 2.4.1 + 2020.0.0 Cairo-SR8 UTF-8 @@ -141,6 +141,11 @@ lombok provided + + org.hibernate.validator + hibernate-validator + 6.2.0.Final + net.dreamlu mica-auto