diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 8cec3380b..edef3061d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -98,10 +98,10 @@ jobs: run: echo '127.0.0.1 livk.com' | sudo tee -a /etc/hosts - uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: - java-version: 17 + java-version: 21 distribution: 'temurin' - name: Build with Gradle uses: gradle/gradle-build-action@v2.9.0 diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml deleted file mode 100644 index 8d07ac56c..000000000 --- a/.github/workflows/greetings.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Greetings - -on: [ pull_request_target, issues ] - -jobs: - greeting: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/first-interaction@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: "感谢提交PR(Thanks for submitting the PR)" - issue-message: "感谢提交issue(Thanks for submitting the issue)" diff --git a/.sdkmanrc b/.sdkmanrc index a0d9ca7ee..54cfaaa0e 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1 +1 @@ -java=17.0.9-open +java=21-open diff --git a/build.gradle.kts b/build.gradle.kts index e6e5c65db..35eaab323 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -47,6 +47,7 @@ configure(gradleModuleProjects) { allprojects { repositories { + maven("https://repo.spring.io/milestone/") maven("https://repo.spring.io/release") maven("https://maven.aliyun.com/repository/public") maven("https://mirrors.cloud.tencent.com/nexus/repository/maven-public/") diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index f59f79eaa..5e0c8c45c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -4,6 +4,7 @@ plugins { } repositories { + maven("https://repo.spring.io/milestone") maven("https://repo.spring.io/release") maven("https://maven.aliyun.com/repository/public") maven("https://mirrors.cloud.tencent.com/nexus/repository/maven-public/") diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 87968954e..74e87d7fb 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -7,7 +7,7 @@ dependencyResolutionManagement { } gradle.settingsEvaluated { - if (JavaVersion.current() < JavaVersion.VERSION_17) { - throw GradleException("This build requires JDK 17. It's currently ${JavaVersion.current()}. You can ignore this check by passing '-Dorg.gradle.ignoreBuildJavaVersionCheck'.") + if (JavaVersion.current() < JavaVersion.VERSION_21) { + throw GradleException("This build requires JDK 21. It's currently ${JavaVersion.current()}. You can ignore this check by passing '-Dorg.gradle.ignoreBuildJavaVersionCheck'.") } } diff --git a/buildSrc/src/main/kotlin/com/livk/boot/compile/CompileArgsPlugin.kt b/buildSrc/src/main/kotlin/com/livk/boot/compile/CompileArgsPlugin.kt index b51500b3d..fe54e677c 100644 --- a/buildSrc/src/main/kotlin/com/livk/boot/compile/CompileArgsPlugin.kt +++ b/buildSrc/src/main/kotlin/com/livk/boot/compile/CompileArgsPlugin.kt @@ -24,6 +24,8 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.api.tasks.testing.Test +import org.gradle.external.javadoc.JavadocOutputLevel +import org.gradle.external.javadoc.StandardJavadocDocletOptions /** * @author livk @@ -52,7 +54,11 @@ abstract class CompileArgsPlugin : Plugin { override fun apply(project: Project) { project.pluginManager.apply(JavaPlugin::class.java) project.tasks.withType(Javadoc::class.java) { javadoc -> - javadoc.options.encoding(UTF_8) + val options = javadoc.options as StandardJavadocDocletOptions + options.encoding(UTF_8) + javadoc.isFailOnError = false + options.outputLevel = JavadocOutputLevel.QUIET + options.addStringOption("Xdoclint:none", "-quiet") } val javaCompile = project.tasks.named(JavaPlugin.COMPILE_JAVA_TASK_NAME).get() as JavaCompile addCompile(javaCompile) @@ -81,7 +87,7 @@ abstract class CompileArgsPlugin : Plugin { private fun addCompile(javaCompile: JavaCompile) { javaCompile.options.compilerArgs.addAll(COMPILER_ARGS) javaCompile.options.encoding = UTF_8 - javaCompile.sourceCompatibility = JavaVersion.VERSION_17.toString() - javaCompile.targetCompatibility = JavaVersion.VERSION_17.toString() + javaCompile.sourceCompatibility = JavaVersion.VERSION_21.toString() + javaCompile.targetCompatibility = JavaVersion.VERSION_21.toString() } } diff --git a/gradle.properties b/gradle.properties index f156842e7..19d5ab8a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ #project args group=io.github.livk-cloud -version=1.1.6 +version=1.2.0-SNAPSHOT org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 org.gradle.daemon=true org.gradle.parallel=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a4b061796..ff41b3455 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] -spring-boot = "3.1.6" +spring-boot = "3.2.0" kotlin = "1.9.21" pagehelper = "6.0.0" pagehelper-starter = "2.0.0" mybatis = "3.5.14" -spring-mybatis = "3.0.2" +spring-mybatis = "3.0.3" guava = "32.1.3-jre" easyexcel = "3.3.2" java-web-socket = "1.5.4" @@ -79,7 +79,6 @@ lombok-mapstruct = { group = "org.projectlombok", name = "lombok-mapstruct-bindi guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } easyexcel = { group = "com.alibaba", name = "easyexcel", version.ref = "easyexcel" } java-webSocket = { group = "org.java-websocket", name = "Java-WebSocket", version.ref = "java-web-socket" } -spring-pulsar-starter = { group = "org.springframework.pulsar", name = "spring-pulsar-spring-boot-starter", version.ref = "spring-pulsar" } spotbugs-annotations = { group = "com.github.spotbugs", name = "spotbugs-annotations", version.ref = "spotbugs-annotations" } curator-recipes = { group = "org.apache.curator", name = "curator-recipes", version.ref = "curator" } ip2region = { group = "org.lionsoul", name = "ip2region", version.ref = "ip2region" } @@ -93,7 +92,6 @@ jsqlparser = { group = "com.github.jsqlparser", name = "jsqlparser", version.ref lettucemod = { group = "com.redis", name = "lettucemod", version.ref = "lettucemod" } minio = { group = "io.minio", name = "minio", version.ref = "minio" } dnsjava = { group = "dnsjava", name = "dnsjava", version.ref = "dnsjava" } -snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml" } aliyun-oss = { group = "com.aliyun.oss", name = "aliyun-sdk-oss", version.ref = "aliyun-oss" } aviator = { group = "com.googlecode.aviator", name = "aviator", version.ref = "aviator" } protobuf-java = { group = "com.google.protobuf", name = "protobuf-java", version.ref = "protobuf-java" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 2c1a0a37d..a32ddea78 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -35,7 +35,7 @@ fileTree(rootDir) { } gradle.settingsEvaluated { - if (JavaVersion.current() < JavaVersion.VERSION_17) { - throw GradleException("This build requires JDK 17. It's currently ${JavaVersion.current()}. You can ignore this check by passing '-Dorg.gradle.ignoreBuildJavaVersionCheck'.") + if (JavaVersion.current() < JavaVersion.VERSION_21) { + throw GradleException("This build requires JDK 21. It's currently ${JavaVersion.current()}. You can ignore this check by passing '-Dorg.gradle.ignoreBuildJavaVersionCheck'.") } } diff --git a/spring-boot-example/spring-authorization-server/auth-server/src/main/java/com/livk/auth/server/config/AuthorizationServerConfiguration.java b/spring-boot-example/spring-authorization-server/auth-server/src/main/java/com/livk/auth/server/config/AuthorizationServerConfiguration.java index 5d4b5ee6c..1209ef954 100644 --- a/spring-boot-example/spring-authorization-server/auth-server/src/main/java/com/livk/auth/server/config/AuthorizationServerConfiguration.java +++ b/spring-boot-example/spring-authorization-server/auth-server/src/main/java/com/livk/auth/server/config/AuthorizationServerConfiguration.java @@ -35,6 +35,7 @@ import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.userdetails.UserDetailsService; @@ -84,18 +85,16 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h OAuth2SmsAuthenticationProvider smsAuthenticationProvider = new OAuth2SmsAuthenticationProvider( authenticationManager, authorizationService, oAuth2TokenGenerator); - OAuth2AuthorizationServerConfigurer configurer = authorizationServerConfigurer + http.with(authorizationServerConfigurer, configurer -> configurer .tokenEndpoint((tokenEndpoint) -> tokenEndpoint.accessTokenRequestConverter(accessTokenRequestConverter()) .authenticationProvider(passwordAuthenticationProvider) .authenticationProvider(smsAuthenticationProvider) .accessTokenResponseHandler(new AuthenticationSuccessEventHandler()) .errorResponseHandler(new AuthenticationFailureEventHandler())) .authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint - .consentPage(SecurityConstants.CUSTOM_CONSENT_PAGE_URI)); - - http.apply(configurer); - http.apply(configurer.authorizationService(authorizationService)); - http.apply(new FormIdentityLoginConfigurer()); + .consentPage(SecurityConstants.CUSTOM_CONSENT_PAGE_URI)) + .authorizationService(authorizationService)) + .with(new FormIdentityLoginConfigurer(), Customizer.withDefaults()); RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher(); HttpSessionSecurityContextRepository httpSessionSecurityContextRepository = new HttpSessionSecurityContextRepository(); diff --git a/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/KafkaConstant.java b/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/KafkaConstant.java index feb5df900..b3861a3b6 100644 --- a/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/KafkaConstant.java +++ b/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/KafkaConstant.java @@ -28,6 +28,4 @@ public interface KafkaConstant { String TOPIC = "livk-topic"; - String NEW_TOPIC = "livk-new-topic"; - } diff --git a/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/config/KafkaConfig.java b/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/config/KafkaConfig.java index 9b81d8f0e..79842f6a0 100644 --- a/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/config/KafkaConfig.java +++ b/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/config/KafkaConfig.java @@ -32,14 +32,14 @@ public class KafkaConfig { @Bean public KafkaAdmin myKafkaAdmin(KafkaProperties kafkaProperties) { - KafkaAdmin admin = new KafkaAdmin(kafkaProperties.buildAdminProperties()); + KafkaAdmin admin = new KafkaAdmin(kafkaProperties.buildAdminProperties(null)); admin.setFatalIfBrokerNotAvailable(true); return admin; } @Bean public NewTopic myTopic() { - return new NewTopic(KafkaConstant.NEW_TOPIC, 1, (short) 1); + return new NewTopic(KafkaConstant.TOPIC, 1, (short) 1); } } diff --git a/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/controller/ProducerController.java b/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/controller/ProducerController.java index 8e3e335c6..022b391e3 100644 --- a/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/controller/ProducerController.java +++ b/spring-boot-example/spring-kafka/src/main/java/com/livk/kafka/controller/ProducerController.java @@ -44,7 +44,7 @@ public class ProducerController { public void producer() { kafkaTemplate.send(KafkaConstant.TOPIC, UUID.randomUUID().toString()); // 异步获取结果 - kafkaTemplate.send(KafkaConstant.NEW_TOPIC, UUID.randomUUID().toString()).whenComplete((result, throwable) -> { + kafkaTemplate.send(KafkaConstant.TOPIC, UUID.randomUUID().toString()).whenComplete((result, throwable) -> { if (throwable != null) { log.error("ex:{}", throwable.getMessage()); } @@ -53,7 +53,7 @@ public void producer() { } }); // 同步获取结果 - CompletableFuture> future = kafkaTemplate.send(KafkaConstant.NEW_TOPIC, + CompletableFuture> future = kafkaTemplate.send(KafkaConstant.TOPIC, UUID.randomUUID().toString()); try { SendResult result = future.get(); diff --git a/spring-boot-example/spring-kafka/src/test/java/com/livk/kafka/controller/ProducerControllerTest.java b/spring-boot-example/spring-kafka/src/test/java/com/livk/kafka/controller/ProducerControllerTest.java index faa34d0bc..94c2d46d1 100644 --- a/spring-boot-example/spring-kafka/src/test/java/com/livk/kafka/controller/ProducerControllerTest.java +++ b/spring-boot-example/spring-kafka/src/test/java/com/livk/kafka/controller/ProducerControllerTest.java @@ -17,6 +17,7 @@ package com.livk.kafka.controller; +import com.livk.kafka.KafkaConstant; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -32,7 +33,7 @@ * @author livk */ @AutoConfigureMockMvc -@SpringBootTest("spring.kafka.bootstrap-servers=localhost:9092") +@SpringBootTest @EmbeddedKafka(ports = 9092) class ProducerControllerTest { diff --git a/spring-boot-example/spring-micrometer/micrometer-tracing/src/main/java/com/livk/micrometer/tracing/MicrometerTraceApp.java b/spring-boot-example/spring-micrometer/micrometer-tracing/src/main/java/com/livk/micrometer/tracing/MicrometerTraceApp.java index a6254fef3..74c4ea2e9 100644 --- a/spring-boot-example/spring-micrometer/micrometer-tracing/src/main/java/com/livk/micrometer/tracing/MicrometerTraceApp.java +++ b/spring-boot-example/spring-micrometer/micrometer-tracing/src/main/java/com/livk/micrometer/tracing/MicrometerTraceApp.java @@ -46,7 +46,7 @@ public static void main(String[] args) { @GetMapping("home") public String home() { log.info("home() has been called"); - ExecutorService wrap = ContextSnapshots.wrap(Executors.newFixedThreadPool(2)); + ExecutorService wrap = ContextSnapshots.wrap(Executors.newFixedThreadPool(2, Thread.ofVirtual().factory())); for (int i = 0; i < 3; i++) { wrap.execute(() -> log.info("home")); } diff --git a/spring-boot-example/spring-protobuf-mq/spring-protobuf-kafka/src/test/java/com/livk/proto/kafka/controller/UserControllerTest.java b/spring-boot-example/spring-protobuf-mq/spring-protobuf-kafka/src/test/java/com/livk/proto/kafka/controller/UserControllerTest.java index b047a455b..e63e6fb45 100644 --- a/spring-boot-example/spring-protobuf-mq/spring-protobuf-kafka/src/test/java/com/livk/proto/kafka/controller/UserControllerTest.java +++ b/spring-boot-example/spring-protobuf-mq/spring-protobuf-kafka/src/test/java/com/livk/proto/kafka/controller/UserControllerTest.java @@ -30,7 +30,7 @@ /** * @author livk */ -@SpringBootTest("spring.kafka.bootstrap-servers=localhost:9092") +@SpringBootTest @EmbeddedKafka(ports = 9092) @AutoConfigureMockMvc class UserControllerTest { diff --git a/spring-boot-example/spring-protobuf-mq/spring-protobuf-pulsar/build.gradle.kts b/spring-boot-example/spring-protobuf-mq/spring-protobuf-pulsar/build.gradle.kts index 83c73c38d..539712e39 100644 --- a/spring-boot-example/spring-protobuf-mq/spring-protobuf-pulsar/build.gradle.kts +++ b/spring-boot-example/spring-protobuf-mq/spring-protobuf-pulsar/build.gradle.kts @@ -4,6 +4,6 @@ plugins { dependencies { implementation(project(":spring-boot-example:spring-protobuf-mq:protobuf-commons")) - implementation("org.springframework.pulsar:spring-pulsar-spring-boot-starter") + implementation("org.springframework.boot:spring-boot-starter-pulsar") implementation("org.springframework.boot:spring-boot-starter-web") } diff --git a/spring-boot-example/spring-pulsar/pulsar-commons/build.gradle.kts b/spring-boot-example/spring-pulsar/pulsar-commons/build.gradle.kts index 0b35d35ae..c34062b13 100644 --- a/spring-boot-example/spring-pulsar/pulsar-commons/build.gradle.kts +++ b/spring-boot-example/spring-pulsar/pulsar-commons/build.gradle.kts @@ -4,6 +4,6 @@ plugins { dependencies { api(project(":spring-extension-commons")) - api("org.springframework.pulsar:spring-pulsar-spring-boot-starter") + api("org.springframework.boot:spring-boot-starter-pulsar") api("org.springframework.boot:spring-boot-autoconfigure") } diff --git a/spring-boot-example/spring-pulsar/pulsar-producer/src/test/java/com/livk/pulsar/producer/controller/MessageControllerTest.java b/spring-boot-example/spring-pulsar/pulsar-producer/src/test/java/com/livk/pulsar/producer/controller/MessageControllerTest.java index d21525060..088e3c013 100644 --- a/spring-boot-example/spring-pulsar/pulsar-producer/src/test/java/com/livk/pulsar/producer/controller/MessageControllerTest.java +++ b/spring-boot-example/spring-pulsar/pulsar-producer/src/test/java/com/livk/pulsar/producer/controller/MessageControllerTest.java @@ -39,7 +39,7 @@ * @author livk */ @SpringBootTest({ "spring.pulsar.client.service-url=pulsar://livk.com:6650", "spring.pulsar.consumer.topics=livk-topic", - "spring.pulsar.consumer.subscription-name=consumer" }) + "spring.pulsar.consumer.subscription.name=consumer" }) @AutoConfigureMockMvc class MessageControllerTest { diff --git a/spring-boot-example/spring-websocket/spring-websocket-session/src/test/java/com/livk/socket/WebSocketClientTestTest.java b/spring-boot-example/spring-websocket/spring-websocket-session/src/test/java/com/livk/socket/WebSocketClientTestTest.java index fdd02480a..c450f3acb 100644 --- a/spring-boot-example/spring-websocket/spring-websocket-session/src/test/java/com/livk/socket/WebSocketClientTestTest.java +++ b/spring-boot-example/spring-websocket/spring-websocket-session/src/test/java/com/livk/socket/WebSocketClientTestTest.java @@ -44,14 +44,15 @@ class WebSocketClientTestTest { void testMain() { String uri = "ws://127.0.0.1:8888/websocket/"; int threadNum = 1000; - ExecutorService service = Executors.newFixedThreadPool(threadNum); - CountDownLatch countDownLatch = new CountDownLatch(threadNum); - for (int i = 0; i < threadNum; i++) { - String url = uri + "No" + i; - service.submit(new WebSocketClientTest(url, countDownLatch)); - countDownLatch.countDown(); + try (ExecutorService service = Executors.newFixedThreadPool(threadNum, Thread.ofVirtual().factory())) { + CountDownLatch countDownLatch = new CountDownLatch(threadNum); + for (int i = 0; i < threadNum; i++) { + String url = uri + "No" + i; + service.submit(new WebSocketClientTest(url, countDownLatch)); + countDownLatch.countDown(); + } + assertEquals(0, countDownLatch.getCount()); } - assertEquals(0, countDownLatch.getCount()); } } diff --git a/spring-boot-example/spring-zookeeper/zookeeper-lock/src/test/java/com/livk/zookeeper/LockControllerTest.java b/spring-boot-example/spring-zookeeper/zookeeper-lock/src/test/java/com/livk/zookeeper/LockControllerTest.java index 6398ef61d..166b6b07d 100644 --- a/spring-boot-example/spring-zookeeper/zookeeper-lock/src/test/java/com/livk/zookeeper/LockControllerTest.java +++ b/spring-boot-example/spring-zookeeper/zookeeper-lock/src/test/java/com/livk/zookeeper/LockControllerTest.java @@ -42,22 +42,23 @@ class LockControllerTest { @Test void lock() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(10); - CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - String param = String.valueOf(i); - service.submit(() -> { - try { - mockMvc.perform(get("/lock").queryParam("id", param)).andExpect(status().isOk()); - countDownLatch.countDown(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - }); + try (ExecutorService service = Executors.newFixedThreadPool(10, Thread.ofVirtual().factory())) { + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + String param = String.valueOf(i); + service.submit(() -> { + try { + mockMvc.perform(get("/lock").queryParam("id", param)).andExpect(status().isOk()); + countDownLatch.countDown(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + countDownLatch.await(); + service.shutdown(); } - countDownLatch.await(); - service.shutdown(); } } diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/ClassPathHttpScanner.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/ClassPathHttpScanner.java index 30ff6e521..96b9404d6 100644 --- a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/ClassPathHttpScanner.java +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/ClassPathHttpScanner.java @@ -17,7 +17,12 @@ package com.livk.autoconfigure.http; +import com.livk.autoconfigure.http.adapter.AdapterFactory; +import com.livk.autoconfigure.http.adapter.AdapterType; +import com.livk.autoconfigure.http.annotation.HttpProvider; import com.livk.autoconfigure.http.factory.HttpFactoryBean; +import com.livk.commons.util.AnnotationUtils; +import com.livk.commons.util.ClassUtils; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; @@ -28,10 +33,13 @@ import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.AnnotationBeanNameGenerator; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; +import org.springframework.context.annotation.ScannedGenericBeanDefinition; +import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.lang.NonNull; import org.springframework.util.Assert; +import org.springframework.web.service.invoker.HttpExchangeAdapter; import java.lang.annotation.Annotation; import java.util.LinkedHashSet; @@ -78,19 +86,29 @@ protected Set doScan(@NonNull String... basePackages) { for (String basePackage : basePackages) { Set candidateComponents = findCandidateComponents(basePackage); for (BeanDefinition candidateComponent : candidateComponents) { - String beanClassName = candidateComponent.getBeanClassName(); - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HttpFactoryBean.class); - builder.addPropertyValue("type", beanClassName); - builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); + if (candidateComponent instanceof ScannedGenericBeanDefinition scannedGenericBeanDefinition) { + AnnotationAttributes attributes = AnnotationUtils + .attributesFor(scannedGenericBeanDefinition.getMetadata(), HttpProvider.class); + AdapterType type = attributes.getEnum("type"); + AdapterFactory adapterFactory = AdapterType.builder(type); + String beanClassName = candidateComponent.getBeanClassName(); + Assert.notNull(beanClassName, "beanClassName not be null"); + Class beanType = ClassUtils.resolveClassName(beanClassName, + super.getResourceLoader().getClassLoader()); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HttpFactoryBean.class); + builder.addPropertyValue("type", beanType); + builder.addPropertyValue("adapterFactory", adapterFactory); + builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); - String beanName = beanNameGenerator.generateBeanName(candidateComponent, registry); - if (checkCandidate(beanName, beanDefinition)) { - beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, beanClassName); + AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); + String beanName = beanNameGenerator.generateBeanName(candidateComponent, registry); + if (checkCandidate(beanName, beanDefinition)) { + beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, beanType); - BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, beanName); - beanDefinitions.add(holder); - registerBeanDefinition(holder, registry); + BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, beanName); + beanDefinitions.add(holder); + registerBeanDefinition(holder, registry); + } } } } diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/HttpInterfaceAutoConfiguration.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/HttpInterfaceAutoConfiguration.java index 030afd026..e3ae312d6 100644 --- a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/HttpInterfaceAutoConfiguration.java +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/HttpInterfaceAutoConfiguration.java @@ -20,19 +20,12 @@ import com.livk.auto.service.annotation.SpringAutoService; import com.livk.autoconfigure.http.customizer.HttpServiceProxyFactoryCustomizer; import com.livk.autoconfigure.http.factory.HttpServiceRegistrar; -import com.livk.commons.http.WebClientConfiguration; -import com.livk.commons.http.annotation.EnableWebClient; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.EmbeddedValueResolver; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.support.WebClientAdapter; -import org.springframework.web.service.invoker.HttpServiceProxyFactory; /** *

@@ -41,43 +34,16 @@ * * @author livk */ -@EnableWebClient -@AutoConfiguration(after = WebClientConfiguration.class) +@AutoConfiguration @SpringAutoService @Import(HttpServiceRegistrar.class) -@ConditionalOnClass(value = WebClient.class, name = "com.livk.http.marker.HttpMarker") +@ConditionalOnClass(name = "com.livk.http.marker.HttpMarker") public class HttpInterfaceAutoConfiguration { - /** - * Web client web client. - * @param builder the builder - * @return the web client - */ - @Bean - @ConditionalOnMissingBean - public WebClient webClient(WebClient.Builder builder) { - return builder.build(); - } - - /** - * Http service proxy factory http service proxy factory. - * @param webClient the web client - * @param customizers the customizers - * @return the http service proxy factory - */ - @Bean - public HttpServiceProxyFactory httpServiceProxyFactory(WebClient webClient, - ObjectProvider customizers) { - HttpServiceProxyFactory.Builder builder = HttpServiceProxyFactory - .builder(WebClientAdapter.forClient(webClient)); - customizers.orderedStream().forEach(customizer -> customizer.customize(builder)); - return builder.build(); - } - /** * 添加SpringEL解析 * @param beanFactory bean factory - * @return HttpServiceProxyFactoryCustomizer + * @return HttpServiceProxyFactoryCustomizer http service proxy factory customizer */ @Bean public HttpServiceProxyFactoryCustomizer embeddedValueResolverCustomizer(ConfigurableBeanFactory beanFactory) { diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/AdapterFactory.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/AdapterFactory.java new file mode 100644 index 000000000..c730d7d1f --- /dev/null +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/AdapterFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.autoconfigure.http.adapter; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.web.service.invoker.HttpExchangeAdapter; + +/** + * @author livk + */ +public interface AdapterFactory { + + H create(BeanFactory beanFactory); + +} diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/AdapterType.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/AdapterType.java new file mode 100644 index 000000000..a3dca2980 --- /dev/null +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/AdapterType.java @@ -0,0 +1,105 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.autoconfigure.http.adapter; + +import com.livk.commons.util.ClassUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.support.RestClientAdapter; +import org.springframework.web.client.support.RestTemplateAdapter; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.support.WebClientAdapter; +import org.springframework.web.service.invoker.HttpExchangeAdapter; + +/** + * @author livk + */ +@RequiredArgsConstructor +public enum AdapterType { + + REST_TEMPLATE, + + WEB_CLIENT, + + REST_CLIENT, + + /** + * 适配器模式自动检测,出现多个情况,默认顺序为 {@link WebClient} > {@link RestClient} > + * {@link RestTemplate} + */ + AUTO; + + @SuppressWarnings("unchecked") + public static > T builder(AdapterType type) { + return switch (type) { + case REST_TEMPLATE -> (T) new RestTemplateAdapterWrapper(); + case WEB_CLIENT -> (T) new WebClientAdapterWrapper(); + case REST_CLIENT -> (T) new RestClientAdapterWrapper(); + case AUTO -> { + ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); + if (ClassUtils.isPresent("org.springframework.web.reactive.function.client.WebClient", classLoader)) { + yield (T) new WebClientAdapterWrapper(); + } + else if (ClassUtils.isPresent("org.springframework.web.client.RestClient", classLoader)) { + yield (T) new RestClientAdapterWrapper(); + } + else if (ClassUtils.isPresent("org.springframework.web.client.RestTemplate", classLoader)) { + yield (T) new RestTemplateAdapterWrapper(); + } + throw new UnsupportedOperationException("缺少构建HttpExchangeAdapter的类信息"); + } + }; + } + + private static class RestTemplateAdapterWrapper implements AdapterFactory { + + @Override + public RestTemplateAdapter create(BeanFactory beanFactory) { + RestTemplate restTemplate = beanFactory.getBeanProvider(RestTemplate.class) + .getIfAvailable(() -> beanFactory.getBean(RestTemplateBuilder.class).build()); + return RestTemplateAdapter.create(restTemplate); + } + + } + + private static class WebClientAdapterWrapper implements AdapterFactory { + + @Override + public WebClientAdapter create(BeanFactory beanFactory) { + WebClient webClient = beanFactory.getBeanProvider(WebClient.class) + .getIfAvailable(() -> beanFactory.getBean(WebClient.Builder.class).build()); + return WebClientAdapter.create(webClient); + } + + } + + private static class RestClientAdapterWrapper implements AdapterFactory { + + @Override + public RestClientAdapter create(BeanFactory beanFactory) { + RestClient restClient = beanFactory.getBeanProvider(RestClient.class) + .getIfAvailable(() -> beanFactory.getBean(RestClient.Builder.class).build()); + return RestClientAdapter.create(restClient); + } + + } + +} diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/BeanFactoryHttpExchangeAdapter.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/BeanFactoryHttpExchangeAdapter.java new file mode 100644 index 000000000..a227f1359 --- /dev/null +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/adapter/BeanFactoryHttpExchangeAdapter.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.autoconfigure.http.adapter; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.lang.NonNull; +import org.springframework.web.service.invoker.HttpExchangeAdapter; +import org.springframework.web.service.invoker.HttpRequestValues; + +/** + * The type Bean factory http exchange adapter. + * + * @author livk + */ +public class BeanFactoryHttpExchangeAdapter implements HttpExchangeAdapter { + + private final HttpExchangeAdapter adapter; + + /** + * Instantiates a new Bean factory http exchange adapter. + * @param factory the factory + * @param beanFactory the bean factory + */ + public BeanFactoryHttpExchangeAdapter(AdapterFactory factory, BeanFactory beanFactory) { + adapter = factory.create(beanFactory); + } + + @Override + public boolean supportsRequestAttributes() { + return adapter.supportsRequestAttributes(); + } + + @Override + public void exchange(@NonNull HttpRequestValues requestValues) { + adapter.exchange(requestValues); + } + + @NonNull + @Override + public HttpHeaders exchangeForHeaders(@NonNull HttpRequestValues requestValues) { + return adapter.exchangeForHeaders(requestValues); + } + + @Override + public T exchangeForBody(@NonNull HttpRequestValues requestValues, + @NonNull ParameterizedTypeReference bodyType) { + return adapter.exchangeForBody(requestValues, bodyType); + } + + @NonNull + @Override + public ResponseEntity exchangeForBodilessEntity(@NonNull HttpRequestValues requestValues) { + return adapter.exchangeForBodilessEntity(requestValues); + } + + @NonNull + @Override + public ResponseEntity exchangeForEntity(@NonNull HttpRequestValues requestValues, + @NonNull ParameterizedTypeReference bodyType) { + return adapter.exchangeForEntity(requestValues, bodyType); + } + +} diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/annotation/HttpProvider.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/annotation/HttpProvider.java index f8e953506..572834708 100644 --- a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/annotation/HttpProvider.java +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/annotation/HttpProvider.java @@ -17,6 +17,7 @@ package com.livk.autoconfigure.http.annotation; +import com.livk.autoconfigure.http.adapter.AdapterType; import org.springframework.core.annotation.AliasFor; import org.springframework.stereotype.Component; import org.springframework.web.service.annotation.HttpExchange; @@ -40,6 +41,13 @@ @HttpExchange public @interface HttpProvider { + /** + * 指定适配器模式 + * @return AdapterType + * @see AdapterType + */ + AdapterType type() default AdapterType.AUTO; + /** * The value may indicate a suggestion for a logical component name, to be turned into * a Spring bean in case of an autodetected component. diff --git a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/factory/HttpFactoryBean.java b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/factory/HttpFactoryBean.java index 176169a04..99cc1eac6 100644 --- a/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/factory/HttpFactoryBean.java +++ b/spring-boot-extension-autoconfigure/src/main/java/com/livk/autoconfigure/http/factory/HttpFactoryBean.java @@ -17,14 +17,20 @@ package com.livk.autoconfigure.http.factory; -import com.livk.commons.util.ClassUtils; +import com.livk.autoconfigure.http.adapter.AdapterFactory; +import com.livk.autoconfigure.http.adapter.BeanFactoryHttpExchangeAdapter; +import com.livk.autoconfigure.http.customizer.HttpServiceProxyFactoryCustomizer; +import lombok.Setter; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.FactoryBean; import org.springframework.lang.NonNull; +import org.springframework.web.service.invoker.HttpExchangeAdapter; import org.springframework.web.service.invoker.HttpServiceProxyFactory; +import java.util.Objects; + /** *

* HttpFactoryBean @@ -32,24 +38,24 @@ * * @author livk */ +@Setter public class HttpFactoryBean implements FactoryBean, BeanFactoryAware { private BeanFactory beanFactory; private Class type; - /** - * Sets type. - * @param httpInterfaceTypeName the http interface type name - */ - public void setType(String httpInterfaceTypeName) { - type = ClassUtils.resolveClassName(httpInterfaceTypeName); - } + private AdapterFactory adapterFactory; @Override public Object getObject() { - HttpServiceProxyFactory proxyFactory = beanFactory.getBean(HttpServiceProxyFactory.class); - return proxyFactory.createClient(type); + HttpExchangeAdapter adapter = new BeanFactoryHttpExchangeAdapter(adapterFactory, beanFactory); + HttpServiceProxyFactory.Builder builder = HttpServiceProxyFactory.builderFor(adapter); + beanFactory.getBeanProvider(HttpServiceProxyFactoryCustomizer.class) + .orderedStream() + .forEach(customizer -> customizer.customize(builder)); + HttpServiceProxyFactory proxyFactory = builder.build(); + return proxyFactory.createClient(Objects.requireNonNull(getObjectType())); } @Override diff --git a/spring-boot-extension-starters/http-spring-boot-starter/build.gradle.kts b/spring-boot-extension-starters/http-spring-boot-starter/build.gradle.kts index ab5ae48c1..5558a100e 100644 --- a/spring-boot-extension-starters/http-spring-boot-starter/build.gradle.kts +++ b/spring-boot-extension-starters/http-spring-boot-starter/build.gradle.kts @@ -1,6 +1,5 @@ description = "http spring boot starter" dependencies { - api("org.springframework:spring-webflux") - api("io.projectreactor.netty:reactor-netty-http") + } diff --git a/spring-boot-extension-tests/http-spring-boot-test/build.gradle.kts b/spring-boot-extension-tests/http-spring-boot-test/build.gradle.kts index 4f2a9c15b..ac527d211 100644 --- a/spring-boot-extension-tests/http-spring-boot-test/build.gradle.kts +++ b/spring-boot-extension-tests/http-spring-boot-test/build.gradle.kts @@ -5,4 +5,5 @@ plugins { dependencies { implementation(project(":spring-boot-extension-starters:http-spring-boot-starter")) implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework:spring-webflux") } diff --git a/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/controller/HttpController.java b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/controller/HttpController.java index 01819b7b1..2f02a60c0 100644 --- a/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/controller/HttpController.java +++ b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/controller/HttpController.java @@ -17,10 +17,10 @@ package com.livk.http.controller; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.livk.http.service.RemoteService; +import com.google.common.collect.Maps; +import com.livk.http.service.JavaService; +import com.livk.http.service.SpringBootService; +import com.livk.http.service.SpringService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringBootVersion; @@ -30,6 +30,9 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; +import java.util.Objects; + /** *

* HttpController @@ -42,20 +45,34 @@ @RequiredArgsConstructor public class HttpController { - private final RemoteService service; + private final SpringBootService bootService; + + private final SpringService springService; + + private final JavaService javaService; @GetMapping("get") - public HttpEntity get() { - return ResponseEntity.ok(service.get()); + public HttpEntity> get() { + Map result = Maps.newHashMap(); + result.putAll(bootService.springBoot()); + result.putAll(springService.spring()); + result.putAll(javaService.java()); + return ResponseEntity.ok(result); + } + + @GetMapping("/rpc/spring-boot") + public Map springBoot() { + return Map.of("spring-boot-version", SpringBootVersion.getVersion()); + } + + @GetMapping("/rpc/spring") + public Map spring() { + return Map.of("spring-version", Objects.requireNonNull(SpringVersion.getVersion())); } - @GetMapping("rpc") - public JsonNode rpc() { - ObjectNode node = new ObjectNode(JsonNodeFactory.instance); - node.put("spring-boot-version", SpringBootVersion.getVersion()) - .put("spring-version", SpringVersion.getVersion()) - .put("java-version", System.getProperty("java.version")); - return node; + @GetMapping("/rpc/java") + public Map java() { + return Map.of("java-version", System.getProperty("java.version")); } } diff --git a/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/RemoteService.java b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/JavaService.java similarity index 76% rename from spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/RemoteService.java rename to spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/JavaService.java index 0b5af651d..90c8bbd64 100644 --- a/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/RemoteService.java +++ b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/JavaService.java @@ -17,9 +17,12 @@ package com.livk.http.service; +import com.livk.autoconfigure.http.adapter.AdapterType; import com.livk.autoconfigure.http.annotation.HttpProvider; import org.springframework.web.service.annotation.GetExchange; +import java.util.Map; + /** *

* RemoteService @@ -27,10 +30,10 @@ * * @author livk */ -@HttpProvider(url = "http://localhost:${server.port:8080}/rpc") -public interface RemoteService { +@HttpProvider(type = AdapterType.REST_TEMPLATE, url = "http://localhost:${server.port:8080}/rpc") +public interface JavaService { - @GetExchange() - String get(); + @GetExchange("java") + Map java(); } diff --git a/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/SpringBootService.java b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/SpringBootService.java new file mode 100644 index 000000000..99e00c72f --- /dev/null +++ b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/SpringBootService.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.http.service; + +import com.livk.autoconfigure.http.adapter.AdapterType; +import com.livk.autoconfigure.http.annotation.HttpProvider; +import org.springframework.web.service.annotation.GetExchange; + +import java.util.Map; + +/** + *

+ * RemoteService + *

+ * + * @author livk + */ +@HttpProvider(type = AdapterType.WEB_CLIENT, url = "http://localhost:${server.port:8080}/rpc") +public interface SpringBootService { + + @GetExchange("spring-boot") + Map springBoot(); + +} diff --git a/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/SpringService.java b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/SpringService.java new file mode 100644 index 000000000..60cc96b4f --- /dev/null +++ b/spring-boot-extension-tests/http-spring-boot-test/src/main/java/com/livk/http/service/SpringService.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.http.service; + +import com.livk.autoconfigure.http.adapter.AdapterType; +import com.livk.autoconfigure.http.annotation.HttpProvider; +import org.springframework.web.service.annotation.GetExchange; + +import java.util.Map; + +/** + *

+ * RemoteService + *

+ * + * @author livk + */ +@HttpProvider(type = AdapterType.REST_CLIENT, url = "http://localhost:${server.port:8080}/rpc") +public interface SpringService { + + @GetExchange("spring") + Map spring(); + +} diff --git a/spring-boot-extension-tests/lock-spring-boot-test/curator-lock-spring-boot-test/src/test/java/com/livk/curator/lock/ShopControllerTest.java b/spring-boot-extension-tests/lock-spring-boot-test/curator-lock-spring-boot-test/src/test/java/com/livk/curator/lock/ShopControllerTest.java index ed4fecc4b..b5c12b8b2 100644 --- a/spring-boot-extension-tests/lock-spring-boot-test/curator-lock-spring-boot-test/src/test/java/com/livk/curator/lock/ShopControllerTest.java +++ b/spring-boot-extension-tests/lock-spring-boot-test/curator-lock-spring-boot-test/src/test/java/com/livk/curator/lock/ShopControllerTest.java @@ -50,21 +50,22 @@ class ShopControllerTest { @Order(1) @Test void testBuyLocal() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(10); - CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - service.submit(() -> { - try { - mockMvc.perform(post("/shop/buy/distributed")).andExpect(status().isOk()); - countDownLatch.countDown(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - }); + try (ExecutorService service = Executors.newFixedThreadPool(10, Thread.ofVirtual().factory())) { + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + service.submit(() -> { + try { + mockMvc.perform(post("/shop/buy/distributed")).andExpect(status().isOk()); + countDownLatch.countDown(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + countDownLatch.await(); + service.shutdown(); } - countDownLatch.await(); - service.shutdown(); } @Order(2) diff --git a/spring-boot-extension-tests/lock-spring-boot-test/local-lock-spring-boot-test/src/test/java/com/livk/local/lock/ShopControllerTest.java b/spring-boot-extension-tests/lock-spring-boot-test/local-lock-spring-boot-test/src/test/java/com/livk/local/lock/ShopControllerTest.java index b475ecb1e..4bc466524 100644 --- a/spring-boot-extension-tests/lock-spring-boot-test/local-lock-spring-boot-test/src/test/java/com/livk/local/lock/ShopControllerTest.java +++ b/spring-boot-extension-tests/lock-spring-boot-test/local-lock-spring-boot-test/src/test/java/com/livk/local/lock/ShopControllerTest.java @@ -50,21 +50,22 @@ class ShopControllerTest { @Order(1) @Test void testBuyLocal() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(500); - CountDownLatch countDownLatch = new CountDownLatch(500); - for (int i = 0; i < 500; i++) { - service.submit(() -> { - try { - mockMvc.perform(post("/shop/buy/local")).andExpect(status().isOk()); - countDownLatch.countDown(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - }); + try (ExecutorService service = Executors.newFixedThreadPool(500, Thread.ofVirtual().factory())) { + CountDownLatch countDownLatch = new CountDownLatch(500); + for (int i = 0; i < 500; i++) { + service.submit(() -> { + try { + mockMvc.perform(post("/shop/buy/local")).andExpect(status().isOk()); + countDownLatch.countDown(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + countDownLatch.await(); + service.shutdown(); } - countDownLatch.await(); - service.shutdown(); } @Order(2) diff --git a/spring-boot-extension-tests/lock-spring-boot-test/redisson-lock-spring-boot-test/src/test/java/com/livk/redisson/lock/ShopControllerTest.java b/spring-boot-extension-tests/lock-spring-boot-test/redisson-lock-spring-boot-test/src/test/java/com/livk/redisson/lock/ShopControllerTest.java index 9ae8f1fbf..ddc96c6bd 100644 --- a/spring-boot-extension-tests/lock-spring-boot-test/redisson-lock-spring-boot-test/src/test/java/com/livk/redisson/lock/ShopControllerTest.java +++ b/spring-boot-extension-tests/lock-spring-boot-test/redisson-lock-spring-boot-test/src/test/java/com/livk/redisson/lock/ShopControllerTest.java @@ -50,21 +50,22 @@ class ShopControllerTest { @Order(1) @Test void testBuyLocal() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(10); - CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - service.submit(() -> { - try { - mockMvc.perform(post("/shop/buy/distributed")).andExpect(status().isOk()); - countDownLatch.countDown(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - }); + try (ExecutorService service = Executors.newFixedThreadPool(10, Thread.ofVirtual().factory())) { + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + service.submit(() -> { + try { + mockMvc.perform(post("/shop/buy/distributed")).andExpect(status().isOk()); + countDownLatch.countDown(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + countDownLatch.await(); + service.shutdown(); } - countDownLatch.await(); - service.shutdown(); } @Order(2) diff --git a/spring-boot-extension-tests/oss-spring-boot-test/oss-aliyun-spring-boot-test/src/test/java/com/livk/oss/aliyun/controller/OssControllerTest.java b/spring-boot-extension-tests/oss-spring-boot-test/oss-aliyun-spring-boot-test/src/test/java/com/livk/oss/aliyun/controller/OssControllerTest.java index 11367c49f..0563615ad 100644 --- a/spring-boot-extension-tests/oss-spring-boot-test/oss-aliyun-spring-boot-test/src/test/java/com/livk/oss/aliyun/controller/OssControllerTest.java +++ b/spring-boot-extension-tests/oss-spring-boot-test/oss-aliyun-spring-boot-test/src/test/java/com/livk/oss/aliyun/controller/OssControllerTest.java @@ -27,7 +27,7 @@ import java.io.File; import java.io.InputStream; -import java.net.URL; +import java.net.URI; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -53,7 +53,7 @@ void test() throws Exception { .andReturn() .getResponse() .getContentAsString(); - try (InputStream stream = new URL(url).openStream()) { + try (InputStream stream = new URI(url).toURL().openStream()) { FileUtils.download(stream, "./test.jpg"); } File file = new File("./test.jpg"); diff --git a/spring-boot-extension-tests/oss-spring-boot-test/oss-minio-spring-boot-test/src/test/java/com/livk/oss/minio/controller/OssControllerTest.java b/spring-boot-extension-tests/oss-spring-boot-test/oss-minio-spring-boot-test/src/test/java/com/livk/oss/minio/controller/OssControllerTest.java index 0c9a35bb4..e14abc3c3 100644 --- a/spring-boot-extension-tests/oss-spring-boot-test/oss-minio-spring-boot-test/src/test/java/com/livk/oss/minio/controller/OssControllerTest.java +++ b/spring-boot-extension-tests/oss-spring-boot-test/oss-minio-spring-boot-test/src/test/java/com/livk/oss/minio/controller/OssControllerTest.java @@ -26,7 +26,7 @@ import java.io.File; import java.io.InputStream; -import java.net.URL; +import java.net.URI; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -51,7 +51,7 @@ void test() throws Exception { .andReturn() .getResponse() .getContentAsString(); - try (InputStream stream = new URL(url).openStream()) { + try (InputStream stream = new URI(url).toURL().openStream()) { FileUtils.download(stream, "./test.jpg"); } File file = new File("./test.jpg"); diff --git a/spring-extension-commons/src/main/java/com/livk/commons/aop/AnnotationAbstractPointcutAdvisor.java b/spring-extension-commons/src/main/java/com/livk/commons/aop/AnnotationAbstractPointcutAdvisor.java index 568982642..3f6be10fc 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/aop/AnnotationAbstractPointcutAdvisor.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/aop/AnnotationAbstractPointcutAdvisor.java @@ -59,7 +59,7 @@ public Object invoke(@NonNull MethodInvocation invocation) throws Throwable { * 执行拦截的方法 * @param invocation 方法相关信息 * @param annotation 注解信息 - * @return 方法返回结果 + * @return 方法返回结果 object * @throws Throwable the throwable */ protected abstract Object invoke(MethodInvocation invocation, A annotation) throws Throwable; diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/RestClientConfiguration.java b/spring-extension-commons/src/main/java/com/livk/commons/http/RestClientConfiguration.java new file mode 100644 index 000000000..01e5eb135 --- /dev/null +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/RestClientConfiguration.java @@ -0,0 +1,94 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.commons.http; + +import com.livk.auto.service.annotation.SpringAutoService; +import com.livk.commons.http.annotation.EnableRestTemplate; +import com.livk.commons.http.support.OkHttpClientHttpRequestFactory; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.web.client.RestClientCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestClient; + +import java.util.concurrent.TimeUnit; + +/** + *

+ * RestClientConfiguration + *

+ * + * @author livk + */ +@AutoConfiguration +@SpringAutoService(EnableRestTemplate.class) +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) +public class RestClientConfiguration { + + /** + * Rest client + * @param builder builder + * @return client + */ + @Bean + public RestClient restClient(RestClient.Builder builder) { + return builder.build(); + } + + /** + * The type Ok http client configuration. + */ + @Configuration(enforceUniqueMethods = false) + @ConditionalOnClass(OkHttpClient.class) + public static class OkHttpClientConfiguration { + + /** + * Rest template customizer rest template customizer. + * @return the rest template customizer + */ + @Bean + @ConditionalOnMissingBean(OkHttpClient.class) + public RestClientCustomizer restClientCustomizer() { + ConnectionPool pool = new ConnectionPool(200, 300, TimeUnit.SECONDS); + OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory().connectionPool(pool) + .connectTimeout(3, TimeUnit.SECONDS) + .readTimeout(3, TimeUnit.SECONDS) + .writeTimeout(3, TimeUnit.SECONDS); + return builder -> builder.requestFactory(requestFactory); + } + + /** + * Rest template customizer rest template customizer. + * @param okHttpClient the ok http client + * @return the rest template customizer + */ + @Bean + @ConditionalOnBean(OkHttpClient.class) + public RestClientCustomizer restClientCustomizer(OkHttpClient okHttpClient) { + return builder -> builder.requestFactory(new OkHttpClientHttpRequestFactory(okHttpClient)); + } + + } + +} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/RestTemplateConfiguration.java b/spring-extension-commons/src/main/java/com/livk/commons/http/RestTemplateConfiguration.java index e1658a874..f2f93c12b 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/http/RestTemplateConfiguration.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/RestTemplateConfiguration.java @@ -19,6 +19,7 @@ import com.livk.auto.service.annotation.SpringAutoService; import com.livk.commons.http.annotation.EnableRestTemplate; +import com.livk.commons.http.support.OkHttpClientHttpRequestFactory; import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -26,23 +27,18 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import java.util.concurrent.TimeUnit; /** *

- * RestTemplate相关配置 + * HttpConfiguration *

- * 仅在SERVLET环境下生效 - *

- * REACTIVE环境下请使用{@link org.springframework.web.reactive.function.client.WebClient} * * @author livk */ @@ -52,7 +48,7 @@ public class RestTemplateConfiguration { /** - * 注入RestTemplate + * Rest template rest template. * @param builder the builder * @return the rest template */ @@ -62,38 +58,36 @@ public RestTemplate restTemplate(RestTemplateBuilder builder) { } /** - * okhttp配置相关 + * The type Ok http client configuration. */ @Configuration(enforceUniqueMethods = false) @ConditionalOnClass(OkHttpClient.class) public static class OkHttpClientConfiguration { /** - * 自定义okhttp相关配置 + * Rest template customizer rest template customizer. * @return the rest template customizer */ @Bean @ConditionalOnMissingBean(OkHttpClient.class) public RestTemplateCustomizer restTemplateCustomizer() { ConnectionPool pool = new ConnectionPool(200, 300, TimeUnit.SECONDS); - OkHttpClient.Builder builder = new OkHttpClient().newBuilder() + OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory().connectionPool(pool) .connectTimeout(3, TimeUnit.SECONDS) .readTimeout(3, TimeUnit.SECONDS) .writeTimeout(3, TimeUnit.SECONDS); - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(pool).to(builder::setConnectionPool$okhttp); - return restTemplate -> restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory(builder.build())); + return restTemplate -> restTemplate.setRequestFactory(requestFactory); } /** - * 从Spring IOC获取okhttp相关配置装配 + * Rest template customizer rest template customizer. * @param okHttpClient the ok http client * @return the rest template customizer */ @Bean @ConditionalOnBean(OkHttpClient.class) public RestTemplateCustomizer restTemplateCustomizer(OkHttpClient okHttpClient) { - return restTemplate -> restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory(okHttpClient)); + return restTemplate -> restTemplate.setRequestFactory(new OkHttpClientHttpRequestFactory(okHttpClient)); } } diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/WebClientConfiguration.java b/spring-extension-commons/src/main/java/com/livk/commons/http/WebClientConfiguration.java index 034ef3566..945cb1840 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/http/WebClientConfiguration.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/WebClientConfiguration.java @@ -30,8 +30,8 @@ import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; import org.springframework.boot.web.reactive.function.client.WebClientCustomizer; import org.springframework.context.annotation.Bean; +import org.springframework.http.client.ReactorResourceFactory; import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.http.client.reactive.ReactorResourceFactory; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; import reactor.netty.tcp.DefaultSslContextSpec; diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/EnableRestClient.java b/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/EnableRestClient.java new file mode 100644 index 000000000..fdfeef314 --- /dev/null +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/EnableRestClient.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.commons.http.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

+ * 用于生成配置文件 + *

+ * {@code @SpringAutoService(EnableRestClient.class)} + *

+ * {@link HttpClientType#REST_TEMPLATE} + * + * @author livk + * @see EnableHttpClient + * @see com.livk.commons.http.RestTemplateConfiguration + */ +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@EnableHttpClient(HttpClientType.REST_CLIENT) +public @interface EnableRestClient { + +} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/HttpClientType.java b/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/HttpClientType.java index 64c9e653c..0a1aaa5a3 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/HttpClientType.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/annotation/HttpClientType.java @@ -36,7 +36,12 @@ public enum HttpClientType { /** * WebClient */ - WEB_CLIENT(EnableWebClient.class); + WEB_CLIENT(EnableWebClient.class), + + /** + * Rest client http client type. + */ + REST_CLIENT(EnableRestClient.class); private final Class annotationType; diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpRequest.java b/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpRequest.java new file mode 100644 index 000000000..d18684818 --- /dev/null +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpRequest.java @@ -0,0 +1,150 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.commons.http.support; + +import lombok.RequiredArgsConstructor; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okio.BufferedSink; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.StreamingHttpOutputMessage; +import org.springframework.http.client.*; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.FastByteArrayOutputStream; +import org.springframework.util.StringUtils; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; + +/** + * The type Ok http client http request. + * + * @author livk + */ +@RequiredArgsConstructor +class OkHttpClientHttpRequest extends AbstractClientHttpRequest implements StreamingHttpOutputMessage { + + private final OkHttpClient client; + + private final URI uri; + + private final HttpMethod method; + + private Body body; + + private FastByteArrayOutputStream bodyStream; + + @NonNull + @Override + public HttpMethod getMethod() { + return this.method; + } + + @NonNull + @Override + public URI getURI() { + return this.uri; + } + + @Override + public void setBody(@NonNull Body body) { + assertNotExecuted(); + this.body = body; + } + + @NonNull + @Override + protected OutputStream getBodyInternal(@NonNull HttpHeaders headers) { + if (this.bodyStream == null) { + this.bodyStream = new FastByteArrayOutputStream(1024); + } + return this.bodyStream; + } + + @NonNull + @Override + protected ClientHttpResponse executeInternal(@NonNull HttpHeaders headers) throws IOException { + if (this.body == null && this.bodyStream != null) { + this.body = outputStream -> this.bodyStream.writeTo(outputStream); + } + RequestBody requestBody; + if (body != null) { + requestBody = new BodyRequestBody(headers, body); + } + else if (okhttp3.internal.http.HttpMethod.requiresRequestBody(getMethod().name())) { + String header = headers.getFirst(HttpHeaders.CONTENT_TYPE); + MediaType contentType = (header != null) ? MediaType.parse(header) : null; + requestBody = RequestBody.create(new byte[0], contentType); + } + else { + requestBody = null; + } + Request.Builder builder = new Request.Builder().url(this.uri.toURL()); + builder.method(this.method.name(), requestBody); + headers.forEach((headerName, headerValues) -> { + for (String headerValue : headerValues) { + builder.addHeader(headerName, headerValue); + } + }); + Request request = builder.build(); + return new OkHttpClientHttpResponse(this.client.newCall(request).execute()); + } + + @RequiredArgsConstructor + + private static class BodyRequestBody extends RequestBody { + + private final HttpHeaders headers; + + private final Body body; + + @Override + public long contentLength() { + return this.headers.getContentLength(); + } + + @Nullable + @Override + public MediaType contentType() { + String contentType = this.headers.getFirst(HttpHeaders.CONTENT_TYPE); + if (StringUtils.hasText(contentType)) { + return MediaType.parse(contentType); + } + else { + return null; + } + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + this.body.writeTo(sink.outputStream()); + } + + @Override + public boolean isOneShot() { + return true; + } + + } + +} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpRequestFactory.java b/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpRequestFactory.java new file mode 100644 index 000000000..4e4757afc --- /dev/null +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpRequestFactory.java @@ -0,0 +1,167 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.commons.http.support; + +import okhttp3.Cache; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.net.URI; +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +/** + * The type Ok http client http request factory. + * + * @author livk + */ +public class OkHttpClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean { + + private OkHttpClient client; + + private final boolean defaultClient; + + /** + * Create a factory with a default {@link OkHttpClient} instance. + */ + public OkHttpClientHttpRequestFactory() { + this.client = new OkHttpClient(); + this.defaultClient = true; + } + + /** + * Create a factory with the given {@link OkHttpClient} instance. + * @param client the client to use + */ + public OkHttpClientHttpRequestFactory(OkHttpClient client) { + Assert.notNull(client, "OkHttpClient must not be null"); + this.client = client; + this.defaultClient = false; + } + + /** + * Set the underlying read timeout in milliseconds. A value of 0 specifies an infinite + * timeout. + * @param readTimeout the read timeout + * @param unit the unit + * @return the ok http client http request factory + */ + public OkHttpClientHttpRequestFactory readTimeout(long readTimeout, TimeUnit unit) { + this.client = this.client.newBuilder().readTimeout(readTimeout, unit).build(); + return this; + } + + /** + * Set the underlying read timeout in milliseconds. A value of 0 specifies an infinite + * timeout. + * @param readTimeout the read timeout + * @return the ok http client http request factory + * @since 6.1 + */ + public OkHttpClientHttpRequestFactory readTimeout(Duration readTimeout) { + this.client = this.client.newBuilder().readTimeout(readTimeout).build(); + return this; + } + + /** + * Set the underlying write timeout in milliseconds. A value of 0 specifies an + * infinite timeout. + * @param writeTimeout the write timeout + * @param unit the unit + * @return the ok http client http request factory + */ + public OkHttpClientHttpRequestFactory writeTimeout(long writeTimeout, TimeUnit unit) { + this.client = this.client.newBuilder().writeTimeout(writeTimeout, unit).build(); + return this; + } + + /** + * Set the underlying write timeout in milliseconds. A value of 0 specifies an + * infinite timeout. + * @param writeTimeout the write timeout + * @return the ok http client http request factory + * @since 6.1 + */ + public OkHttpClientHttpRequestFactory writeTimeout(Duration writeTimeout) { + this.client = this.client.newBuilder().writeTimeout(writeTimeout).build(); + return this; + } + + /** + * Set the underlying connect timeout in milliseconds. A value of 0 specifies an + * infinite timeout. + * @param connectTimeout the connect timeout + * @param unit the unit + * @return the ok http client http request factory + */ + public OkHttpClientHttpRequestFactory connectTimeout(long connectTimeout, TimeUnit unit) { + this.client = this.client.newBuilder().connectTimeout(connectTimeout, unit).build(); + return this; + } + + /** + * Set the underlying connect timeout in milliseconds. A value of 0 specifies an + * infinite timeout. + * @param connectTimeout the connect timeout + * @return the ok http client http request factory + * @since 6.1 + */ + public OkHttpClientHttpRequestFactory connectTimeout(Duration connectTimeout) { + this.client = this.client.newBuilder().connectTimeout(connectTimeout).build(); + return this; + } + + /** + * Connection pool ok http client http request factory. + * @param connectionPool the connection pool + * @return the ok http client http request factory + */ + public OkHttpClientHttpRequestFactory connectionPool(ConnectionPool connectionPool) { + OkHttpClient.Builder builder = this.client.newBuilder(); + builder.setConnectionPool$okhttp(connectionPool); + this.client = builder.build(); + return this; + } + + @NonNull + @Override + public ClientHttpRequest createRequest(@NonNull URI uri, @NonNull HttpMethod httpMethod) { + return new OkHttpClientHttpRequest(this.client, uri, httpMethod); + } + + @Override + public void destroy() throws IOException { + if (this.defaultClient) { + // Clean up the client if we created it in the constructor + Cache cache = this.client.cache(); + if (cache != null) { + cache.close(); + } + this.client.dispatcher().executorService().close(); + this.client.connectionPool().evictAll(); + } + } + +} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpResponse.java b/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpResponse.java new file mode 100644 index 000000000..b6e31a6b6 --- /dev/null +++ b/spring-extension-commons/src/main/java/com/livk/commons/http/support/OkHttpClientHttpResponse.java @@ -0,0 +1,96 @@ +/* + * Copyright 2021 spring-boot-extension 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.livk.commons.http.support; + +import okhttp3.Response; +import okhttp3.ResponseBody; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.io.InputStream; + +/** + * The type Ok http client http response. + * + * @author livk + */ +class OkHttpClientHttpResponse implements ClientHttpResponse { + + private final Response response; + + @Nullable + private volatile HttpHeaders headers; + + /** + * Instantiates a new Ok http client http response. + * @param response the response + */ + public OkHttpClientHttpResponse(Response response) { + Assert.notNull(response, "Response must not be null"); + this.response = response; + } + + @NonNull + @Override + public HttpStatusCode getStatusCode() { + return HttpStatusCode.valueOf(this.response.code()); + } + + @NonNull + @Override + public String getStatusText() { + return this.response.message(); + } + + @NonNull + @Override + public InputStream getBody() { + ResponseBody body = this.response.body(); + return (body != null ? body.byteStream() : InputStream.nullInputStream()); + } + + @NonNull + @Override + public HttpHeaders getHeaders() { + HttpHeaders headers = this.headers; + if (headers == null) { + headers = new HttpHeaders(); + for (String headerName : this.response.headers().names()) { + for (String headerValue : this.response.headers(headerName)) { + headers.add(headerName, headerValue); + } + } + this.headers = headers; + } + return headers; + } + + @Override + public void close() { + ResponseBody body = this.response.body(); + if (body != null) { + body.close(); + } + } + +} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/jackson/JacksonWrapper.java b/spring-extension-commons/src/main/java/com/livk/commons/jackson/JacksonWrapper.java deleted file mode 100644 index cac39f41f..000000000 --- a/spring-extension-commons/src/main/java/com/livk/commons/jackson/JacksonWrapper.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2021 spring-boot-extension 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.livk.commons.jackson; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; -import com.livk.commons.beans.GenericWrapper; -import com.livk.commons.spring.context.SpringContextHolder; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; - -/** - * The type Jackson wrapper. - * - * @author livk - */ -@Slf4j -@Deprecated(forRemoval = true) -@RequiredArgsConstructor -public class JacksonWrapper implements GenericWrapper { - - /** - * The constant BEAN_NAME. - */ - public static final String BEAN_NAME = "com.livk.commons.jackson.JacksonWrapper"; - - private final ObjectMapper mapper; - - /** - * Unwrap of context object mapper. - * @return the object mapper - */ - public static ObjectMapper unwrapOfContext() { - GenericWrapper wrapper = null; - try { - if (SpringContextHolder.getApplicationContext().containsBean(JacksonWrapper.BEAN_NAME)) { - wrapper = SpringContextHolder.getBean(JacksonWrapper.BEAN_NAME, JacksonWrapper.class); - } - else { - throw new NoSuchBeanDefinitionException(JacksonWrapper.BEAN_NAME); - } - } - catch (Exception e) { - log.debug("Building 'ObjectMapper'"); - } - return wrapper == null ? JsonMapper.builder().build() : wrapper.unwrap(); - } - - @Override - public ObjectMapper unwrap() { - return mapper; - } - -} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/jackson/util/JacksonUtils.java b/spring-extension-commons/src/main/java/com/livk/commons/jackson/util/JacksonUtils.java deleted file mode 100644 index 1f97210dd..000000000 --- a/spring-extension-commons/src/main/java/com/livk/commons/jackson/util/JacksonUtils.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2021 spring-boot-extension 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.livk.commons.jackson.util; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.type.CollectionType; -import com.fasterxml.jackson.databind.type.MapType; -import com.fasterxml.jackson.databind.type.TypeFactory; -import com.livk.commons.jackson.core.JacksonSupport; -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.ResolvableType; - -import java.util.List; -import java.util.Map; - -/** - * Jackson一些基本序列化与反序列化 - *

- * 自定义Mapper,请注册{@link com.livk.commons.beans.Wrapper}到IOC - *

- * 请使用{@link JsonMapperUtils} - * - * @author livk - * @see JacksonSupport - * @see TypeFactoryUtils - * @deprecated 当前类设计存在语义不清 - */ -@Slf4j -@UtilityClass -@Deprecated(forRemoval = true) -public class JacksonUtils { - - /** - * 获取当前MAPPER的TypeFactory - * @return the type factory - */ - public static TypeFactory typeFactory() { - return TypeFactoryUtils.instance(); - } - - /** - * 构建一个JavaType - * @param targetClass the target class - * @return the java type - */ - public static JavaType javaType(Class targetClass) { - return TypeFactoryUtils.javaType(targetClass); - } - - /** - * 构建一个含有泛型的JavaType - * @param targetClass the target class - * @param generics the generics - * @return the java type - */ - public static JavaType javaType(Class targetClass, Class... generics) { - return TypeFactoryUtils.javaType(targetClass, generics); - } - - /** - * ResolvableType转成Jackson JavaType - * @param resolvableType the resolvable type - * @return the java type - * @see ResolvableType - */ - public static JavaType javaType(ResolvableType resolvableType) { - return TypeFactoryUtils.javaType(resolvableType); - } - - /** - * 构建一个CollectionType - * @param the type parameter - * @param targetClass the target class - * @return the java type - * @see CollectionType - */ - public static CollectionType collectionType(Class targetClass) { - return TypeFactoryUtils.collectionType(targetClass); - } - - /** - * 构建一个MapType - * @param the type parameter - * @param the type parameter - * @param keyClass the key class - * @param valueClass the value class - * @return the java type - * @see MapType - */ - public static MapType mapType(Class keyClass, Class valueClass) { - return TypeFactoryUtils.mapType(keyClass, valueClass); - } - - /** - * Read value t. - * @param the type parameter - * @param obj the obj - * @param type the type - * @return the t - */ - - public static T readValue(Object obj, Class type) { - return JsonMapperUtils.readValue(obj, javaType(type)); - } - - /** - * Read value t. - * @param the type parameter - * @param obj the obj - * @param type the type - * @return the t - */ - - public T readValue(Object obj, JavaType type) { - return JsonMapperUtils.readValue(obj, type); - } - - /** - * Read value t. - * @param the type parameter - * @param obj the obj - * @param typeReference the type reference - * @return the t - */ - - public static T readValue(Object obj, TypeReference typeReference) { - return JsonMapperUtils.readValue(obj, typeReference); - } - - /** - * json序列化 - * @param obj obj - * @return json string - */ - - public static String writeValueAsString(Object obj) { - return JsonMapperUtils.writeValueAsString(obj); - } - - /** - * Write value as bytes byte [ ]. - * @param obj the obj - * @return the byte [ ] - */ - - public static byte[] writeValueAsBytes(Object obj) { - return JsonMapperUtils.writeValueAsBytes(obj); - } - - /** - * json反序列化成List - *

- * 也可以看看{@link JacksonUtils#readValue(Object, TypeReference)} , - *

- * {@link JacksonUtils#convertValue(Object, JavaType)} - * @param 泛型 - * @param obj the obj - * @param clazz 类型 - * @return the list - */ - - public static List readValueList(Object obj, Class clazz) { - return JsonMapperUtils.readValueList(obj, clazz); - } - - /** - * json反序列化成Map - *

- * 也可以看看{@link JacksonUtils#readValue(Object, TypeReference)} , - *

- * {@link JacksonUtils#convertValue(Object, JavaType)} - * @param the type parameter - * @param the type parameter - * @param obj the obj - * @param keyClass K Class - * @param valueClass V Class - * @return the map - */ - - public static Map readValueMap(Object obj, Class keyClass, Class valueClass) { - return JsonMapperUtils.readValueMap(obj, keyClass, valueClass); - } - - /** - * 将json转化成JsonNode - * @param obj the obj - * @return the json node - */ - - public JsonNode readTree(Object obj) { - return JsonMapperUtils.readTree(obj); - } - - /** - * Convert object. - * @param the type parameter - * @param fromValue the value - * @param type the type - * @return the object - */ - public static T convertValue(Object fromValue, Class type) { - return JsonMapperUtils.convertValue(fromValue, type); - } - - /** - * Convert value t. - * @param the type parameter - * @param fromValue the value - * @param typeReference the type reference - * @return the t - */ - public static T convertValue(Object fromValue, TypeReference typeReference) { - return JsonMapperUtils.convertValue(fromValue, typeReference); - } - - /** - * Convert object. - * @param the type parameter - * @param fromValue the value - * @param javaType the java type - * @return the object - */ - public static T convertValue(Object fromValue, JavaType javaType) { - return JsonMapperUtils.convertValue(fromValue, javaType); - } - - /** - * Object to map map. - * @param the type parameter - * @param the type parameter - * @param fromValue the fromValue - * @param keyClass the key class - * @param valueClass the value class - * @return the map - */ - public static Map convertValueMap(Object fromValue, Class keyClass, Class valueClass) { - return JsonMapperUtils.convertValueMap(fromValue, keyClass, valueClass); - } - -} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/spring/context/SpringAbstractImportSelector.java b/spring-extension-commons/src/main/java/com/livk/commons/spring/context/SpringAbstractImportSelector.java index faef9e3e2..a4a9b90c4 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/spring/context/SpringAbstractImportSelector.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/spring/context/SpringAbstractImportSelector.java @@ -41,6 +41,7 @@ *

* 功效大致与 {@link AutoConfigurationImportSelector}一样,缺失排除自动装配的能力 * + * @param 注解类型 * @author livk * @see AutoConfigurationImportSelector * @see org.springframework.boot.autoconfigure.EnableAutoConfiguration @@ -51,9 +52,16 @@ public abstract class SpringAbstractImportSelector extends /** * The Annotation class. */ + protected final Class annotationClass; + + /** + * 构建生菜annotationClass + */ @SuppressWarnings("unchecked") - protected final Class annotationClass = (Class) GenericTypeResolver.resolveTypeArgument(this.getClass(), - SpringAbstractImportSelector.class); + protected SpringAbstractImportSelector() { + this.annotationClass = (Class) GenericTypeResolver.resolveTypeArgument(this.getClass(), + SpringAbstractImportSelector.class); + } @Override protected Class getAnnotationClass() { diff --git a/spring-extension-commons/src/main/java/com/livk/commons/spring/util/SpringUtils.java b/spring-extension-commons/src/main/java/com/livk/commons/spring/util/SpringUtils.java deleted file mode 100644 index faa3c09e1..000000000 --- a/spring-extension-commons/src/main/java/com/livk/commons/spring/util/SpringUtils.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2021 spring-boot-extension 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.livk.commons.spring.util; - -import com.livk.commons.expression.spring.SpringExpressionResolver; -import com.livk.commons.spring.context.AnnotationMetadataResolver; -import com.livk.commons.spring.env.SpringEnvBinder; -import lombok.experimental.UtilityClass; -import org.springframework.boot.context.properties.bind.BindResult; -import org.springframework.boot.context.properties.bind.Bindable; -import org.springframework.core.env.Environment; -import org.springframework.core.io.ResourceLoader; -import org.springframework.util.Assert; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -/** - *

- * SpringUtils - *

- * - * @author livk - */ -@Deprecated(forRemoval = true) -@UtilityClass -public class SpringUtils { - - private static final SpringExpressionResolver RESOLVER = new SpringExpressionResolver(); - - /** - * 获取被注解标注的class - * @param annotationType annotation - * @param resourceLoader resourceLoader - * @param packages 待扫描的包 - * @return set class - */ - public Set> findByAnnotationType(Class annotationType, ResourceLoader resourceLoader, - String... packages) { - Assert.notNull(annotationType, "annotation not null"); - return new AnnotationMetadataResolver(resourceLoader).find(annotationType, packages); - } - - /** - * {example env= "spring.data.redisson.host=127.0.0.1" keyPrefix="spring.data" - * result=Map.of("redisson.host","127.0.0.1")} - * @param environment env - * @param keyPrefix prefix - * @return map sub properties - */ - public Map getSubPropertiesMap(Environment environment, String keyPrefix) { - return new SpringEnvBinder(environment).mapOf(keyPrefix, String.class, String.class) - .orElseGet(Collections::emptyMap); - } - - /** - * Gets sub properties. - * @param environment the environment - * @param keyPrefix the key prefix - * @return the sub properties - */ - public Properties getSubProperties(Environment environment, String keyPrefix) { - return new SpringEnvBinder(environment).propertiesOf(keyPrefix).orElseGet(Properties::new); - } - - /** - * Bind bind result. - * @param the type parameter - * @param environment the environment - * @param keyPrefix the key prefix - * @param bindable the bindable - * @return the bind result - */ - public BindResult bind(Environment environment, String keyPrefix, Bindable bindable) { - return new SpringEnvBinder(environment).bind(keyPrefix, bindable); - } - - /** - * 解析SpEL表达式 非模板表达式: #username 模板表达式:"livk:#{#username}" - * @param 类型 - * @param method 方法 - * @param args 方法参数 - * @param condition 表达式 - * @param returnClass 返回类型 - * @param expandMap 拓展数据 - * @return T - */ - public T parseSpEL(Method method, Object[] args, String condition, Class returnClass, - Map expandMap) { - return RESOLVER.evaluate(condition, method, args, expandMap, returnClass); - } - - /** - * 解析SpEL表达式 - * @param 类型 - * @param method 方法 - * @param args 方法参数 - * @param condition 表达式 - * @param returnClass 返回类型 - * @return T - */ - public T parseSpEL(Method method, Object[] args, String condition, Class returnClass) { - return parseSpEL(method, args, condition, returnClass, Map.of()); - } - - /** - * 解析SpEL表达式 - * @param 类型 - * @param variables 需要填充的数据 - * @param condition 表达式 - * @param returnClass 返回类型 - * @return T - */ - public T parseSpEL(Map variables, String condition, Class returnClass) { - return parseSpEL(null, null, condition, returnClass, variables); - } - - /** - * 解析SpEL表达式 非模板表达式: #username 模板表达式:"livk:#{#username}" - * @param method 方法 - * @param args 方法参数 - * @param condition 表达式 - * @return string string - */ - public String parseSpEL(Method method, Object[] args, String condition) { - return parseSpEL(method, args, condition, String.class); - } - - /** - * 解析SpEL表达式 - * @param variables 需要填充的数据 - * @param condition 表达式 - * @return string string - */ - public String parseSpEL(Map variables, String condition) { - return parseSpEL(variables, condition, String.class); - } - - /** - * 解析SpEL表达式 - * @param method 方法 - * @param args 方法参数 - * @param condition 表达式 - * @param expandMap 需要填充的数据 - * @return the string - */ - public String parseSpEL(Method method, Object[] args, String condition, Map expandMap) { - return parseSpEL(method, args, condition, String.class, expandMap); - } - -} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/util/BaseStreamUtils.java b/spring-extension-commons/src/main/java/com/livk/commons/util/BaseStreamUtils.java index 1ee1612a8..6a4280f20 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/util/BaseStreamUtils.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/util/BaseStreamUtils.java @@ -17,7 +17,6 @@ package com.livk.commons.util; -import com.google.common.collect.Streams; import lombok.experimental.UtilityClass; import java.util.*; @@ -152,22 +151,6 @@ public Predicate distinct(Function function) { return t -> seen.putIfAbsent(function.apply(t), Boolean.TRUE) == null; } - /** - * Convert stream. - *

- * Deprecated - *

- * use {@link com.google.common.collect.Streams#stream(java.util.Iterator)} - * @param the type parameter - * @param iterator the iterator - * @return the stream - * @see com.google.common.collect.Streams#stream(java.util.Iterator) - */ - @Deprecated(forRemoval = true) - public Stream convert(Iterator iterator) { - return Streams.stream(iterator); - } - /** * Enumeration转化成Stream * @param type parameter diff --git a/spring-extension-commons/src/main/java/com/livk/commons/util/ObjectUtils.java b/spring-extension-commons/src/main/java/com/livk/commons/util/ObjectUtils.java index cbec42f2d..f0763e86f 100644 --- a/spring-extension-commons/src/main/java/com/livk/commons/util/ObjectUtils.java +++ b/spring-extension-commons/src/main/java/com/livk/commons/util/ObjectUtils.java @@ -19,9 +19,6 @@ import lombok.experimental.UtilityClass; -import java.util.function.Predicate; -import java.util.stream.Stream; - /** *

* 常用Object相关工具类 @@ -32,32 +29,4 @@ @UtilityClass public class ObjectUtils extends org.springframework.util.ObjectUtils { - /** - * All checked boolean. - * @param the type parameter - * @param predicate the predicate - * @param ts the ts - * @return the boolean - * @see Predicates - */ - @Deprecated(since = "1.1.4", forRemoval = true) - @SafeVarargs - public boolean allChecked(Predicate predicate, T... ts) { - return !ObjectUtils.isEmpty(ts) && Stream.of(ts).allMatch(predicate); - } - - /** - * Any checked boolean. - * @param the type parameter - * @param predicate the predicate - * @param ts the ts - * @return the boolean - * @see Predicates - */ - @Deprecated(since = "1.1.4", forRemoval = true) - @SafeVarargs - public boolean anyChecked(Predicate predicate, T... ts) { - return !ObjectUtils.isEmpty(ts) && Stream.of(ts).anyMatch(predicate); - } - } diff --git a/spring-extension-commons/src/main/java/com/livk/commons/util/PathPatternUtils.java b/spring-extension-commons/src/main/java/com/livk/commons/util/PathPatternUtils.java deleted file mode 100644 index 289428e7d..000000000 --- a/spring-extension-commons/src/main/java/com/livk/commons/util/PathPatternUtils.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2021 spring-boot-extension 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.livk.commons.util; - -import lombok.experimental.UtilityClass; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.http.server.RequestPath; -import org.springframework.web.util.pattern.PathPattern; -import org.springframework.web.util.pattern.PathPatternParser; - -import java.net.URI; - -/** - * The type Path pattern utils. - *

- * 基本上没有使用 - * - * @author livk - */ -@UtilityClass -@Deprecated(since = "1.1.6", forRemoval = true) -public class PathPatternUtils { - - /** - * Matches boolean. - * @param pathPattern the path pattern - * @param uri the uri - * @param contextPath the context path - * @return the boolean - */ - public boolean matches(String pathPattern, String uri, String contextPath) { - PathPattern pattern = PathPatternParser.defaultInstance.parse(pathPattern); - return pattern.matches(RequestPath.parse(URI.create(uri), contextPath)); - } - - /** - * Matches boolean. - * @param pathPattern the path pattern - * @param uri the uri - * @return the boolean - */ - public boolean matches(String pathPattern, String uri) { - return matches(pathPattern, uri, ""); - } - - /** - * Matches boolean. - * @param pathPattern the path pattern - * @param uri the uri - * @param properties the properties - * @return the boolean - */ - public boolean matches(String pathPattern, String uri, ServerProperties properties) { - String contextPath = properties.getServlet().getContextPath(); - return matches(pathPattern, uri, contextPath); - } - -} diff --git a/spring-extension-commons/src/main/java/com/livk/commons/util/Predicates.java b/spring-extension-commons/src/main/java/com/livk/commons/util/Predicates.java deleted file mode 100644 index 8c5dace8c..000000000 --- a/spring-extension-commons/src/main/java/com/livk/commons/util/Predicates.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2021 spring-boot-extension 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.livk.commons.util; - -import lombok.RequiredArgsConstructor; -import org.springframework.util.Assert; - -import java.util.Arrays; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Stream; - -/** - * The type Predicates. - * - * @param the type parameter - * @author livk - */ -@Deprecated(since = "1.1.6", forRemoval = true) -@RequiredArgsConstructor(staticName = "create") -public class Predicates { - - private final Stream dataStream; - - /** - * Create predicates. - * @param the type parameter - * @param dataArray the data array - * @return the predicates - */ - @SafeVarargs - public static Predicates create(T... dataArray) { - Assert.notEmpty(dataArray, "dataArray must not be null or empty"); - return new Predicates<>(Arrays.stream(dataArray)); - } - - /** - * Map predicates. - * @param the type parameter - * @param function the function - * @return the predicates - */ - public Predicates map(Function function) { - return new Predicates<>(dataStream.map(function)); - } - - /** - * All checked boolean. - * @param predicate the predicate - * @return the boolean - */ - public boolean allChecked(Predicate predicate) { - return dataStream.allMatch(predicate); - } - - /** - * Any checked boolean. - * @param predicate the predicate - * @return the boolean - */ - public boolean anyChecked(Predicate predicate) { - return dataStream.anyMatch(predicate); - } - - /** - * None match boolean. - * @param predicate the predicate - * @return the boolean - */ - public boolean noneMatch(Predicate predicate) { - return dataStream.noneMatch(predicate); - } - -} diff --git a/spring-extension-commons/src/test/java/com/livk/commons/util/SnowflakeTest.java b/spring-extension-commons/src/test/java/com/livk/commons/util/SnowflakeTest.java index 5c8862de4..fb35a8279 100644 --- a/spring-extension-commons/src/test/java/com/livk/commons/util/SnowflakeTest.java +++ b/spring-extension-commons/src/test/java/com/livk/commons/util/SnowflakeTest.java @@ -44,18 +44,19 @@ class SnowflakeTest { void nextId() throws InterruptedException { int num = 10000; List list = new CopyOnWriteArrayList<>(); - ExecutorService service = Executors.newFixedThreadPool(1000); - CountDownLatch countDownLatch = new CountDownLatch(num); - for (int i = 0; i < num; i++) { - service.submit(() -> { - list.add(SNOWFLAKE.nextId()); - countDownLatch.countDown(); - }); + try (ExecutorService service = Executors.newFixedThreadPool(1000, Thread.ofVirtual().factory())) { + CountDownLatch countDownLatch = new CountDownLatch(num); + for (int i = 0; i < num; i++) { + service.submit(() -> { + list.add(SNOWFLAKE.nextId()); + countDownLatch.countDown(); + }); + } + countDownLatch.await(); + service.shutdown(); + Set set = new HashSet<>(list); + assertEquals(set.size(), list.size()); } - countDownLatch.await(); - service.shutdown(); - Set set = new HashSet<>(list); - assertEquals(set.size(), list.size()); } } diff --git a/spring-extension-context/src/main/java/com/livk/core/disruptor/ClassPathDisruptorScanner.java b/spring-extension-context/src/main/java/com/livk/core/disruptor/ClassPathDisruptorScanner.java index 248046d60..3030d4771 100644 --- a/spring-extension-context/src/main/java/com/livk/core/disruptor/ClassPathDisruptorScanner.java +++ b/spring-extension-context/src/main/java/com/livk/core/disruptor/ClassPathDisruptorScanner.java @@ -20,6 +20,7 @@ import com.livk.commons.util.AnnotationUtils; import com.livk.core.disruptor.annotation.DisruptorEvent; import com.livk.core.disruptor.factory.DisruptorFactoryBean; +import com.livk.core.disruptor.support.SpringDisruptor; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; @@ -27,6 +28,7 @@ import org.springframework.beans.factory.support.*; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ScannedGenericBeanDefinition; +import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AnnotationTypeFilter; @@ -108,7 +110,9 @@ protected Set doScan(@NonNull String... basePackages) { String beanName = StringUtils.hasText(name) ? name : beanNameGenerator.generateBeanName(beanDefinition, registry); if (checkCandidate(beanName, beanDefinition)) { - beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, beanClassName); + ResolvableType resolvableType = ResolvableType.forClassWithGenerics(SpringDisruptor.class, + type); + beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, resolvableType); BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, beanName); definitionHolders.add(holder); diff --git a/spring-extension-dependencies/spring-extension-dependencies.gradle.kts b/spring-extension-dependencies/spring-extension-dependencies.gradle.kts index 2d4da978a..fcb0f171b 100644 --- a/spring-extension-dependencies/spring-extension-dependencies.gradle.kts +++ b/spring-extension-dependencies/spring-extension-dependencies.gradle.kts @@ -19,7 +19,6 @@ dependencies { api(libs.bundles.mapstruct.all) api(libs.guava) api(libs.easyexcel) - api(libs.spring.pulsar.starter) api(libs.spotbugs.annotations) api(libs.curator.recipes) api(libs.ip2region) @@ -31,7 +30,6 @@ dependencies { api(libs.lettucemod) api(libs.minio) api(libs.dnsjava) - api(libs.snakeyaml) api(libs.aliyun.oss) api(libs.aviator) api(libs.commons.jexl3)