diff --git a/.circleci/config.yml b/.circleci/config.yml index 3f260a24..3beeaa62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,7 +24,7 @@ jobs: - ~/.m2 - run: name: "Running build" - command: ./mvnw -Pdocs clean install -U -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dgpg.skip + command: ./mvnw clean install -U -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dgpg.skip - run: name: "Aggregate test results" when: always diff --git a/.gitignore b/.gitignore index 15395b04..e4b59732 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,11 @@ target .DS_Store .flattened-pom.xml +# temp ignore +*.cache +*.diff +*.patch +*.tmp + +# Maven ignore +.flattened-pom.xml diff --git a/.mvn/maven.config b/.mvn/maven.config index 3b8cf46e..e69de29b 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1 +0,0 @@ --DaltSnapshotDeploymentRepository=repo.spring.io::default::https://repo.spring.io/libs-snapshot-local -P spring diff --git a/README-zh.md b/README-zh.md index 5c314f70..e275e787 100644 --- a/README-zh.md +++ b/README-zh.md @@ -39,8 +39,6 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 **[Seata](https://github.com/seata/seata)**:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。 -**[Alibaba Cloud ACM](https://www.aliyun.com/product/acm)**:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。 - **[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。 **[Alibaba Cloud SchedulerX](https://help.aliyun.com/document_detail/43136.html)**: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。 @@ -72,7 +70,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone com.alibaba.cloud spring-cloud-alibaba-dependencies - 0.2.1.RELEASE + 2.2.4.RELEASE pom import @@ -81,19 +79,6 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone 然后在 `dependencies` 中添加自己所需使用的依赖即可使用。 -如果您想体验最新的 BUILD-SNAPSHOT 的新功能,则可以将版本换成最新的版本,但是需要在 pom.xml 中配置 Spring BUILDSNAPSHOT 仓库,**注意: SNAPSHOT 版本随时可能更新** - - - - spring-snapshot - Spring Snapshot Repository - https://repo.spring.io/snapshot - - true - - - - ## 演示 Demo 为了演示如何使用,Spring Cloud Alibaba 项目包含了一个子模块`spring-cloud-alibaba-examples`。此模块中提供了演示用的 example ,您可以阅读对应的 example 工程下的 readme 文档,根据里面的步骤来体验。 @@ -110,13 +95,11 @@ Example 列表: [Seata Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/seata-example/readme-zh.md) -[Alibaba Cloud OSS Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/oss-example/readme-zh.md) +[Alibaba Cloud OSS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample) -[Alibaba Cloud ANS Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/ans-example/ans-provider-example/readme-zh.md) +[Alibaba Cloud SMS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-sms-spring-boot-sample) -[Alibaba Cloud ACM Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/acm-example/acm-local-example/readme-zh.md) - -[Alibaba Cloud SchedulerX Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/schedulerx-example/schedulerx-simple-task-example/readme-zh.md) +[Alibaba Cloud SchedulerX Example](https://github.com/alibaba/aliyun-spring-boot) ## 版本管理规范 @@ -127,6 +110,7 @@ Example 列表: * 1.5.x 版本适用于 Spring Boot 1.5.x * 2.0.x 版本适用于 Spring Boot 2.0.x * 2.1.x 版本适用于 Spring Boot 2.1.x +* 2.2.x 版本适用于 Spring Boot 2.2.x ## 社区交流 @@ -137,7 +121,9 @@ spring-cloud-alibaba@googlegroups.com,欢迎通过此邮件列表讨论与 spr ### 钉钉群 -![DingQR](https://img.alicdn.com/tfs/TB1zrRie4v1gK0jSZFFXXb0sXXa-7862-3570.png) +![DingQR](https://img.alicdn.com/tfs/TB1jXikzAL0gK0jSZFtXXXQCXXa-1002-323.png) + +如图片有问题,访问 https://img.alicdn.com/tfs/TB1jXikzAL0gK0jSZFtXXXQCXXa-1002-323.png ## 社区相关开源 diff --git a/README.md b/README.md index 6f69e3dc..8a3073be 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ With Spring Cloud Alibaba, you only need to add some annotations and a small amo For more features, please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md). + ## Components **[Sentinel](https://github.com/alibaba/Sentinel)**: Sentinel takes "traffic flow" as the breakthrough point, and provides solutions in areas such as flow control, concurrency, circuit breaking, and load protection to protect service stability. @@ -45,7 +46,7 @@ For more features, please refer to [Roadmap](https://github.com/alibaba/spring-c **[Alibaba Cloud SMS](https://www.aliyun.com/product/sms)**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers. -**[Alibaba Cloud SchedulerX](https://www.aliyun.com/product/SchedulerX)**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds.. +**[Alibaba Cloud SchedulerX](https://www.aliyun.com/aliware/schedulerx?spm=5176.10695662.784137.1.4b07363dej23L3)**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds.. For more features please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md). @@ -71,7 +72,7 @@ These artifacts are available from Maven Central and Spring Release repository v com.alibaba.cloud spring-cloud-alibaba-dependencies - 2.1.0.RELEASE + 2.2.4.RELEASE pom import @@ -89,8 +90,6 @@ add the module in `dependencies`. [Nacos Discovery](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc) -[ACM](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc) - ## Examples @@ -106,9 +105,9 @@ Examples: [RocketMQ Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/rocketmq-example/readme.md) -[Alibaba Cloud OSS Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/oss-example/readme.md) +[Alibaba Cloud OSS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample) -[Duboo Spring Cloud Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/README_CN.md) +[Dubbo Spring Cloud Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/README_CN.md) ## Version control guidelines The version number of the project is in the form of x.x.x, where x is a number, starting from 0, and is not limited to the range 0~9. When the project is in the incubator phase, the version number is 0.x.x. @@ -118,6 +117,7 @@ As the interfaces and annotations of Spring Boot 1 and Spring Boot 2 have been c * 1.5.x for Spring Boot 1.5.x * 2.0.x for Spring Boot 2.0.x * 2.1.x for Spring Boot 2.1.x +* 2.2.x for Spring Boot 2.2.x ## Code of Conduct This project is a sub-project of Spring Cloud, it adheres to the Contributor Covenant [code of conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io. diff --git a/mvnw b/mvnw index 84073fa2..761189a9 100755 --- a/mvnw +++ b/mvnw @@ -249,5 +249,6 @@ fi exec "$JAVACMD" \ $MAVEN_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Drevision=${VERSION}" \ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@" \ No newline at end of file diff --git a/pom.xml b/pom.xml index a6a035d9..76a96e45 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ com.alibaba.cloud spring-cloud-alibaba-dependencies - ${revision} + ${project.version} pom import @@ -380,6 +380,31 @@ false + + org.codehaus.mojo + flatten-maven-plugin + ${flatten-maven-plugin.version} + + true + resolveCiFriendliesOnly + + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + @@ -393,69 +418,6 @@ - - - spring - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/release - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/libs-release-local - - false - - - - - release @@ -500,32 +462,6 @@ - - - org.codehaus.mojo - flatten-maven-plugin - ${flatten-maven-plugin.version} - - true - resolveCiFriendliesOnly - - - - flatten - process-resources - - flatten - - - - flatten.clean - clean - - clean - - - - @@ -542,9 +478,6 @@ - - - \ No newline at end of file diff --git a/spring-cloud-alibaba-coverage/pom.xml b/spring-cloud-alibaba-coverage/pom.xml index 5f6a520e..ae940cc2 100644 --- a/spring-cloud-alibaba-coverage/pom.xml +++ b/spring-cloud-alibaba-coverage/pom.xml @@ -28,6 +28,12 @@ ${revision} + + com.alibaba.cloud + spring-cloud-alibaba-commons + ${revision} + + com.alibaba.cloud spring-cloud-starter-alibaba-seata diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index f07b95fc..084300b4 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -18,7 +18,6 @@ Spring Cloud Alibaba Dependencies - 2.0.3.RELEASE 1.8.0 1.3.0 @@ -161,6 +160,7 @@ sentinel-spring-webflux-adapter ${sentinel.version} + com.alibaba.csp sentinel-api-gateway-adapter-common @@ -240,6 +240,12 @@ ${revision} + + com.alibaba.cloud + spring-cloud-alibaba-commons + ${revision} + + com.alibaba.cloud @@ -260,68 +266,6 @@ - - spring - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/release - - false - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot-local - - true - - - false - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - https://repo.spring.io/libs-release-local - - false - - - - - release @@ -401,12 +345,44 @@ Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots/ + sonatype-nexus-staging Nexus Release Repository https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + true + + + false + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release-local + + false + + + + + diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc new file mode 100644 index 00000000..1bf27292 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc @@ -0,0 +1,176 @@ +== Spring Cloud AliCloud ACM + +Spring Cloud AliCloud ACM 是阿里云提供的商业版应用配置管理(Application Configuration Management) 产品 在 Spring Cloud 应用侧的客户端实现,且目前完全免费。 + +使用 Spring Cloud AliCloud ACM,可基于 Spring Cloud 的编程模型快速接入 ACM 配置管理功能。 + +NOTE: 目前 EDAS 已经支持直接部署 Nacos Config 应用 + +=== 如何引入 Spring Cloud AliCloud ACM + +如果要在您的项目中引入 ACM,使用 group ID 为 `com.alibaba.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-acm` 的 starter。 + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-acm + +---- + +=== 使用 ACM 进行配置管理 + +当客户端引入了 Spring Cloud AliCloud ACM Starter 以后,应用启动时会自动从配置管理的服务端获取配置信息,并注入到 Spring 的 Environment 中。 + +以下是一个简单的应用示例。 + +[source,java] +---- +@SpringBootApplication +public class ProviderApplication { + + public static void main(String[] args) { + ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args); + String userName = applicationContext.getEnvironment().getProperty("user.name"); + String userAge = applicationContext.getEnvironment().getProperty("user.age"); + System.err.println("user name :"+userName+"; age: "+userAge); + } +} +---- + +在从配置中心服务端获取配置信息之前,还需要配置服务端的地址,在 bootstrap.properties 中,还需要配置以下信息。 + +[source,properties] +---- +# 必选,应用名会被作为从服务端获取配置 key 的关键词组成部分 +spring.application.name=acm-config +server.port=18081 +# 以下就是配置中心服务端的IP和端口配置 +spring.cloud.alicloud.acm.server-list=127.0.0.1 +spring.cloud.alicloud.acm.server-port=8080 +---- + +NOTE: 此时没有启动配置中心,启动应用会报错,因此在应用启动之前,应当首先启动配置中心。 + + +==== 启动配置中心 + +ACM 使用的配置中心有两种,一种是本地运行的轻量版配置中心,主要用于开发和本地调试,一种是阿里云产品 ACM。通常情况下,可以使用轻量版配置中心作为开发和测试环境,使用云上的 ACM 作为灰度和生产环境。 + +===== 使用轻量版配置中心 + +轻量版配置中心的下载和启动方式可参考 https://help.aliyun.com/document_detail/44163.html[这里] + +NOTE: 只需要执行文档中的第1步 (下载轻量配置中心) 和第2步 (启动轻量配置中心)。 + + +===== 使用阿里云配置中心 + +使用云上 ACM ,可以省去服务端的维护工作,同时稳定性也会更有保障。当使用云上配置中心时,代码部分和使用轻量配置中心并没有区别,但是配置上会有一些区别。 + +以下是一个简单的使用云上配置中心的配置示例,配置详情需要在 https://acm.console.aliyun.com[ACM控制台查询] + +[source,properties] +---- +# 应用名会被作为从服务端获取配置 key 的关键词组成部分,因此是必选 +spring.application.name=acm-config +# 端口配置自由配置即可 +server.port=18081 +# 以下就是配置中心的IP和端口配置 +spring.cloud.alicloud.acm.server-mode=EDAS +spring.cloud.alicloud.access-key=你的阿里云AK +spring.cloud.alicloud.secret-key=你的阿里云SK +spring.cloud.alicloud.acm.endpoint=acm.aliyun.com +spring.cloud.alicloud.acm.namespace=你的 ACM namespace,需要在 ACM 控制台查询 +---- + +NOTE: EDAS 提供应用托管服务,如果你将应用托管到 EDAS,那么 EDAS 将会自动为你填充所有与业务无关的配置。 + +==== 在配置中心添加配置 + +1. 启动好轻量版配置中心之后,在控制台中添加如下的配置。 + +[source,subs="normal"] +---- +Group: DEFAULT_GROOUP + +DataId: acm-config.properties + +Content: user.name=james + user.age=18 +---- + +NOTE: DataId 的格式为 `{prefix}.{file-extension}`,prefix 默认从配置 spring.application.name 中取值,file-extension 默认的值为 "properties"。 + +==== 启动应用验证 + +启动这个Example,可以在控制台看到打印出的值正是我们在轻量版配置中心上预先配置的值。 + +[source,subs="normal"] +---- +user name :james; age: 18 +---- + +=== 更改配置文件扩展名 + +spring-cloud-starter-alicloud-acm 中 DataId 默认的文件扩展名是 properties。除去 properties 格式之外,也支持 yaml 格式。 +支持通过 spring.cloud.alicloud.acm.file-extension 来配置文件的扩展名,yaml 格式可以配置成 `yaml` 或 `yml`。 + +NOTE: 修改文件扩展名后,在配置中心中的 DataID 以及 Content 的格式都必须做相应的修改。 + +=== 动态更新 + +spring-cloud-starter-alicloud-acm 默认支持配置的动态更新,当您在配置中心修改配置的内容时,会发布 Spring 中的 RefreshEvent 事件。 +带有 @RefreshScope 和 @ConfigurationProperties 注解的类会自动刷新。 + +NOTE: 你可以通过配置 spring.cloud.alicloud.acm.refresh.enabled=false 来关闭动态刷新。 + +=== Profile 粒度的配置 + +spring-cloud-starter-alicloud-acm 在加载配置的时候,首先会加载 DataId 为{spring.application.name}.{file-extension}的配置,当 spring.profiles.active 中配置有内容时,还会依次去加载 spring.profile 对应的内容, DataId 的格式为{spring.application.name}-{profile}.{file-extension}的配置,且后者的优先级高于前者。 + +spring.profiles.active 属于配置的元数据,所以也必须配置在 bootstrap.properties 或 bootstrap.yaml 中。比如可以在 bootstrap.properties 中增加如下内容。 + +[sources,properties] +---- +spring.profiles.active={profile-name} +---- + +Note: 也可以通过 JVM 参数 -Dspring.profiles.active=develop 或者 --spring.profiles.active=develop 这类优先级更高的方式来配置,只需遵循 Spring Boot 规范即可。 + + +=== 自定义配置中心超时时间 + +ACM Client 与 Server 通信的超时时间默认是 3000ms,可以通过 `spring.cloud.alicloud.acm.timeout` 来修改超时时间,单位为 ms 。 + +=== 自定义 Group 的配置 + +在没有明确指定 `{spring.cloud.alicloud.acm.group}` 配置的情况下, 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现: + +[source,properties] +---- +spring.cloud.alicloud.acm.group=DEVELOP_GROUP +---- + +NOTE: 该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值要和 `spring.cloud.alicloud.acm.group` 的配置值一致。 + +=== 共享配置 + +ACM 提供了一种多个应用之间共享配置中心的同一个配置的推荐方式,供多个应用共享一些配置时使用,您在使用的时候需要添加在 bootstrap 中添加一个配置项 `spring.application.group`。 + +[source,properties] +---- +spring.application.group=company.department.team +---- + +这时应用在获取上文提到的自身所独有的配置之前,会先依次从这些 DataId 去获取,分别是 company:application.properties, company.department:application.properties, company.department.team:application.properties。 +然后,还会从 {spring.application.group}:{spring.application.name}.{file-extension} 中获取,越往后优先级越高,最高的仍然是应用自身所独有的配置。 + + +NOTE: 共享配置中 DataId 默认后缀为 properties,可以通过 spring.cloud.alicloud.acm.file-extension 配置. `{spring.application.group}:{spring.application.name}.{file-extension}` 。 + +NOTE: 如果设置了 `spring.profiles.active` ,DataId 的格式还支持 `{spring.application.group}:{spring.application.name}-{spring.profiles.active}.{file-extension}`。优先级高于 `{spring.application.group}:{spring.application.name}.{file-extension}` + +=== Actuator 监控 + +ACM 对应的 Actuator 监控地址为 `/acm`,其中 `config` 代表了 ACM 元数据配置的信息,`runtime.sources` 对应的是从 ACM 服务端获取的配置的信息及最后刷新时间, `runtime.refreshHistory` 对应的是动态刷新的历史记录。 \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/ans.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/ans.adoc new file mode 100644 index 00000000..f44c1a18 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/ans.adoc @@ -0,0 +1,96 @@ +== Spring Cloud AliCloud ANS + +ANS(Application Naming Service) 是隶属于阿里云 EDAS 产品的组件, Spring Cloud AliCloud ANS 提供了 Spring Cloud 规范下商业版的服务注册与发现,可以让用户方便的在本地开发,同时也可以运行在云环境里。 + +NOTE: 目前 EDAS 已经支持直接部署 Nacos Discovery 应用 + +=== 如何引入 Spring Cloud AliCloud ANS + +如果要在您的项目中引入 ANS,使用 group ID 为 `com.alibaba.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-ans` 的 starter。 + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-ans + +---- + +=== 使用ANS进行服务注册 + +当客户端引入了 Spring Cloud AliCloud ANS Starter 以后,服务的元数据会被自动注册到注册中心,比如IP、端口、权重等信息。客户端会与服务端保持心跳,来证明自己可以正常提供服务。 + +以下是一个简单的应用示例。 + +[source,java] +---- +@SpringBootApplication +@EnableDiscoveryClient +@RestController +public class ProviderApplication { + + @RequestMapping("/") + public String home() { + return "Hello world"; + } + + public static void main(String[] args) { + SpringApplication.run(ProviderApplication.class, args); + } + +} +---- + +既然服务会被注册到注册中心,那么肯定需要配置注册中心的地址,在 application.properties 中,还需要配置上以下地址。 + +[source,properties] +---- +# 应用名会被作为服务名称使用,因此会必选 +spring.application.name=ans-provider +server.port=18081 +# 以下就是注册中心的IP和端口配置 +spring.cloud.alicloud.ans.server-list=127.0.0.1 +spring.cloud.alicloud.ans.server-port=8080 +---- + +NOTE: 此时没有启动注册中心,启动应用会报错,因此在应用启动之前,应当首先启动注册中心。 + +=== 启动注册中心 + +ANS 使用的注册中心有两种,一种是完全免费的轻量版配置中心,主要用于开发和本地调试,一种是云上注册中心,ANS 依托于阿里云 EDAS 产品提供服务注册的功能。通常情况下,可以使用轻量版配置中心作为开发和测试环境,使用云上的 EDAS 作为灰度和生产环境。 + +==== 启动轻量版配置中心 + +轻量版配置中心的下载和启动方式可参考 https://help.aliyun.com/document_detail/44163.html?spm=a2c4g.11186623.6.677.5f206b82Z2mTCF[这里] + +NOTE: 只需要进行第1步(下载轻量配置中心)和第2步(启动轻量配置中心)即可,第3步(配置hosts)在与 ANS 结合使用时,不需要操作。 + +启动完轻量版配置中心以后,直接启动 ProviderApplication ,即可将服务注册到轻量版配置中心,由于轻量版配置中心的默认端口是8080,因此你可以打开 http://127.0.0.1:8080 ,点击左侧"服务列表",查看注册上来的服务。 + +==== 使用云上注册中心 + +使用云上注册中心,可以省去服务端的维护工作,同时稳定性也会更有保障。当使用云上注册中心时,代码部分和使用轻量配置中心并没有区别,但是配置上会有一些区别。 + +以下是一个简单的使用云上配置中心的配置示例。 + +[source,properties] +---- +# 应用名会被作为服务名称使用,因此是必选 +spring.application.name=ans-provider +# 端口配置自由配置即可 +server.port=18081 +# 以下就是注册中心的IP和端口配置,因为默认就是127.0.0.1和8080,因此以下两行配置也可以省略 +spring.cloud.alicloud.ans.server-mode=EDAS +spring.cloud.alicloud.access-key=你的阿里云AK +spring.cloud.alicloud.secret-key=你的阿里云SK +spring.cloud.alicloud.edas.namespace=cn-xxxxx +---- + +server-mode 的默认值为 LOCAL ,如果要使用云上注册中心,则需要更改为 EDAS 。 + +access-key 和 secret-key 则是阿里云账号的 AK/SK,需要首先注册阿里云账号,然后登陆 https://usercenter.console.aliyun.com/#/manage/ak[阿里云AK/SK管理页面] ,即可看到 AccessKey ID 和 Access Key Secret ,如果没有的话,需要点击"创建 AccessKey"按钮创建。 + +namespace 是阿里云 EDAS 产品的概念,用于隔离不同的环境,比如测试环境和生产环境。要获取 namespace 需要 https://common-buy.aliyun.com/?spm=5176.11451019.0.0.6f5965c0Uq5tue&commodityCode=edaspostpay#/buy[开通 EDAS 服务],按量计费模式下开通是免费的,开通以后进入 https://edas.console.aliyun.com/#/namespaces?regionNo=cn-hangzhou[EDAS控制台],即可看到对应的 namespace,比如 cn-hangzhou。 + +NOTE: EDAS 提供应用托管服务,如果你将应用托管到 EDAS,那么 EDAS 将会自动为你填充所有配置。 + diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc index 4827d751..4f7de312 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc @@ -229,7 +229,7 @@ in develop-env enviroment; user name :nacos-config-yaml-update; age: 68 spring.profiles.active=product ---- -同时生产环境上 Nacos 需要添加对应 DataId 的基础配置。例如,在生成环境下的 Naocs 添加了DataId为:nacos-config-product.yaml的配置: +同时生产环境上 Nacos 需要添加对应 DataId 的基础配置。例如,在生产环境下的 Naocs 添加了DataId为:nacos-config-product.yaml的配置: [source,subs="normal"] ---- @@ -415,8 +415,8 @@ Endpoint 暴露的 json 中包含了三种属性: |=== |配置项 |Key |默认值 |说明 |服务端地址|`spring.cloud.nacos.config.server-addr`|| Nacos Server 启动监听的ip地址和端口 -|配置对应的 DataId|`spring.cloud.nacos.config.name`|| 先取 prefix,再去 name,最后取 spring.application.name -|配置对应的 DataId|`spring.cloud.nacos.config.prefix`|| 先取 prefix,再去 name,最后取 spring.application.name +|配置对应的 DataId|`spring.cloud.nacos.config.name`|| 先取 prefix,再取 name,最后取 spring.application.name +|配置对应的 DataId|`spring.cloud.nacos.config.prefix`|| 先取 prefix,再取 name,最后取 spring.application.name |配置内容编码|`spring.cloud.nacos.config.encode`||读取的配置内容对应的编码 |GROUP|`spring.cloud.nacos.config.group`|`DEFAULT_GROUP`|配置对应的组 |文件扩展名|`spring.cloud.nacos.config.fileExtension`|`properties`|配置项对应的文件扩展名,目前支持 properties 和 yaml(yml) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/oss.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/oss.adoc new file mode 100644 index 00000000..bff6b663 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/oss.adoc @@ -0,0 +1,140 @@ +== Spring Cloud AliCloud OSS + +OSS(Object Storage Service)是阿里云的一款对象存储服务产品, Spring Cloud AliCloud OSS 提供了Spring Cloud规范下商业版的对象存储服务,提供简单易用的API,并且支持与 Spring 框架中 Resource 的整合。 + +=== 如何引入 Spring Cloud AliCloud OSS + +如果要在您的项目中引入 OSS,使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-oss` 的 starter。 + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-oss + +---- + +=== 如何使用 OSS API + +==== 配置 OSS + +使用 Spring Cloud AliCloud OSS 之前,需要在 application.properties 中加入以下配置。 + +[source,properties] +---- +spring.cloud.alicloud.access-key=你的阿里云AK +spring.cloud.alicloud.secret-key=你的阿里云SK +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +---- + +access-key 和 secret-key 是阿里云账号的AK/SK,需要首先注册阿里云账号,然后登陆 https://usercenter.console.aliyun.com/#/manage/ak[阿里云AK/SK管理页面] ,即可看到 AccessKey ID 和 Access Key Secret ,如果没有的话,需要点击"创建AccessKey"按钮创建。 + +endpoint可以到 OSS 的 https://help.aliyun.com/document_detail/31837.html?spm=a2c4g.11186623.2.9.7dc72841Z2hGqa#concept-zt4-cvy-5db[官方文档]中查看,根据所在的 region ,填写对应的 endpoint 即可。 + + +==== 引入 OSS API + +Spring Cloud Alicloud OSS 中的 OSS API 基于阿里云官方OSS SDK提供,具备上传、下载、查看等所有对象存储类操作API。 + +一个简单的使用 OSS API 的应用如下。 + +[source,java] +---- +@SpringBootApplication +public class OssApplication { + + @Autowired + private OSS ossClient; + + @RequestMapping("/") + public String home() { + ossClient.putObject("bucketName", "fileName", new FileInputStream("/your/local/file/path")); + return "upload success"; + } + + public static void main(String[] args) throws URISyntaxException { + SpringApplication.run(OssApplication.class, args); + } + +} +---- + +在上传文件之前,首先需要 https://account.aliyun.com/register/register.htm?spm=5176.8142029.388261.26.e9396d3eaYK2sG&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F[注册阿里云账号] ,如果已经有的话,请 https://common-buy.aliyun.com/?spm=5176.8465980.unusable.dopen.4cdf1450rg8Ujb&commodityCode=oss#/open[开通OSS服务]。 + +进入 https://oss.console.aliyun.com/overview[OSS控制台],点击左侧"新建Bucket",按照提示创建一个Bucket,然后将bucket名称替换掉上面代码中的"bucketName",而"fileName"取任意文件名,"/your/local/file/path"取任意本地文件路径,然后 curl http://127.0.0.1:端口/ 即可上传文件,可以到 https://oss.console.aliyun.com/overview[OSS控制台]查看效果。 + +更多关于 OSS API 的操作,可以参考 https://help.aliyun.com/document_detail/32008.html[OSS官方SDK文档]。 + +=== 与 Spring 框架的 Resource 结合 + +Spring Cloud AliCloud OSS 整合了 Spring 框架的 Resource 规范,可以让用户很方便的引用 OSS 的资源。 + +一个简单的使用 Resource 的例子如下。 + +[source,java] +---- +@SpringBootApplication +public class OssApplication { + + @Value("oss://bucketName/fileName") + private Resource file; + + @GetMapping("/file") + public String fileResource() { + try { + return "get file resource success. content: " + StreamUtils.copyToString( + file.getInputStream(), Charset.forName(CharEncoding.UTF_8)); + } catch (Exception e) { + return "get resource fail: " + e.getMessage(); + } + } + + public static void main(String[] args) throws URISyntaxException { + SpringApplication.run(OssApplication.class, args); + } + +} +---- + +NOTE: 以上示例运行的前提是,在 OSS 上需要有名为"bucketName"的Bucket,同时在该Bucket下,存在名为"fileName"的文件。 + +=== 采用 STS 授权 + +Spring Cloud AliCloud OSS 除了 AccessKey/SecretKey 的授权方式以外,还支持 STS 授权方式。 STS 是临时访问令牌的方式,一般用于授权第三方,临时访问自己的资源。 + +作为第三方,也就是被授权者,只需要配置以下内容,就可以访问临时被授权的资源。 + +[source,properties] +---- +spring.cloud.alicloud.oss.authorization-mode=STS +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +spring.cloud.alicloud.oss.sts.access-key=你被授权的AK +spring.cloud.alicloud.oss.sts.secret-key=你被授权的SK +spring.cloud.alicloud.oss.sts.security-token=你被授权的ST +---- + +其中 spring.cloud.alicloud.oss.authorization-mode 是枚举类型,此时填写 STS ,代表采用 STS 的方式授权。 endpoint可以到 OSS 的 https://help.aliyun.com/document_detail/31837.html?spm=a2c4g.11186623.2.9.7dc72841Z2hGqa#concept-zt4-cvy-5db[官方文档]中查看,根据所在的 region ,填写对应的 endpoint 即可。 + +access-key、secret-key和security-token需要由授权方颁发,如果对 STS 不了解的话,可以参考 https://help.aliyun.com/document_detail/31867.html[STS官方文档]。 + +=== 更多客户端配置 + +除了基本的配置项以外, Spring Cloud AliCloud OSS 还支持很多额外的配置,也是在 application.properties 文件中。 + +以下是一些简单的示例。 + +[source,properties] +---- +spring.cloud.alicloud.oss.authorization-mode=STS +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +spring.cloud.alicloud.oss.sts.access-key=你被授权的AK +spring.cloud.alicloud.oss.sts.secret-key=你被授权的SK +spring.cloud.alicloud.oss.sts.security-token=你被授权的ST + +spring.cloud.alicloud.oss.config.connection-timeout=3000 +spring.cloud.alicloud.oss.config.max-connections=1000 +---- + +如果想了解更多的配置项,可以参考 https://help.aliyun.com/document_detail/32010.html?spm=a2c4g.11186623.6.703.50b25413nGsYHc[OSSClient配置项] 的末尾表格。 + +NOTE: 通常情况下,都需要将 https://help.aliyun.com/document_detail/32010.html?spm=a2c4g.11186623.6.703.50b25413nGsYHc[OSSClient配置项] 末尾表格中的参数名更换成"-"连接,且所有字母小写。例如 ConnectionTimeout,对应 connection-timeout。 \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/schedulerx.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/schedulerx.adoc new file mode 100644 index 00000000..bb23022a --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/schedulerx.adoc @@ -0,0 +1,114 @@ +== Spring Cloud AliCloud SchedulerX + +SchedulerX(分布式任务调度) 是隶属于阿里云EDAS产品的组件, Spring Cloud AliCloud SchedulerX 提供了在Spring Cloud的配置规范下,分布式任务调度的功能支持。SchedulerX可提供秒级、精准、高可靠、高可用的定时任务调度服务,并支持多种类型的任务调度,如简单单机任务、简单多机任务、脚本任务以及网格任务。 + +=== 如何引入 Spring Cloud AliCloud SchedulerX + +如果要在您的项目中引入 SchedulerX,使用 group ID 为 `com.alibaba.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-schedulerX` 的 starter。 + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-schedulerX + +---- + +=== 启动SchedulerX任务调度 + +当客户端引入了 Spring Cloud AliCloud SchedulerX Starter 以后,只需要进行一些简单的配置,就可以自动初始化SchedulerX的任务调度服务。 + +以下是一个简单的应用示例。 + +[source,java] +---- +@SpringBootApplication +public class ScxApplication { + + public static void main(String[] args) { + SpringApplication.run(ScxApplication.class, args); + } + +} +---- + +在application.properties中,需要加上以下配置。 + +[source,properties] +---- +server.port=18033 +# 其中cn-test是SchedulerX的测试区域 +spring.cloud.alicloud.scx.group-id=*** +spring.cloud.alicloud.edas.namespace=cn-test +---- + +在获取group-id之前,需要首先 https://account.aliyun.com/register/register.htm?spm=5176.8142029.388261.26.e9396d3eEIv28g&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F[注册阿里云账号] ,然后 https://common-buy.aliyun.com/?spm=5176.11451019.0.0.6f5965c0Uq5tue&commodityCode=edaspostpay#/buy[开通EDAS服务] ,并 https://edas.console.aliyun.com/#/edasTools[开通分布式任务管理组件] 。 + +其中group-id的获取,请参考 https://help.aliyun.com/document_detail/98784.html?spm=a2c4g.11186623.2.17.23c87da9P2F3tG[这里]。 + +NOTE: 在创建group的时候,要选择"测试"区域。 + +=== 编写一个简单任务 + +简单任务是最常用的任务类型,只需要实现 ScxSimpleJobProcessor 接口即可。 + +以下是一个简单的单机类型任务示例。 + +[source,java] +---- +public class SimpleTask implements ScxSimpleJobProcessor { + + @Override + public ProcessResult process(ScxSimpleJobContext context) { + System.out.println("-----------Hello world---------------"); + ProcessResult processResult = new ProcessResult(true); + return processResult; + } + +} +---- + +=== 对任务进行调度 + +进入 https://edas.console.aliyun.com/#/edasSchedulerXJob?regionNo=cn-test[SchedulerX任务列表] 页面,选择上方"测试"区域,点击右上角"新建Job",创建一个Job,即如下所示。 + +[source,text] +---- +Job分组:测试——***-*-*-**** +Job处理接口:org.springframework.cloud.alibaba.cloud.examples.SimpleTask +类型:简单Job单机版 +定时表达式:默认选项——0 * * * * ? +Job描述:无 +自定义参数:无 +---- + +以上任务类型选择了"简单Job单机版",并且制定了Cron表达式为"0 * * * * ?",这意味着,每过一分钟,任务将会被执行且只执行一次。 + +更多任务类型,请参考 https://help.aliyun.com/document_detail/43136.html[SchedulerX官方文档]。 + +=== 生产环境使用 + +以上使用的都是SchedulerX的"测试"区域,主要用于本地调试和测试。 + +在生产级别,除了上面的group-id和namespace以外,还需要一些额外的配置,如下所示。 + +[source,properties] +---- +server.port=18033 +# 其中cn-test是SchedulerX的测试区域 +spring.cloud.alicloud.scx.group-id=*** +spring.cloud.alicloud.edas.namespace=*** +# 当应用运行在EDAS上时,以下配置不需要手动配置。 +spring.cloud.alicloud.access-key=*** +spring.cloud.alicloud.secret-key=*** +# 以下配置不是必须的,请参考SchedulerX文档 +spring.cloud.alicloud.scx.domain-name=*** +---- + +其中group-id与之前的获取方式一样,namespace则是从EDAS控制台左侧"命名空间"列表中获取命名空间ID。 + +NOTE: group-id必须创建在namespace当中。 + +access-key以及secret-key为阿里云账号的AK/SK信息,如果应用在EDAS上部署,则不需要填写这两项信息,否则请前往 https://usercenter.console.aliyun.com/#/manage/ak[安全信息管理]获取。 + +domain-name并不是必须的,具体请参考 https://help.aliyun.com/document_detail/35359.html[SchedulerX官方文档]。 \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc index e51bb9b7..2a8832f5 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc @@ -150,11 +150,13 @@ server.listen(8060, function() { ===== 测试1:Spring Cloud微服务完美调用异构微服务 -为你的Spring Cloud微服务整合Ribbon,然后构建 http://node-service/ ,就可以请求到异构微服务的 `/` 了。 +为你的Spring Cloud微服务整合Ribbon,然后构建 `http://node-service/**` +,就可以请求到异构微服务的 `/**` 了。 示例: -Ribbon请求 `http://node-service/` 会请求到 `http://localhost:8060/` ,以此类推。 +Ribbon请求 `http://node-service/` 会请求到 `http://localhost:8060/` +,以此类推。 至于断路器,正常为你的Spring Cloud微服务整合Sentinel或者Hystirx、Resilience4J即可 。 @@ -167,8 +169,8 @@ Cloud微服务整合Sentinel或者Hystirx、Resilience4J即可 。 如果你有一个Spring Cloud微服务叫做 `spring-cloud-microservice` ,那么NodeJS应用只需构建 -http://localhost:8070/spring-cloud-microservice/ ,Alibaba -Sidecar就会把请求转发到 `spring-cloud-microservice` 的 `/` 。 +`http://localhost:8070/spring-cloud-microservice/**` ,Alibaba +Sidecar就会把请求转发到 `spring-cloud-microservice` 的 `/**` 。 而Spring Cloud Gateway是整合了Ribbon的,所以实现了负载均衡;Spring Cloud Gateway还可以整合Sentinel或者Hystirx、Resilience4J,所以也带有了断路器。 diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sms.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sms.adoc new file mode 100644 index 00000000..e6f6813e --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sms.adoc @@ -0,0 +1,253 @@ +== Spring Cloud AliCloud SMS + +短信服务(Short Message Service)是阿里云为用户提供的一种通信服务的能力。 Spring Cloud AliCloud SMS 实现了与 SMS 的简单集成,提供更为简单易用的 API,可以基于 Spring Cloud Alibaba SMS 来快速的接入阿里云的 SMS 服务。 + +=== 如何引入 Spring Cloud AliCloud SMS + +如果要在您的项目中引入 SMS,使用 group ID 为 `com.alibaba.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-sms` 的 starter。 + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-sms + +---- + +=== 如何使用 SMS API + +==== 配置 SMS + +使用 Spring Cloud AliCloud SMS 之前,需要在 application.properties 中加入以下配置。 + +[source,properties] +---- +spring.cloud.alicloud.access-key=你的阿里云 AK +spring.cloud.alicloud.secret-key=你的阿里云 SK +---- + +access-key 和 secret-key 是阿里云账号的 AK/SK,需要首先注册阿里云账号,然后登陆 https://usercenter.console.aliyun.com/#/manage/ak[阿里云AK/SK管理页面] ,即可看到 AccessKey ID 和 Access Key Secret ,如果没有的话,需要点击"创建AccessKey"按钮创建。 + + +==== 引入 SMS API + +Spring Cloud Alicloud SMS 中的 SMS API 基于阿里云官方 SMS SDK ,提供具备单个短信发送、多个短信批量发送、短信查询、短信消息(`短信回执消息` 和 `上行短信消息`) 类型操作API。 + +一个简单的使用 SMS API 发送短信的应用如下。 + +[source,java] +---- +@SpringBootApplication +public class SmsApplication { + + @Autowired + private ISmsService smsService; + + /** + * 短信发送 Example + * @param code + * @return + */ + @RequestMapping("/batch-sms-send.do") + + public SendBatchSmsResponse batchsendCheckCode( + @RequestParam(name = "code") String code) { + + // 组装请求对象-具体描述见控制台-文档部分内容 + SendSmsRequest request = new SendSmsRequest(); + // 必填:待发送手机号 + request.setPhoneNumbers("152******"); + // 必填:短信签名-可在短信控制台中找到 + request.setSignName("******"); + // 必填:短信模板-可在短信控制台中找到 + request.setTemplateCode("******"); + // 可选:模板中的变量替换JSON串,如模板内容为"【企业级分布式应用服务】,您的验证码为${code}"时,此处的值为 + request.setTemplateParam("{\"code\":\"" + code + "\"}"); + SendSmsResponse sendSmsResponse ; + try { + sendSmsResponse = smsService.sendSmsRequest(request); + } + catch (ClientException e) { + e.printStackTrace(); + sendSmsResponse = new SendSmsResponse(); + } + return sendSmsResponse ; + } + + public static void main(String[] args) throws URISyntaxException { + + SpringApplication.run(SmsApplication.class, args); + } + +} +---- + +在发送短信之前,首先需要 https://account.aliyun.com/register/register.htm?spm=5176.8142029.388261.26.e9396d3eaYK2sG&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F[注册阿里云账号] ,如果已经有的话,请 https://dysms.console.aliyun.com/dysms.htm?spm=5176.8195934.1283918..18924183bHPct2&accounttraceid=c8cb4243-3080-4eb1-96b0-1f2316584269#/[开通 SMS 服务]。 + +更多关于 SMS 发送短信的步骤,可以参考 SMS 官方 https://help.aliyun.com/document_detail/55284.html?spm=a2c4g.11186623.6.568.715e4f30ZiVkbI[短信发送API(SendSms)---JAVA] 文档。 + +NOTE: 由于早期的 SMS sdk 版本的问题,如果短信发送失败,请将代码中含有明确指定 MethodType 为 POST 的这行代码给删除掉。如果还有问题,请第一时间联系我们。 + + +=== SMS Api 的高级功能 + +Spring Cloud Alicloud SMS 封装的 API 接口为了降低学习的成本,尽量保持和官网提供的 API 以及 Example 保持一致。 + +* 批量短信发送 + +参考以下的 Example ,来快速开发一个具有批量短信发送的功能。在 Controller 中或者新建一个 Controler 新增如下代码: + +[source,java] +---- +/** + * 批量短信发送 Example + * @param code + * @return + */ +@RequestMapping("/batch-sms-send.do") +public SendBatchSmsResponse batchsendCheckCode( + @RequestParam(name = "code") String code) { + // 组装请求对象 + SendBatchSmsRequest request = new SendBatchSmsRequest(); + // 使用 GET 提交 + request.setMethod(MethodType.GET); + // 必填:待发送手机号。支持JSON格式的批量调用,批量上限为100个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式 + request.setPhoneNumberJson("[\"177********\",\"130********\"]"); + // 必填:短信签名-支持不同的号码发送不同的短信签名 + request.setSignNameJson("[\"*******\",\"*******\"]"); + // 必填:短信模板-可在短信控制台中找到 + request.setTemplateCode("******"); + // 必填:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为 + // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败 + request.setTemplateParamJson( + "[{\"code\":\"" + code + "\"},{\"code\":\"" + code + "\"}]"); + SendBatchSmsResponse sendSmsResponse ; + try { + sendSmsResponse = smsService + .sendSmsBatchRequest(request); + return sendSmsResponse; + } + catch (ClientException e) { + e.printStackTrace(); + sendSmsResponse = new SendBatchSmsResponse(); + } + return sendSmsResponse ; +} +---- + +NOTE: 这里设置请求的 MethodType 为 GET,和官网给出的例子还有些不一样。这是因为依赖的阿里云 POP API 版本不一致导致不兼容的问题,设置为 GET 即可。 + +更多的参数说明可 https://help.aliyun.com/document_detail/66041.html?spm=a2c4g.11186623.6.571.631315e8AauJhP[参考这里] + +* 短信查询 + +参考以下的 Example ,可以快速开发根据某个指定的号码查询短信历史发送状态。在 Controller 中或者新建一个 Controler 新增如下代码: + +[source,java] +---- +/** + * + * 短信查询 Example + * @param telephone + * @return + */ +@RequestMapping("/query.do") +public QuerySendDetailsResponse querySendDetailsResponse( + @RequestParam(name = "tel") String telephone) { + // 组装请求对象 + QuerySendDetailsRequest request = new QuerySendDetailsRequest(); + // 必填-号码 + request.setPhoneNumber(telephone); + // 必填-短信发送的日期 支持30天内记录查询(可查其中一天的发送数据),格式yyyyMMdd + request.setSendDate("20190103"); + // 必填-页大小 + request.setPageSize(10L); + // 必填-当前页码从1开始计数 + request.setCurrentPage(1L); + try { + QuerySendDetailsResponse response = smsService.querySendDetails(request); + return response; + } + catch (ClientException e) { + e.printStackTrace(); + } + + return new QuerySendDetailsResponse(); +} + +---- + +更多的参数说明,可 https://help.aliyun.com/document_detail/55289.html?spm=a2c4g.11186623.6.569.4f852c78mugEfx[参考这里] + +* 短信回执消息 + +通过订阅 SmsReport 短信状态报告,可以获知每条短信的发送情况,了解短信是否达到终端用户的状态与相关信息。这些工作已经都被 Spring Cloud AliCloud SMS 封装在内部了。你只需要完成以下两步即可。 + +1、在 `application.properties` 配置文件中(也可以是 application.yaml)配置 SmsReport 的队列名称。 + +.application.properties +[source,properties] +---- +spring.cloud.alicloud.sms.report-queue-name=Alicom-Queue-********-SmsReport +---- + +2、 实现 SmsReportMessageListener 接口,并初始化一个 Spring Bean 。 + +[source,java] +---- +/** + * 如果需要监听短信是否被对方成功接收,只需实现这个接口并初始化一个 Spring Bean 即可。 + */ +@Component +public class SmsReportMessageListener + implements org.springframework.cloud.alicloud.sms.SmsReportMessageListener { + + @Override + public boolean dealMessage(Message message) { + // 在这里添加你的处理逻辑 + + //do something + + System.err.println(this.getClass().getName() + "; " + message.toString()); + return true; + } +} +---- + +更多关于 Message 的消息体格式可 https://help.aliyun.com/document_detail/55496.html?spm=a2c4g.11186623.6.570.7f792c78rOiWXO[参考这里]。 + +* 上行短信消息 + +通过订阅SmsUp上行短信消息,可以获知终端用户回复短信的内容。这些工作也已经被 Spring Cloud AliCloud SMS 封装好了。你只需要完成以下两步即可。 + +1、 在 `application.properties` 配置文件中(也可以是 application.yaml)配置 SmsReport 的队列名称。 + +.application.properties +---- +spring.cloud.alicloud.sms.up-queue-name=Alicom-Queue-********-SmsUp +---- + +2、实现 SmsUpMessageListener 接口,并初始化一个 Spring Bean 。 + +[source,java] +---- +/** + * 如果发送的短信需要接收对方回复的状态消息,只需实现该接口并初始化一个 Spring Bean 即可。 + */ +@Component +public class SmsUpMessageListener + implements org.springframework.cloud.alicloud.sms.SmsUpMessageListener { + + @Override + public boolean dealMessage(Message message) { + // 在这里添加你的处理逻辑 + + //do something + + System.err.println(this.getClass().getName() + "; " + message.toString()); + return true; + } +} +---- + +更多关于 Message 的消息体格式可 https://help.aliyun.com/document_detail/55496.html?spm=a2c4g.11186623.6.570.7f792c78rOiWXO[参考这里]。 \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc index bdbd021b..a736fcfb 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc @@ -23,4 +23,6 @@ include::rocketmq.adoc[] include::sidecar.adoc[] +include::sidecar.adoc[] + diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/acm.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/acm.adoc new file mode 100644 index 00000000..11468106 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/acm.adoc @@ -0,0 +1,178 @@ +== Spring Cloud Alibaba Cloud ACM + +Spring Cloud AliCloud ACM is an implementation of the commercial product Application Configuration Management(ACM) in the client side of Spring Cloud, and is free of charge. + +Use Spring Cloud AliCloud ACM to quickly access ACM configuration management capabilities based on Spring Cloud's programming model. + +NOTE: Currently EDAS already supports direct deployment of the Nacos Config app. + +=== How to Introduce Spring Cloud Alibaba Cloud ACM + +If you want to use ACM in your project, please use the starter with the group ID as `com.alibaba.cloud` and the artifact ID as `spring-cloud-starter-alicloud-acm`. + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-acm + +---- + +=== Use ACM to Manage Configurations + +When Spring Cloud Alibaba Cloud ACM Starter is introduced into the client, the application will automatically get configuration information from the configuration management server when it starts, and inject the configuration into Spring Environment. + +The following is a simple illustration. + +[source,java] +---- +@SpringBootApplication +public class ProviderApplication { + + public static void main(String[] args) { + ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args); + String userName = applicationContext.getEnvironment().getProperty("user.name"); + String userAge = applicationContext.getEnvironment().getProperty("user.age"); + System.err.println("user name :" +userName+"; age: "+userAge); + } +} +---- + +As we need to obtain configuration information from the configuration server, we will need to configure the address of the server. We also need to add the following information in bootstrap.properties. + +[source,properties] +---- +# Required. The application name will be used as part of the keyword to get the configuration key from the server. +spring.application.name=acm-config +server.port=18081 +# The following is the IP and port number of the configuration server. +spring.cloud.alicloud.acm.server-list=127.0.0.1 +spring.cloud.alicloud.acm.server-port=8080 +---- + +NOTE: By now the configuration center is not started yet, so you will get an error message if your application is started. Therefore, start the configuration center before you start your application. + + +==== Start Configuration Center + +ACM uses two types of configuration centers. One is lightweight configuration center, the other is ACM which is used on Alibaba Cloud. Generally, you can use the lightweight version for application development and local testing, and use ACM for canary deployment or production. + +===== Use Lightweight Configuration Center + +Refer to the https://help.aliyun.com/document_detail/44163.html[Configure Lightweight Configuration Center] for details about how to download and install lightweight configuration center. + +NOTE: You only need to perform step 1(Download lightweight configuration center) and step 2(Start lightweight configuration center). + + +===== Use ACM on the Alibaba Cloud + +Using ACM on the cloud saves you from the tedious work of server maintenance while at the same time provides a better stability. There is no difference at the code level between using ACM on cloud and lightweight configuration center, but there are some differences in configurations. + +The following is a simple sample of using ACM. You can view configuration details on https://acm.console.aliyun.com[ACM Console] + +[source,properties] +---- +# The application name will be used as part of the keyword to obtain configuration key from the server, and is mandatory. +spring.application.name=acm-config +# Configure your own port number +server.port=18081 +# The following is the IP and port number of the configuration center. +spring.cloud.alicloud.acm.server-mode=EDAS +spring.cloud.alicloud.access-key=Your Alibaba Cloud AK +spring.cloud.alicloud.secret-key=Your Alibaba Cloud SK +spring.cloud.alicloud.acm.endpoint=acm.aliyun.com +spring.cloud.alicloud.acm.namespace=Your ACM namespace(You can find the namespace on the ACM console) +---- + +NOTE: EDAS provides application hosting service and will fill in all configurations about ACM automatically for the hosted applications. + +==== Add Configuration in the Configuration Center + +1. After you start the lightweight configuration center, add the following configuration on the console. + +[source,subs="normal"] +---- +Group: DEFAULT_GROOUP + +DataId: acm-config.properties + +Content: user.name=james + user.age=18 +---- + +NOTE: The format of dataId is `{prefix}. {file-extension}`. “prefix” is obtained from spring.application.name by default, and the value of “file-extension” is "properties” by default. + +==== Start Application Verification + +Start the following example and you can see that the value printed on the console is the value we configured in the lightweight configuration center. + +[source,subs="normal"] +---- +user name :james; age: 18 +---- + +=== Modify Configuration File Extension + +The default file extension of dataId in spring-cloud-starter-alicloud-acm is properties. In addition to properties, yaml is also supported. +You can set the file extension using spring.cloud.alicloud.acm.file-extension. Just set it to `yaml` or `yml`for yaml format. + +NOTE: After you change the file extension, you need to make corresponding format changes in the DataID and content of the configuration center. + +=== Dynamic Configuration Refresh + +spring-cloud-starter-alicloud-acm supports dynamic configuration updates. RefreshEvent in Spring is published when you update configuration in the configuration center. +All classes with @RefreshScope and @ConfigurationProperties annotations will be refreshed automatically. + +NOTE: You can disable automatic refresh by this setting: spring.cloud.alicloud.acm.refresh.enabled=false + +=== Configure Profile Granularity + +When configuration is loaded by spring-cloud-starter-alicloud-acm, configuration with DataId {spring.application.name}. {file-extension} will be loaded first. If there is content in spring.profiles.active, the content of spring.profile, and configuration with the dataid format of{spring.application.name}-{profile}. {file-extension} will also be loaded in turn, and the latter has higher priority. + +spring.profiles.active is the configuration metadata, and should also be configured in bootstrap.properties or bootstrap.yaml. For example, you can add the following content in bootstrap.properties. + +[sources,properties] +---- +spring.profiles.active={profile-name} +---- + +Note: You can also configure the granularity through JVM parameters such as -Dspring.profiles.active=develop or --spring.profiles.active=develop, which have higher priority. Just follow the specifications of Spring Boot. + + +=== Support Custom ACM Timeout + +the default timeout of ACM client get config from sever is 3000 ms . If you need to define a timeout, set configuration `spring.cloud.alicloud.acm.timeout`,the unit is millisecond. + + +=== Support Custom Group Configurations + +DEFAULT_GROUP is used by default when no `{spring.cloud.alicloud.acm.group}` configuration is defined. If you need to define your own group, you can use the following method: + +[source,properties] +---- +spring.cloud.alicloud.acm.group=DEVELOP_GROUP +---- + +NOTE: This configuration must be placed in the bootstrap.properties file, and the value of Group must be the same with the value of `spring.cloud.alicloud.acm.group`. + +==== Support Shared Configurations + +ACM provides a solution to share the same configuration across multiple applications. You can do this by adding the `spring.application.group` configuration in Bootstrap. + +[source,properties] +---- +spring.application.group=company.department.team +---- + +Then, you application will retrieve configurations from the following DataId in turn before it retrieves its own configuration: company:application.properties, company.department:application.properties, company.department.team:application.properties. +After that, it also retrieves configuration from {spring.application.group}: {spring.application.name}. {file-extension} +The later in order, the higer the priority, and the unique configuration of the application itself has the highest priority. + + +NOTE: The default suffix of DataId is properties, and you can change it using spring.cloud.alicloud.acm.file-extension. `{spring.application.group}: {spring.application.name}. {file-extension}` . + +NOTE: If you configured `spring.profiles.active` , then the DataId format of `{spring.application.group}: {spring.application.name}-{spring.profiles.active}. {file-extension}` is also supported, and has higher priority than `{spring.application.group}: {spring.application.name}. {file-extension}` + +=== Actuator Endpoint + +the Actuator endpoint of ACM is `/acm`, `config` represents the ACM metadata configuration information, `runtime.sources` corresponds to the configuration information obtained from the ACM server and the last refresh time, `runtime.refreshHistory` corresponds to the dynamic refresh history. \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/ans.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/ans.adoc new file mode 100644 index 00000000..dede7648 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/ans.adoc @@ -0,0 +1,96 @@ +== Spring Cloud Alibaba Cloud ANS + +ANS(Application Naming Service) is a component of EDAS. Spring Cloud Alibaba Cloud ANS provides the commercial version of service registration and discovery in conformity with the Spring Cloud specifications, so that you can develop your applications locally and run them on the cloud. + +NOTE: EDAS currently supports direct deployment of Nacos Discovery applications + +=== How to Introduce Spring Cloud Alibaba Cloud ANS + +If you want to use ANS in your project, please use the starter with the group ID as `com.alibaba.cloud` and the artifact ID as `spring-cloud-starter-alicloud-ans`. + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-ans + +---- + +=== Use ANS to Register Service + +When Spring Cloud AliCloud ANS Starter is introduced on the client, the metadata of the service such as IP, port number and weright will be registered to the registration center automatically. The client will maintain heartbeat with the server to prove that it is capable of providing service properly. + +The following is a simple illustration. + +[source,java] +---- +@SpringBootApplication +@EnableDiscoveryClient +@RestController +public class ProviderApplication { + + @RequestMapping("/") + public String home() { + return "Hello world"; + } + + public static void main(String[] args) { + SpringApplication.run(ProviderApplication.class, args); + } + +} +---- + +As the service will registered to the registration center, we will need to configure the address of the registration center. We also need to add the following address in application.properties. + +[source,properties] +---- +# The application name will be used as the service name, therefore it is mandatory. +spring.application.name=ans-provider +server.port=18081 +# The following is the IP and port number of the registration center. +spring.cloud.alicloud.ans.server-list=127.0.0.1 +spring.cloud.alicloud.ans.server-port=8080 +---- + +NOTE: By now the registration center is not started yet, so you will get an error message if your application is started. Therefore, start the registration center before you start your application. + +=== Start Registration Center + +ANS uses two types of registration centers. One is the free lightweight configuration center and the other is the registration center on cloud, which is provided through EDAS. Generally, you can use the lightweight version for application development and local testing, and use EDAS for canary deployment or production. + +==== Start Lightweight Configuration Center + +Refer to the https://help.aliyun.com/document_detail/44163.html[Configure Lightweight Configuration Center] for details about how to download and install lightweight configuration center. + +NOTE: You only need to perform step 1(Download lightweight configuration center) and step 2(Start lightweight configuration center). Step 3(Configure hosts) is not required if you use ANS at the same time. + +After you start the lightweight configuration center, start ProviderApplication directly, and you will be able to register your service to the configuration center. The default port of the lightweight configuration center is 8080, therefore you can open http://127.0.0.1:8080, click “Services” on the left and see the registered service. + +==== User Registration Center on the Cloud + +Using the registration center on the cloud saves you from the tedious work of server maintenance while at the same time provides a better stability. There is no difference at the code level between using the registration center on cloud and lightweight configuration center, but there are some differences in configurations. + +The following is a simple sample of using the registration center on the cloud. + +[source,properties] +---- +# The application name will be used the service name, and is therefore mandatory. +spring.application.name=ans-provider +# Configure your own port number +server.port=18081 +# The following is the IP and port number of the configuration center. The default value is 127.0.0.1 and 8080, so the following lines can be omitted. +spring.cloud.alicloud.ans.server-mode=EDAS +spring.cloud.alicloud.access-key=Your Alibaba Cloud AK +spring.cloud.alicloud.secret-key=Your Alibaba Cloud SK +spring.cloud.alicloud.edas.namespace=cn-xxxxx +---- + +The default value of server-mode is LOCAL. If you want to use the registration center on cloud, you need to change it to EDAS. + +Access-key and secret-key are the AK/SK of your Alibaba Cloud account. Register an Alibaba Cloud account first and log on to the Cloud Console https://usercenter.console.aliyun.com/#/manage/ak[Alibaba Cloud AK/SK] to copy your AccessKey ID and Access Key Secret. If you haven’t created one, click the “Create AccessKey” button. + +Namespace is a concept in EDAS, which is used to isolate environments, such as testing environment and production environment. To find your namespace, click to https://common-buy.aliyun.com/?spm=5176.11451019.0.0.6f5965c0Uq5tue&commodityCode=edaspostpay#/buy[Sign up for EDAS] first. You will not be charged under the pay-as-you-go mode. Then log on to the https://edas.console.aliyun.com/#/namespaces?regionNo=cn-hangzhou[EDAS Console] and you will be able to see your namespace, for example cn-hangzhou. + +NOTE: EDAS provides application hosting service and will fill in all configurations automatically for the hosted applications. + diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/circuitbreaker-sentinel.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/circuitbreaker-sentinel.adoc new file mode 100644 index 00000000..b2695e72 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/circuitbreaker-sentinel.adoc @@ -0,0 +1,73 @@ +=== Circuit Breaker: Spring Cloud Circuit Breaker With Sentinel & Configuring Sentinel Circuit Breakers + +==== Default Configuration + +To provide a default configuration for all of your circuit breakers create a `Customizer` bean that is passed a +`SentinelCircuitBreakerFactory` or `ReactiveSentinelCircuitBreakerFactory`. +The `configureDefault` method can be used to provide a default configuration. + +==== +[source,java] +---- +@Bean +public Customizer defaultCustomizer() { + return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id) + .build()); +} +---- +==== + +You can choose to provide default circuit breaking rules via `SentinelConfigBuilder#rules(rules)`. +You can also choose to load circuit breaking rules later elsewhere using +`DegradeRuleManager.loadRules(rules)` API of Sentinel, or via Sentinel dashboard. + +===== Reactive Example + +==== +[source,java] +---- +@Bean +public Customizer defaultCustomizer() { + return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id) + .build()); +} +---- +==== + +==== Specific Circuit Breaker Configuration + +Similarly to providing a default configuration, you can create a `Customizer` bean this is passed a +`SentinelCircuitBreakerFactory`. + +==== +[source,java] +---- +@Bean +public Customizer slowCustomizer() { + String slowId = "slow"; + List rules = Collections.singletonList( + new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setCount(100) + .setTimeWindow(10) + ); + return factory -> factory.configure(builder -> builder.rules(rules), slowId); +} +---- +==== + +===== Reactive Example + +==== +[source,java] +---- +@Bean +public Customizer customizer() { + List rules = Collections.singletonList( + new DegradeRule().setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setCount(100) + .setTimeWindow(10) + ); + return factory -> factory.configure(builder -> builder.rules(rules), "foo", "bar"); +} +---- +==== \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc index 3f205fc8..32152f72 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc @@ -16,5 +16,4 @@ If you’re a Maven Central user, add our BOM to your pom.xml ``` -In the following sections, it will be assumed you are using the Spring Cloud Alibaba BOM and the dependency snippets will not contain versions. - +In the following sections, it will be assumed you are using the Spring Cloud Alibaba BOM and the dependency snippets will not contain versions. \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/introduction.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/introduction.adoc index f4c88314..84a83c1f 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/introduction.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/introduction.adoc @@ -1,6 +1,6 @@ == Introduction -Spring Cloud Alibaba aims to provide a one-stop solution for microservices development. This prjoect includes the required components for developing distributed applications and services, so that developers can develop distributed applications easily with the Spring Cloud programming models. +Spring Cloud Alibaba aims to provide a one-stop solution for microservices development. This project includes the required components for developing distributed applications and services, so that developers can develop distributed applications easily with the Spring Cloud programming models. With Spring Cloud Alibaba, you only need to add a few annotations and configurations, and you will be able to use the distributed solutions of Alibaba for your applications, and build a distributed system of your own with Alibaba middleware. @@ -16,4 +16,4 @@ The features of Spring Cloud Alibaba: 8. **Alibaba Cloud SchedulerX**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds. 9. **Alibaba Cloud SMS**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers. -Spring Cloud Alibaba also provide rich https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples[examples]. \ No newline at end of file +Spring Cloud Alibaba also provide rich https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples[examples]. diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/oss.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/oss.adoc new file mode 100644 index 00000000..a44fd72d --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/oss.adoc @@ -0,0 +1,157 @@ +== Spring Cloud Alibaba Cloud OSS + +OSS(Object Storage Service)is a storage product on Alibaba Cloud. Spring Cloud Alibaba Cloud OSS provides the commercialized storage service in conformity with Spring Cloud specifications. We provide easy-to-use APIs and supports the integration of Resource in the Spring framework. + +=== How to Introduce Spring Cloud Alibaba Cloud OSS + +We’ve released Spring Cloud Alibaba version 0.2.1. You will need to add dependency management POM first. + +[source,xml] +---- + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + 0.2.2.BUILD-SNAPSHOT + pom + import + + + +---- + +Next we need to introduce Spring Cloud Alibaba Cloud OSS Starter. + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-oss + +---- + +=== How to Use OSS API + +==== Configure OSS + +Before you start to use Spring Cloud Alibaba Cloud OSS, please add the following configurations in application.properties. + +[source,properties] +---- +spring.cloud.alicloud.access-key=Your Alibaba Cloud AK +spring.cloud.alicloud.secret-key=Your Alibaba Cloud SK +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +---- + +access-key and secret-key is the AK/SK of your Alibaba Cloud account. If you don’t have one, please register an account first, and log on to https://usercenter.console.aliyun.com/#/manage/ak[Alibaba Cloud AK/SK Management] to get your AccessKey ID and Access Key Secret . If you haven’t create the AccessKeys, click “Create AccessKey” to create one. + +For endpoint information, please refer to the OSS https://help.aliyun.com/document_detail/31837.html[Documentation] and get the endpoint for your region. + + +==== Introduce OSS API + +The OSS API of Spring Cloud Alibaba Cloud OSS is based on the official OSS SDK, and includes APIs for uploading, downloading, viewing files. + +Here is a simple application that uses the OSS API. + +[source,java] +---- +@SpringBootApplication +public class OssApplication { + + @Autowired + private OSS ossClient; + + @RequestMapping("/") + public String home() { + ossClient.putObject("bucketName", "fileName", new FileInputStream("/your/local/file/path")); + return "upload success"; + } + + public static void main(String[] args) throws URISyntaxException { + SpringApplication.run(OssApplication.class, args); + } + +} +---- + +Before you upload your files, please https://account.aliyun.com/register/register.htm?spm=5176.8142029.388261.26.e9396d3eaYK2sG&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F[Register an Alibaba Cloud Account]. If you already have one, please https://common-buy.aliyun.com/?spm=5176.8465980.unusable.dopen.4cdf1450rg8Ujb&commodityCode=oss#/open[Sign up for OSS]. + +Log on to the https://oss.console.aliyun.com/overview[OSS Console], click “Create New Bucket” and create a bucket as instructed. Replace the bucket name in the “bucketname” of the previous code with your new bucket name. "fileName” can be any name you like, and "/your/local/file/path” can be any local file path. Next you can run `curl http://127.0.0.1:port number/ to upload your files, and you will see your file on the https://oss.console.aliyun.com/overview[OSS Console]. + +For more instructions on OSS APIs, please refer to https://help.aliyun.com/document_detail/32008.html[OSS SDK Documentation]. + +=== Integrate with the Resource Specifications of Spring + +Spring Cloud Alibaba Cloud OSS integrates the Resource of the Spring framework, which allows you to use the OSS resources easily. + +The following is a simple example of how to use Resource. + +[source,java] +---- +@SpringBootApplication +public class OssApplication { + + @Value("oss://bucketName/fileName") + private Resource file; + + @GetMapping("/file") + public String fileResource() { + try { + return "get file resource success. content: " + StreamUtils.copyToString( + file.getInputStream(), Charset.forName(CharEncoding.UTF_8)); + } catch (Exception e) { + return "get resource fail: " + e.getMessage(); + } + } + + public static void main(String[] args) throws URISyntaxException { + SpringApplication.run(OssApplication.class, args); + } + +} +---- + +NOTE: A prerequisite for the above sample is that you need to have a bucket named “bucketName” on OSS, and you have a file named “fileName” in this bucket. + +=== Use STS Authentication + +In addition to AccessKeys, Spring Cloud Alibaba Cloud OSS also supports STS authentication. STS is an authentication method with temporary security tokens, and is usually used for a third party to access its resources temporarily. + +For a third party to access resources temporarily, it only needs to complete the following configurations. + +[source,properties] +---- +spring.cloud.alicloud.oss.authorization-mode=STS +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +spring.cloud.alicloud.oss.sts.access-key=Your authenticated AK +spring.cloud.alicloud.oss.sts.secret-key=Your authenticated SK +spring.cloud.alicloud.oss.sts.security-token=Your authenticated ST +---- + +Among which, spring.cloud.alicloud.oss.authorization-mode is the enumeration type. Fill in STS here means that STS authentication is used. For endpoint information, refer to the https://help.aliyun.com/document_detail/31837.html[OSS Documentation] and fill in the endpoint for your region. + +Access-key, secret-key and the security-token need to be issued by the authentication side. For more information about STS, refer to https://help.aliyun.com/document_detail/31867.html[STS Documentation]. + +=== More Configurations for the Client + +In addition to basic configurations, Spring Cloud Alibaba Cloud OSS also supports many other configurations, which are also included in the application.properties file. + +Here are some examples. + +[source,properties] +---- +spring.cloud.alicloud.oss.authorization-mode=STS +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +spring.cloud.alicloud.oss.sts.access-key=Your authenticated AK +spring.cloud.alicloud.oss.sts.secret-key=Your authenticated SK +spring.cloud.alicloud.oss.sts.security-token=Your authenticated ST + +spring.cloud.alicloud.oss.config.connection-timeout=3000 +spring.cloud.alicloud.oss.config.max-connections=1000 +---- + +For more configurations, refer to the table at the bottom of https://help.aliyun.com/document_detail/32010.html[OSSClient Configurations]. + +NOTE: In most cases, you need to connect the parameter names with “-” for the parameters in the table of https://help.aliyun.com/document_detail/32010.html[OSSClient Configurations] with “-”, and all letters should be in lowercase. For example, ConnectionTimeout should be changed to connection-timeout. diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc new file mode 100644 index 00000000..38c79c50 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc @@ -0,0 +1,114 @@ +== Spring Cloud Alibaba Cloud SchedulerX + +SchedulerX(Distributed job scheduling) is a component of EDAS, an Alibaba Cloud product. Spring Cloud Alibaba Cloud SchedulerX provides distributed job scheduling in conformity with the Spring Cloud specifications. SchedulerX provides timed job scheduling service with high accuracy with seconds, high stability and high availabiliy, and supports multiple job types, such as simple single-server jobs, simple multi-host jobs, script jobs, and grid jobs. + +=== How to Introduce Spring Cloud Alibaba Cloud SchedulerX + +If you want to use SchedulerX in your project, please use the starter with the group ID as `com.alibaba.cloud` and the artifact ID as `spring-cloud-starter-alicloud-schedulerX`. + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-schedulerX + +---- + +=== Start SchedulerX + +After Spring Cloud Alibaba Cloud SchedulerX Starter is introduced into the client, you only need to complete a few simple configurations and you will be able to initialize the SchedulerX service automatically. + +The following is a simple example. + +[source,java] +---- +@SpringBootApplication +public class ScxApplication { + + public static void main(String[] args) { + SpringApplication.run(ScxApplication.class, args); + } + +} +---- + +Add the following configurations in the application.properties file. + +[source,properties] +---- +server.port=18033 +# cn-test is the test region of SchedulerX +spring.cloud.alicloud.scx.group-id=*** +spring.cloud.alicloud.edas.namespace=cn-test +---- + +Before getting the group-id, please https://account.aliyun.com/register/register.htm?spm=5176.8142029.388261.26.e9396d3eEIv28g&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F[Register an Alibaba Cloud account], and then https://common-buy.aliyun.com/?spm=5176.11451019.0.0.6f5965c0Uq5tue&commodityCode=edaspostpay#/buy[Sign up for EDAS] and https://edas.console.aliyun.com/#/edasTools[Sign up for SchedulerX] as well. + +To get the group-id, refer to the https://help.aliyun.com/document_detail/98784.html[SchedulerX Documentation]. + +NOTE: When you create a group, please select the “test” region. + +=== Compile a simple job + +Simple job is the most commonly used job type. You only need to implement the ScxSimpleJobProcessor interface. + +The following is a sample of a simple single-server job. + +[source,java] +---- +public class SimpleTask implements ScxSimpleJobProcessor { + + @Override + public ProcessResult process(ScxSimpleJobContext context) { + System.out.println("-----------Hello world---------------"); + ProcessResult processResult = new ProcessResult(true); + return processResult; + } + +} +---- + +=== Job Scheduling + +Go to the https://edas.console.aliyun.com/#/edasSchedulerXJob?regionNo=cn-test[SchedulerX Jobs] page, select the “Test” region, and click “Create Job” on the upper-right corner to create a job, as shown below. + +[source,text] +---- +Job Group: Test——***-*-*-**** +Job process interface:SimpleTask +Type: Simple Single-Server Job +Quartz Cron Expression: Default Option——0 * * * * ? +Job Description: Empty +Custom Parameters: Empty +---- + +The job above is a “Simple Single-Server Job”, and speficied a Cron expression of "0 * * * * ?" . This means that the job will be executed once and once only in every minute. + +For more job types, refer to https://help.aliyun.com/document_detail/43136.html[SchedulerX Documentation]. + +=== Usage in Production Environment + +The previous examples shows how to use SchedulerX in the “Test” region, which is mainly used for local testing. + +At the production level, you need to complete some other configurations in addition to the group-id and namespace as mentioned above. See examples below: + +[source,properties] +---- +server.port=18033 +# cn-test is the test region of SchedulerX +spring.cloud.alicloud.scx.group-id=*** +spring.cloud.alicloud.edas.namespace=*** +# If your application runs on EDAS, you do not need to configure the following. +spring.cloud.alicloud.access-key=*** +spring.cloud.alicloud.secret-key=*** +# The following configurations are not mandatory. You can refer to the SchedulerX documentation for details. +spring.cloud.alicloud.scx.domain-name=*** +---- + +The way to get the group-id is the same as described in the previous examples, and you can get the namespace by clicking “Namespaces” in the left-side navigation pane of the EDAS console. + +NOTE: Group-id must be created within a namespace. + +Access-key and secret-key are the AK/SK of your Alibaba Cloud account. If you deploy you applications on EDAS, then you do not need to fill in this information. Otherwise please go to https://usercenter.console.aliyun.com/#/manage/ak[Security Information] to get your AccessKeys. + +Domain-name is not mandatory. You can refer to https://help.aliyun.com/document_detail/35359.html[SchedulerX Documentation] for details. diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc index dffa682c..e0a5622a 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc @@ -301,6 +301,8 @@ If you want to use Sentinel Starter with Spring Cloud Gateway, you need to add t ``` +include::circuitbreaker-sentinel.adoc[] + === Sentinel Endpoint Sentinel provides an Endpoint internally with a corresponding endpoint id of `sentinel`. diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/sms.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/sms.adoc new file mode 100644 index 00000000..f6308fb0 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/sms.adoc @@ -0,0 +1,210 @@ +== Spring Cloud Alibaba Cloud SMS + +SMS(Short Message Service)is a messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers. + +Spring Cloud Alibaba Cloud SMS provide an easier-to-use API for quick access to Alibaba Cloud's SMS service based on Spring Cloud Alibaba SMS. + +=== How to Introduce Spring Cloud Alibaba Cloud SMS + +If you want to use SMS in your project, please use the starter with the group ID as `com.alibaba.cloud` and the artifact ID as `spring-cloud-starter-alicloud-sms`. + +[source,xml] +---- + + com.alibaba.cloud + spring-cloud-starter-alicloud-sms + +---- + +=== How to use SMS API + +==== Configure SMS + +Before you start to use Spring Cloud Alibaba Cloud SMS, please add the following configurations in application.properties. + +[source,properties] +---- +spring.cloud.alicloud.access-key=AK +spring.cloud.alicloud.secret-key=SK +---- + +access-key and secret-key is the AK/SK of your Alibaba Cloud account. If you don’t have one, please register an account first, and log on to https://usercenter.console.aliyun.com/#/manage/ak[Alibaba Cloud AK/SK Management] to get your AccessKey ID and Access Key Secret . If you haven’t create the AccessKeys, click “Create AccessKey” to create one. + +==== Introduce SMS API + +The SMS API in Spring Cloud Alicloud SMS is based on Alibaba Cloud SMS SDK. It has a single SMS sending, multiple SMS bulk sending, SMS query, SMS message (SMS receipt message and Upstream SMS message) class operation API. + +The following is a simple example of how to use SMS api to send short message: + +[source,java] +---- +@SpringBootApplication +public class SmsApplication { + + @Autowired + private ISmsService smsService; + + @RequestMapping("/batch-sms-send.do") + public SendBatchSmsResponse batchsendCheckCode( + @RequestParam(name = "code") String code) { + + SendSmsRequest request = new SendSmsRequest(); + // Required:the mobile number + request.setPhoneNumbers("152******"); + // Required:SMS-SignName-could be found in sms console + request.setSignName("******"); + // Required:Template-could be found in sms console + request.setTemplateCode("******"); + // Required:The param of sms template.For exmaple, if the template is "Hello,your verification code is ${code}". The param should be like following value + request.setTemplateParam("{\"code\":\"" + code + "\"}"); + SendSmsResponse sendSmsResponse ; + try { + sendSmsResponse = smsService.sendSmsRequest(request); + } + catch (ClientException e) { + e.printStackTrace(); + sendSmsResponse = new SendSmsResponse(); + } + return sendSmsResponse ; + } + + public static void main(String[] args) throws URISyntaxException { + SpringApplication.run(SmsApplication.class, args); + } + +} +---- + +Before you send your messages, please https://account.aliyun.com/register/register.htm?spm=5176.8142029.388261.26.e9396d3eaYK2sG&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F[Register an Alibaba Cloud Account]. If you already have one, please https://dysms.console.aliyun.com/dysms.htm?spm=5176.8195934.1283918..18924183bHPct2&accounttraceid=c8cb4243-3080-4eb1-96b0-1f2316584269#/[Turn on SMS Service]. + +For more information about SMS , please refer to the SMS official https://help.aliyun.com/document_detail/55284.html?spm=a2c4g.11186623.6.568.715e4f30ZiVkbI[SMS] (SendSms)---JAVA] docs . + +NOTE: Due to an issue with the earlier SMS sdk version, if the text message fails to be sent, please delete the line of code that contains the explicit MethodType as POST. If you still have problems, please contact us as soon as possible. + +=== The Advanced Features of SMS Api + +In order to reduce the cost of learning, the API interface of the Spring Cloud Alicloud SMS package is kept as consistent as the API and Example provided by the official website. + +* Batch SMS sending + +Refer to the following example to quickly develop a feature with bulk SMS sending. Add the following code in the Controller or create a new Controller: + +[source,java] +---- +@RequestMapping("/batch-sms-send.do") +public SendBatchSmsResponse batchsendCheckCode( + @RequestParam(name = "code") String code) { + SendBatchSmsRequest request = new SendBatchSmsRequest(); + request.setMethod(MethodType.GET); + request.setPhoneNumberJson("[\"177********\",\"130********\"]"); + request.setSignNameJson("[\"*******\",\"*******\"]"); + request.setTemplateCode("******"); + request.setTemplateParamJson( + "[{\"code\":\"" + code + "\"},{\"code\":\"" + code + "\"}]"); + SendBatchSmsResponse sendSmsResponse ; + try { + sendSmsResponse = smsService + .sendSmsBatchRequest(request); + return sendSmsResponse; + } + catch (ClientException e) { + e.printStackTrace(); + sendSmsResponse = new SendBatchSmsResponse(); + } + return sendSmsResponse ; +} +---- + +NOTE: The MethodType of the request is set to GET, which is somewhat different from the example given by the official website. This is because the inconsistent version of the dependent Alibaba Cloud POP API version causes incompatibility issues, set to GET. + +More parameter descriptions can be https://help.aliyun.com/document_detail/66041.html?spm=a2c4g.11186623.6.571.631315e8AauJhP[reference here] + +* SMS Query + +Refer to the following example to quickly develop a history of sending SMS messages based on a specified number. Add the following code in the Controller or create a new Controller: + +[source,java] +---- +@RequestMapping("/query.do") +public QuerySendDetailsResponse querySendDetailsResponse( + @RequestParam(name = "tel") String telephone) { + QuerySendDetailsRequest request = new QuerySendDetailsRequest(); + request.setPhoneNumber(telephone); + request.setSendDate("20190103"); + request.setPageSize(10L); + request.setCurrentPage(1L); + try { + QuerySendDetailsResponse response = smsService.querySendDetails(request); + return response; + } + catch (ClientException e) { + e.printStackTrace(); + } + + return new QuerySendDetailsResponse(); +} + +---- + +More parameter descriptions can be found at https://help.aliyun.com/document_detail/55289.html?spm=a2c4g.11186623.6.569.4f852c78mugEfx[reference here] + +* SMS receipt message + +By subscribing to the SmsReport SMS status report, you can know the status of each SMS message and whether it knows the status and related information of the terminal user. These efforts have been encapsulated internally by Spring Cloud AliCloud SMS. You only need to complete the following two steps. + +1、Configure the queue name for SmsReport in the `application.properties` configuration file (which can also be application.yaml). + +.application.properties +---- +spring.cloud.alicloud.sms.report-queue-name=Alicom-Queue-********-SmsReport +---- + +2、Implement the SmsReportMessageListener interface and initialize a Spring Bean. + +[source,java] +---- +@Component +public class SmsReportMessageListener + implements SmsReportMessageListener { + + @Override + public boolean dealMessage(Message message) { + //do something + System.err.println(this.getClass().getName() + "; " + message.toString()); + return true; + } +} +---- + +More message body format for Message can be https://help.aliyun.com/document_detail/55496.html?spm=a2c4g.11186623.6.570.7f792c78rOiWXO[reference here]. + +* Upstream SMS message + +By subscribing to the SmsUp upstream SMS message, you can know the content of the end user replying to the SMS. These efforts have also been packaged by Spring Cloud AliCloud SMS. You only need to complete the following two steps. + +1、Configure the queue name for SmsReport in the `application.properties` configuration file (which can also be application.yaml). + +.application.properties +[source,properties] +---- +spring.cloud.alicloud.sms.up-queue-name=Alicom-Queue-********-SmsUp +---- + +2、Implement the SmsUpMessageListener interface and initialize a Spring Bean. + +[source,java] +---- +@Component +public class SmsUpMessageListener + implements org.springframework.cloud.alicloud.sms.SmsUpMessageListener { + + @Override + public boolean dealMessage(Message message) { + //do something + System.err.println(this.getClass().getName() + "; " + message.toString()); + return true; + } +} +---- + +More message body format for Message can be https://help.aliyun.com/document_detail/55496.html?spm=a2c4g.11186623.6.570.7f792c78rOiWXO[reference here]. diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/spring-cloud-alibaba.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/spring-cloud-alibaba.adoc index 99d2d3f2..884e0d56 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/spring-cloud-alibaba.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/spring-cloud-alibaba.adoc @@ -20,3 +20,13 @@ include::sentinel.adoc[] include::dubbo.adoc[] include::rocketmq.adoc[] + +include::ans.adoc[] + +include::acm.adoc[] + +include::oss.adoc[] + +include::schedulerx.adoc[] + +include::sms.adoc[] \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md index 2c9441f3..c58f6783 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md @@ -175,7 +175,7 @@ AccessKey|spring.cloud.nacos.config.access-key|| SecretKey|spring.cloud.nacos.config.secret-key|| 相对路径|spring.cloud.nacos.config.context-path||服务端 API 的相对路径 接入点|spring.cloud.nacos.config.endpoint|UTF-8|地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 -是否开启监听和自动刷新|spring.cloud.nacos.config.refresh.enabled|true| +是否开启监听和自动刷新|spring.cloud.nacos.config.refresh-enabled|true| diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md index b415bf8c..797c09cc 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md @@ -25,6 +25,7 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl spring.cloud.nacos.config.server-addr=127.0.0.1:8848 3. After completing the above two steps, the application will get the externalized configuration from Nacos Server and put it in the Spring Environment's PropertySources.We use the @Value annotation to inject the corresponding configuration into the userName and age fields of the SampleController, and add @RefreshScope to turn on dynamic refresh . + @RefreshScope class SampleController { diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties index cea78476..26000aeb 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties @@ -21,5 +21,36 @@ spring.cloud.nacos.config.extension-configs[2].data-id= extension3.json +#spring.cloud.nacos.config.refresh-enabled=true + + + +## nacos-namespace cannot user 'public',cause by 'public' has special handing inside. +#spring.cloud.nacos.config.namespace=public + +## you can specify a custom name if you don't want to use the application name. +#spring.cloud.nacos.config.name=test-aaa +#spring.cloud.nacos.config.file-extension=yaml + +## not recommended. +#spring.cloud.nacos.config.refreshable-dataids=common.properties +## not recommended. +#spring.cloud.nacos.config.shared-data-ids=common.properties,base-common.properties + +## recommended. +spring.cloud.nacos.config.shared-configs[0].data-id= test2.yaml +spring.cloud.nacos.config.shared-configs[0].refresh=true +## the default value is 'DEFAULT_GROUP' , if not specified. +spring.cloud.nacos.config.shared-configs[0].group= GROUP_APP1 + +## not recommended. +#spring.cloud.nacos.config.ext-config[0]=ext.properties +## recommended. +spring.cloud.nacos.config.extension-configs[1].data-id= test1.yml +spring.cloud.nacos.config.extension-configs[1].refresh= true + + + + #spring.cloud.nacos.config.refresh-enabled=true diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties index 9732f8d5..16c0acc9 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties @@ -1,6 +1,7 @@ server.port=18082 spring.application.name=service-provider spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 +#spring.cloud.nacos.discovery.instance-enabled=true spring.cloud.nacos.username=nacos spring.cloud.nacos.password=nacos diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml new file mode 100644 index 00000000..1a18fd18 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/pom.xml @@ -0,0 +1,60 @@ + + + + + com.alibaba.cloud + nacos-discovery-example + ${revision} + + 4.0.0 + + + nacos-reactivediscovery-consumer-example + Spring Cloud Starter Alibaba Nacos Discovery Reactive Example + Example demonstrating how to use nacos discovery + jar + + + + + org.springframework.boot + spring-boot-starter-webflux + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + true + + + + + + diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java new file mode 100644 index 00000000..b69c91b6 --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/java/com/alibaba/cloud/examples/ConsumerReactiveApplication.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.examples; + +import reactor.core.publisher.Mono; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; + +/** + * @author Jim + */ +@SpringBootApplication +public class ConsumerReactiveApplication { + + @Bean + @LoadBalanced + public WebClient.Builder webClient() { + return WebClient.builder(); + } + + public static void main(String[] args) { + SpringApplication.run(ConsumerReactiveApplication.class, args); + } + + @RestController + class MyController { + + @Autowired + private WebClient.Builder webClientBuilder; + + @GetMapping("/service-call/{name}") + public Mono serviceCall(@PathVariable("name") String name) { + return webClientBuilder.build().get() + .uri("http://service-provider/echo/" + name).retrieve() + .bodyToMono(String.class); + } + + } + +} diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties new file mode 100644 index 00000000..4cdd63be --- /dev/null +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-reactivediscovery-consumer-example/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.application.name=service-consumer-reactive +server.port=18083 +management.endpoints.web.exposure.include=* +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 + +spring.cloud.nacos.username=nacos +spring.cloud.nacos.password=nacos + +spring.cloud.loadbalancer.ribbon.enabled=false diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml index 9c29e19b..b67d1373 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml @@ -17,6 +17,7 @@ nacos-discovery-consumer-example + nacos-reactivediscovery-consumer-example nacos-discovery-provider-example nacos-discovery-spring-cloud-config-server-example nacos-discovery-spring-cloud-config-client-example diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md index 2140c5ea..0ad0d23d 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md @@ -30,7 +30,7 @@ public class ProviderApplication { public static void main(String[] args) { - SpringApplication.run(Application.class, args); + SpringApplication.run(ProviderApplication.class, args); } @RestController diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md index 86469101..3bf0cf3a 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md @@ -29,7 +29,7 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl public class ProviderApplication { public static void main(String[] args) { - SpringApplication.run(Application.class, args); + SpringApplication.run(ProviderApplication.class, args); } @RestController @@ -72,7 +72,7 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl #### Query Service -Enter `http://127.0.0.1:8848/nacos/v1/ns/instances?serviceName=service-provider` in the browser address bar and click Go to, we can see that the service node has been successfully registered to Nacos Server. +Enter `http://127.0.0.1:8848/nacos/#/serviceDetail?name=service-provider&groupName=DEFAULT_GROUP` in the browser address bar and click Go to, we can see that the service node has been successfully registered to Nacos Server. ![查询服务](https://cdn.nlark.com/lark/0/2018/png/54319/1536986288092-5cf96af9-9a26-466b-85f6-39ad1d92dfdc.png) @@ -207,6 +207,7 @@ Metadata|spring.cloud.nacos.discovery.metadata||Extended data, Configure using M log name|spring.cloud.nacos.discovery.log-name|| endpoint|spring.cloud.nacos.discovery.endpoint||The domain name of a service, through which the server address can be dynamically obtained. Integration Ribbon|ribbon.nacos.enabled|true| +enabled|spring.cloud.nacos.discovery.enabled|true|The switch to enable or disable nacos service discovery diff --git a/spring-cloud-alibaba-examples/rocketmq-example/readme.md b/spring-cloud-alibaba-examples/rocketmq-example/readme.md index dc9490c6..eec6675f 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/readme.md +++ b/spring-cloud-alibaba-examples/rocketmq-example/readme.md @@ -73,7 +73,7 @@ spring.cloud.stream.bindings.input.group=test-group You should startup Name Server and Broker before using RocketMQ Binder. -1. Download [RocketMQ](https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip) and unzip it. +1. Download [RocketMQ](https://archive.apache.org/dist/rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip) and unzip it. 2. Startup Name Server diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/java/com/alibaba/cloud/examples/RocketMQConsumerApplication.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/java/com/alibaba/cloud/examples/RocketMQConsumerApplication.java index 2bd73880..0458e9ef 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/java/com/alibaba/cloud/examples/RocketMQConsumerApplication.java +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/java/com/alibaba/cloud/examples/RocketMQConsumerApplication.java @@ -74,10 +74,13 @@ public class RocketMQConsumerApplication { while (true) { mySink.input5().poll(m -> { String payload = (String) m.getPayload(); + if(payload.contains("0")){ + throw new IllegalArgumentException("111111111111111111111111111111111111111111"); + } System.out.println("pull msg: " + payload); }, new ParameterizedTypeReference() { }); - Thread.sleep(2_000); + Thread.sleep(5_00); } } diff --git a/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml index 39c89173..86f8dec6 100644 --- a/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml @@ -9,6 +9,7 @@ ../../pom.xml 4.0.0 + account-service Spring Cloud Starter Alibaba Seata Example - Account Service jar @@ -43,7 +44,7 @@ mysql mysql-connector-java - 5.1.31 + 8.0.11 log4j diff --git a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties index d5f73adf..91d6d0c8 100644 --- a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties @@ -5,9 +5,9 @@ spring.cloud.nacos.discovery.server-addr=localhost:8848 spring.datasource.name="accountDataSource" spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://xxx:3306/seata?useSSL=false&serverTimezone=UTC -spring.datasource.username=xxx -spring.datasource.password=xxx +spring.datasource.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC&useUnicode=yes&characterEncoding=UTF-8 +spring.datasource.username=root +spring.datasource.password=qwertyui spring.datasource.druid.max-active=20 spring.datasource.druid.min-idle=2 spring.datasource.druid.initial-size=2 diff --git a/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml index 6ccd456a..95c92df6 100644 --- a/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml @@ -10,7 +10,6 @@ 4.0.0 business-service - Spring Cloud Starter Alibaba Seata Example - Business Service jar diff --git a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties index e1fc1c85..bc40bece 100644 --- a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties @@ -5,6 +5,8 @@ spring.cloud.nacos.discovery.server-addr=localhost:8848 #feign.hystrix.enabled=true #feign.sentinel.enabled=true +feign.client.config.default.connectTimeout=10000 +feign.client.config.default.readTimeout=10000 logging.level.io.seata=debug diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml index a856310d..fd9a12e3 100644 --- a/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml @@ -10,7 +10,7 @@ 4.0.0 order-service - Spring Cloud Starter Alibaba Seata Example - Business Service + Spring Cloud Starter Alibaba Seata Example - Order Service jar @@ -43,7 +43,7 @@ mysql mysql-connector-java - 5.1.31 + 8.0.11 log4j @@ -52,5 +52,5 @@ - - \ No newline at end of file + + diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OderApplication.java b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java similarity index 92% rename from spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OderApplication.java rename to spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java index b1233273..33e31a71 100644 --- a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OderApplication.java +++ b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java @@ -25,10 +25,10 @@ import org.springframework.web.client.RestTemplate; * @author xiaojing */ @SpringBootApplication -public class OderApplication { +public class OrderApplication { public static void main(String[] args) { - SpringApplication.run(OderApplication.class, args); + SpringApplication.run(OrderApplication.class, args); } @Bean diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties index fb4a4b7c..d2b79a5f 100644 --- a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties @@ -5,9 +5,9 @@ spring.cloud.nacos.discovery.server-addr=localhost:8848 spring.datasource.name="orderDataSource" spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://xxx:3306/seata?useSSL=false&serverTimezone=UTC -spring.datasource.username=xxx -spring.datasource.password=xxx +spring.datasource.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC&useUnicode=yes&characterEncoding=UTF-8 +spring.datasource.username=root +spring.datasource.password=qwertyui spring.datasource.druid.max-active=20 spring.datasource.druid.min-idle=2 spring.datasource.druid.initial-size=2 diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml index a2cbdccd..14f90394 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml @@ -42,7 +42,7 @@ mysql mysql-connector-java - 5.1.31 + 8.0.11 log4j diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties index a2bd463a..04548090 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties @@ -5,9 +5,9 @@ spring.cloud.nacos.discovery.server-addr=localhost:8848 spring.datasource.name="storageDataSource" spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://xxx:3306/seata?useSSL=false&serverTimezone=UTC -spring.datasource.username=xxx -spring.datasource.password=xxx +spring.datasource.url=jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC&useUnicode=yes&characterEncoding=UTF-8 +spring.datasource.username=root +spring.datasource.password=qwertyui spring.datasource.druid.max-active=20 spring.datasource.druid.min-idle=2 spring.datasource.druid.initial-size=2 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml index 15e7634e..180dcab7 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml @@ -22,6 +22,11 @@ spring-cloud-starter-alibaba-sentinel + + com.alibaba.cloud + spring-cloud-alibaba-sentinel-datasource + + org.springframework.boot spring-boot-starter-web @@ -35,10 +40,10 @@ spring-boot-starter-thymeleaf - - - - + + com.alibaba.csp + sentinel-datasource-nacos + @@ -51,6 +56,10 @@ + + + + diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties index 16ee4a26..8ce30d81 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties @@ -9,6 +9,18 @@ management.health.diskspace.enabled=false spring.cloud.sentinel.transport.dashboard=localhost:8080 spring.cloud.sentinel.eager=true +spring.cloud.sentinel.web-context-unify=true + +#spring.cloud.sentinel.block-page=/errorPage +#spring.cloud.sentinel.filter.enabled=false +#spring.cloud.sentinel.http-method-specify=false + +#spring.cloud.sentinel.datasource.ds6.nacos.server-addr=127.0.0.1:8848 +#spring.cloud.sentinel.datasource.ds6.nacos.username=nacos +#spring.cloud.sentinel.datasource.ds6.nacos.password=nacos +#spring.cloud.sentinel.datasource.ds6.nacos.dataId=flowrule.json +#spring.cloud.sentinel.datasource.ds6.nacos.data-type=json +#spring.cloud.sentinel.datasource.ds6.nacos.rule-type=flow #spring.cloud.sentinel.block-page=/errorPage #spring.cloud.sentinel.filter.enabled=false diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml index 380b6485..fb0b8329 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml @@ -31,7 +31,7 @@ com.alibaba.cloud sentinel-dubbo-api - ${revision} + ${project.version} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml index 82e048c5..52334958 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml @@ -31,7 +31,7 @@ com.alibaba.cloud sentinel-dubbo-api - ${revision} + ${project.version} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/pom.xml index bf6b8743..51c7096f 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/pom.xml @@ -59,4 +59,5 @@ + diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/fallback/EchoServiceFallback.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/fallback/EchoServiceFallback.java index 055521c5..2e6a9aab 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/fallback/EchoServiceFallback.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/fallback/EchoServiceFallback.java @@ -34,7 +34,7 @@ public class EchoServiceFallback implements EchoService { /** * 调用服务提供方的输出接口. * @param str 用户输入 - * @return response + * @return String */ @Override public String echo(String str) { diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/service/EchoService.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/service/EchoService.java index 417eff79..0745d15d 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/service/EchoService.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/java/com/alibaba/cloud/examples/service/EchoService.java @@ -27,7 +27,8 @@ import org.springframework.web.bind.annotation.PathVariable; *

* example feign client */ -@FeignClient(name = "service-provider", fallbackFactory = EchoServiceFallbackFactory.class) +@FeignClient(name = "service-provider", + fallbackFactory = EchoServiceFallbackFactory.class) public interface EchoService { /** diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/MyConfiguration.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/MyConfiguration.java deleted file mode 100644 index c02f8c87..00000000 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/MyConfiguration.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.examples; - -import com.alibaba.csp.sentinel.adapter.spring.webflux.callback.BlockRequestHandler; -import reactor.core.publisher.Mono; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.server.ServerResponse; -import org.springframework.web.server.ServerWebExchange; - -import static org.springframework.web.reactive.function.BodyInserters.fromObject; - -/** - * @author Jim - */ -@Configuration -public class MyConfiguration { - - @Bean - public BlockRequestHandler blockRequestHandler() { - return new BlockRequestHandler() { - @Override - public Mono handleRequest(ServerWebExchange exchange, - Throwable t) { - return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS) - .contentType(MediaType.APPLICATION_JSON).body(fromObject("block")); - } - }; - } - -} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/SentinelWebFluxController.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/SentinelWebFluxController.java deleted file mode 100644 index 5bf96332..00000000 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-webflux-example/src/main/java/com/alibaba/cloud/examples/SentinelWebFluxController.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.examples; - -import com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Jim - */ -@RestController -public class SentinelWebFluxController { - - @GetMapping("/mono") - public Mono mono() { - return Mono.just("simple string") - // transform the publisher here. - .transform(new SentinelReactorTransformer<>("mono")); - } - - @GetMapping("/test") - public Mono test() { - return Mono.just("simple string") - // transform the publisher here. - .transform(new SentinelReactorTransformer<>("test")); - } - - @GetMapping("/flux") - public Flux flux() { - return Flux.fromArray(new String[] { "a", "b", "c" }) - // transform the publisher here. - .transform(new SentinelReactorTransformer<>("flux")); - } - -} diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/com/alibaba/cloud/examples/ZuulConfiguration.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/com/alibaba/cloud/examples/ZuulConfiguration.java index d3e1ffea..9dccb6b2 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/com/alibaba/cloud/examples/ZuulConfiguration.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-zuul-example/src/main/java/com/alibaba/cloud/examples/ZuulConfiguration.java @@ -41,10 +41,10 @@ public class ZuulConfiguration { @Override public BlockResponse fallbackResponse(String route, Throwable cause) { - if (route.equals("my-service3")) { + if ("my-service3".equals(route)) { return new BlockResponse(433, "Sentinel Block3", route); } - else if (route.equals("my-service4")) { + else if ("my-service4".equals(route)) { return new BlockResponse(444, "my-service4", route); } else { diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml index 1af3a87e..a05830c7 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml @@ -20,7 +20,7 @@ com.alibaba.cloud spring-cloud-dubbo-sample-api - ${revision} + ${project.version} diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudClientBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudClientBootstrap.java index 5171d48f..f6df9283 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudClientBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudClientBootstrap.java @@ -27,6 +27,8 @@ import org.springframework.web.bind.annotation.RestController; /** * Dubbo Spring Cloud Client Bootstrap. + * + * @author Mercy */ @EnableDiscoveryClient @EnableAutoConfiguration diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml index 5146a6d5..6801b6c4 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml @@ -1,6 +1,9 @@ dubbo: cloud: subscribed-services: spring-cloud-alibaba-dubbo-server + protocols: + dubbo: + port: -1 spring: application: diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java index 000859ca..37b162d5 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java @@ -52,6 +52,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; /** * Dubbo Spring Cloud Consumer Bootstrap. + * + * @author Mercy */ @EnableDiscoveryClient @EnableAutoConfiguration @@ -60,7 +62,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @EnableCaching public class DubboSpringCloudConsumerBootstrap { - @Reference + + @Reference(protocol = "dubbo") private UserService userService; @Reference(version = "1.0.0", protocol = "dubbo") diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml index c46f7a87..456836fe 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml @@ -1,4 +1,5 @@ dubbo: + registry: # The Spring Cloud Dubbo's registry extension ## the default value of dubbo-provider-services is "*", that means to subscribe all providers, diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/bootstrap.yaml index e753ea0e..c4b583a8 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/bootstrap.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/bootstrap.yaml @@ -8,6 +8,8 @@ spring: # default disable all cloud: nacos: + username: nacos + password: nacos discovery: enabled: false register-enabled: false diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml index 94c90ccb..99a529b7 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml @@ -42,7 +42,6 @@ - com.alibaba.cloud diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java index 286e2d2b..2421c755 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java @@ -23,6 +23,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * Dubbo Spring Cloud Provider Bootstrap. + * + * @author Mercy */ @EnableDiscoveryClient @EnableAutoConfiguration diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/InMemoryUserService.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/InMemoryUserService.java index bd11c413..37297839 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/InMemoryUserService.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/InMemoryUserService.java @@ -25,6 +25,8 @@ import org.apache.dubbo.config.annotation.Service; /** * In-Memory {@link UserService} implementation. */ +// @Path("/") +// @Service(version = "1.0.0", protocol = "dubbo") @Service(protocol = "dubbo") public class InMemoryUserService implements UserService { diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/StandardRestService.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/StandardRestService.java index a71cc193..64ef0afd 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/StandardRestService.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/com/alibaba/cloud/dubbo/service/StandardRestService.java @@ -42,8 +42,9 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE; * * @author Mercy */ -@Service(version = "1.0.0", protocol = { "dubbo", "rest" }) + @Path("/") +@Service(version = "1.0.0", protocol = { "dubbo", "rest" }) public class StandardRestService implements RestService { private Logger logger = LoggerFactory.getLogger(getClass()); diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/application.yaml index 1a7ec7c5..5a855843 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/application.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/application.yaml @@ -9,11 +9,6 @@ dubbo: name: rest port: 9090 server: netty - registry: -# The Spring Cloud Dubbo's registry extension - address: spring-cloud://localhost -# The traditional Dubbo's registry -# address: zookeeper://127.0.0.1:2181 feign: hystrix: enabled: true \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/bootstrap.yaml index 8f56b284..7efde94a 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/bootstrap.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/resources/bootstrap.yaml @@ -33,6 +33,7 @@ spring: enabled: true register-enabled: true server-addr: 127.0.0.1:8848 + ephemeral: false --- diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/pom.xml index 99f9498f..d434ebb1 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/pom.xml @@ -30,7 +30,7 @@ com.alibaba.cloud spring-cloud-dubbo-sample-api - ${revision} + ${project.version} diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudWebProviderBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudWebProviderBootstrap.java index ab456ccc..d13733c3 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudWebProviderBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudWebProviderBootstrap.java @@ -22,6 +22,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * Dubbo Spring Cloud Provider Bootstrap. + * + * @author Mercy */ @EnableDiscoveryClient @EnableAutoConfiguration diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/application.yaml index b6858c74..f4115cf6 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/application.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/application.yaml @@ -3,7 +3,6 @@ dubbo: base-packages: com.alibaba.cloud.dubbo.service protocols: dubbo: - name: dubbo port: -1 registries: new: diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/bootstrap.yaml index 8f56b284..057185f9 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/bootstrap.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-web-sample/src/main/resources/bootstrap.yaml @@ -8,6 +8,8 @@ spring: # default disable all cloud: nacos: + username: nacos + password: nacos discovery: enabled: false register-enabled: false diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServerBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServerBootstrap.java index bd7e1784..3ded18dd 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServerBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServerBootstrap.java @@ -25,6 +25,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /** * Dubbo Spring Cloud Server Bootstrap. + * + * @author Mercy */ @EnableDiscoveryClient @EnableAutoConfiguration diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml index ea10b540..2503c1b0 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml @@ -15,6 +15,12 @@ + + com.alibaba.cloud + spring-cloud-alibaba-commons + ${project.version} + + org.springframework.boot spring-boot-starter-web @@ -29,7 +35,7 @@ com.alibaba.cloud spring-cloud-dubbo-sample-api - ${revision} + ${project.version} diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java index face2b41..9aaab1fe 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java @@ -24,6 +24,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients; /** * Dubbo Spring Cloud Servlet Gateway Bootstrap. + * + * @author Mercy */ @EnableDiscoveryClient @EnableAutoConfiguration diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java index 8fe7f25d..2cfb8db0 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java @@ -52,8 +52,8 @@ import org.springframework.util.StreamUtils; import org.springframework.web.servlet.HttpServletBean; import org.springframework.web.util.UriComponents; -import static org.apache.commons.lang3.StringUtils.substringAfter; -import static org.apache.commons.lang3.StringUtils.substringBetween; +import static com.alibaba.cloud.commons.lang.StringUtils.substringAfter; +import static com.alibaba.cloud.commons.lang.StringUtils.substringBetween; import static org.springframework.web.util.UriComponentsBuilder.fromUriString; @WebServlet(urlPatterns = "/dsc/*") diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/pom.xml index 690d2031..16cf0b87 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/pom.xml @@ -20,6 +20,13 @@ org.springframework.boot spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-gateway + + + org.springframework.boot spring-boot-starter-web @@ -33,6 +40,7 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery + io.projectreactor reactor-core diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/src/main/resources/application.yml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/src/main/resources/application.yml index 51550341..87702ce2 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/src/main/resources/application.yml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/src/main/resources/application.yml @@ -7,10 +7,12 @@ spring: password: nacos discovery: server-addr: localhost:8848 + group: test gateway: discovery: locator: enabled: true + application: name: node-service sidecar: diff --git a/spring-cloud-alibaba-starters/pom.xml b/spring-cloud-alibaba-starters/pom.xml index eb63bf60..20ce67a7 100644 --- a/spring-cloud-alibaba-starters/pom.xml +++ b/spring-cloud-alibaba-starters/pom.xml @@ -22,10 +22,12 @@ spring-cloud-starter-stream-rocketmq spring-cloud-starter-bus-rocketmq spring-cloud-starter-dubbo - spring-cloud-starter-alibaba-sidecar + spring-cloud-starter-alibaba-sentinel spring-cloud-alibaba-sentinel-datasource spring-cloud-alibaba-sentinel-gateway + + spring-cloud-alibaba-commons diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml new file mode 100644 index 00000000..73248d29 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml @@ -0,0 +1,18 @@ + + + + com.alibaba.cloud + spring-cloud-alibaba-starters + ${revision} + ../pom.xml + + + 4.0.0 + + spring-cloud-alibaba-commons + Spring Cloud Alibaba Commons + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/Charsets.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/Charsets.java new file mode 100644 index 00000000..f15ff0e6 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/Charsets.java @@ -0,0 +1,182 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.commons.io; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * The Charsets constants, copy from apache commons-io. + * + * @author theonefx + */ +public final class Charsets { + + private Charsets() { + } + + /** + * Constructs a sorted map from canonical charset names to charset objects required of + * every implementation of the Java platform. + *

+ * From the Java documentation + * + * Standard charsets: + *

+ * @return An immutable, case-insensitive map from canonical charset names to charset + * objects. + * @see Charset#availableCharsets() + */ + public static SortedMap requiredCharsets() { + // maybe cache? + final TreeMap m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + m.put(StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1); + m.put(StandardCharsets.US_ASCII.name(), StandardCharsets.US_ASCII); + m.put(StandardCharsets.UTF_16.name(), StandardCharsets.UTF_16); + m.put(StandardCharsets.UTF_16BE.name(), StandardCharsets.UTF_16BE); + m.put(StandardCharsets.UTF_16LE.name(), StandardCharsets.UTF_16LE); + m.put(StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8); + return Collections.unmodifiableSortedMap(m); + } + + /** + * Returns the given Charset or the default Charset if the given Charset is null. + * @param charset A charset or null. + * @return the given Charset or the default Charset if the given Charset is null + */ + public static Charset toCharset(final Charset charset) { + return charset == null ? Charset.defaultCharset() : charset; + } + + /** + * Returns a Charset for the named charset. If the name is null, return the default + * Charset. + * @param charset The name of the requested charset, may be null. + * @return a Charset for the named charset + * @throws java.nio.charset.UnsupportedCharsetException If the named charset is + * unavailable + */ + public static Charset toCharset(final String charset) { + return charset == null ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1. + *

+ * Every implementation of the Java platform is required to support this character + * encoding. + *

+ * + * @see Standard + * charsets + * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} + */ + @Deprecated + public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1; + + /** + *

+ * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of + * the Unicode character set. + *

+ *

+ * Every implementation of the Java platform is required to support this character + * encoding. + *

+ * + * @see Standard + * charsets + * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} + */ + @Deprecated + public static final Charset US_ASCII = StandardCharsets.US_ASCII; + + /** + *

+ * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory + * initial byte-order mark (either order accepted on input, big-endian used on output) + *

+ *

+ * Every implementation of the Java platform is required to support this character + * encoding. + *

+ * + * @see Standard + * charsets + * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} + */ + @Deprecated + public static final Charset UTF_16 = StandardCharsets.UTF_16; + + /** + *

+ * Sixteen-bit Unicode Transformation Format, big-endian byte order. + *

+ *

+ * Every implementation of the Java platform is required to support this character + * encoding. + *

+ * + * @see Standard + * charsets + * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} + */ + @Deprecated + public static final Charset UTF_16BE = StandardCharsets.UTF_16BE; + + /** + *

+ * Sixteen-bit Unicode Transformation Format, little-endian byte order. + *

+ *

+ * Every implementation of the Java platform is required to support this character + * encoding. + *

+ * + * @see Standard + * charsets + * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} + */ + @Deprecated + public static final Charset UTF_16LE = StandardCharsets.UTF_16LE; + + /** + *

+ * Eight-bit Unicode Transformation Format. + *

+ *

+ * Every implementation of the Java platform is required to support this character + * encoding. + *

+ * + * @see Standard + * charsets + * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets} + */ + @Deprecated + public static final Charset UTF_8 = StandardCharsets.UTF_8; + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java new file mode 100644 index 00000000..0635edce --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java @@ -0,0 +1,113 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.commons.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +/** + * FileUtils. copy from apache commons-io. + * + * @author theonefx + */ +public final class FileUtils { + + private FileUtils() { + } + + // ----------------------------------------------------------------------- + /** + * Opens a {@link java.io.FileInputStream} for the specified file, providing better + * error messages than simply calling new FileInputStream(file). + *

+ * At the end of the method either the stream will be successfully opened, or an + * exception will have been thrown. + *

+ * An exception is thrown if the file does not exist. An exception is thrown if the + * file object exists but is a directory. An exception is thrown if the file exists + * but cannot be read. + * @param file the file to open for input, must not be {@code null} + * @return a new {@link java.io.FileInputStream} for the specified file + * @throws java.io.FileNotFoundException if the file does not exist + * @throws IOException if the file object is a directory + * @throws IOException if the file cannot be read + * @since 1.3 + */ + public static FileInputStream openInputStream(final File file) throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (!file.canRead()) { + throw new IOException("File '" + file + "' cannot be read"); + } + } + else { + throw new FileNotFoundException("File '" + file + "' does not exist"); + } + return new FileInputStream(file); + } + + // ----------------------------------------------------------------------- + /** + * Reads the contents of a file into a String. The file is always closed. + * @param file the file to read, must not be {@code null} + * @param encoding the encoding to use, {@code null} means platform default + * @return the file contents, never {@code null} + * @throws IOException in case of an I/O error + */ + public static String readFileToString(final File file, final Charset encoding) + throws IOException { + try (InputStream in = openInputStream(file)) { + return IOUtils.toString(in, Charsets.toCharset(encoding)); + } + } + + /** + * Reads the contents of a file into a String. The file is always closed. + * @param file the file to read, must not be {@code null} + * @param encoding the encoding to use, {@code null} means platform default + * @return the file contents, never {@code null} + * @throws java.io.IOException in case of an I/O error + * @throws java.nio.charset.UnsupportedCharsetException thrown instead of + * {@link java.io .UnsupportedEncodingException} in version 2.2 if the encoding is not + * supported. + */ + public static String readFileToString(final File file, final String encoding) + throws IOException { + return readFileToString(file, Charsets.toCharset(encoding)); + } + + /** + * Reads the contents of a file into a String using the default encoding for the VM. + * The file is always closed. + * @param file the file to read, must not be {@code null} + * @return the file contents, never {@code null} + * @throws IOException in case of an I/O error + * @deprecated 2.5 use {@link #readFileToString(File, String)} instead (and specify + * the appropriate encoding) + */ + @Deprecated + public static String readFileToString(final File file) throws IOException { + return readFileToString(file, Charset.defaultCharset()); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java new file mode 100644 index 00000000..85f61c5d --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java @@ -0,0 +1,233 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.commons.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * The IOUtils. copy from apache commons-io. + * + * @author theonefx + */ +public final class IOUtils { + + /** + * Represents the end-of-file (or stream). + * @since 2.5 (made public) + */ + public static final int EOF = -1; + + /** + * The default buffer size ({@value}) to use for. + * {@link #copyLarge(InputStream, java.io.OutputStream)} and + * {@link #copyLarge(Reader, Writer)} + */ + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + private IOUtils() { + + } + + /** + * Gets the contents of an InputStream as a String using the specified + * character encoding. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

+ * @param input the InputStream to read from + * @param encoding the encoding to use, null means platform default + * @return the requested String + * @throws NullPointerException if the input is null + * @throws java.io.IOException if an I/O error occurs + * @since 2.3 + */ + public static String toString(final InputStream input, final Charset encoding) + throws IOException { + try (StringBuilderWriter sw = new StringBuilderWriter()) { + copy(input, sw, encoding); + return sw.toString(); + } + } + + // copy from Reader + // ----------------------------------------------------------------------- + + /** + * Copies chars from a Reader to a Writer. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

+ * Large streams (over 2GB) will return a chars copied value of -1 after + * the copy has completed since the correct number of chars cannot be returned as an + * int. For large streams use the copyLarge(Reader, Writer) method. + * @param input the Reader to read from + * @param output the Writer to write to + * @return the number of characters copied, or -1 if > Integer.MAX_VALUE + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.1 + */ + public static int copy(final Reader input, final Writer output) throws IOException { + final long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + /** + * Copies bytes from an InputStream to chars on a Writer + * using the specified character encoding. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

+ * This method uses {@link java.io.InputStreamReader}. + * @param input the InputStream to read from + * @param output the Writer to write to + * @param inputEncoding the encoding to use for the input stream, null means platform + * default + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.3 + */ + public static void copy(final InputStream input, final Writer output, + final Charset inputEncoding) throws IOException { + final InputStreamReader in = new InputStreamReader(input, + Charsets.toCharset(inputEncoding)); + copy(in, output); + } + + /** + * Copies bytes from an InputStream to an OutputStream using + * an internal buffer of the given size. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

+ * @param input the InputStream to read from + * @param output the OutputStream to write to + * @param bufferSize the bufferSize used to copy from the input to the output + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.5 + */ + public static long copy(final InputStream input, final OutputStream output, + final int bufferSize) throws IOException { + return copyLarge(input, output, new byte[bufferSize]); + } + + /** + * Copies chars from a large (over 2GB) Reader to a Writer. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedReader. + *

+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * @param input the Reader to read from + * @param output the Writer to write to + * @return the number of characters copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.3 + */ + public static long copyLarge(final Reader input, final Writer output) + throws IOException { + return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]); + } + + /** + * Copies chars from a large (over 2GB) Reader to a Writer. + *

+ * This method uses the provided buffer, so there is no need to use a + * BufferedReader. + *

+ * @param input the Reader to read from + * @param output the Writer to write to + * @param buffer the buffer to be used for the copy + * @return the number of characters copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(final Reader input, final Writer output, + final char[] buffer) throws IOException { + long count = 0; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + /** + * Copies bytes from a large (over 2GB) InputStream to an + * OutputStream. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + *

+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}. + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 1.3 + */ + public static long copyLarge(final InputStream input, final OutputStream output) + throws IOException { + return copy(input, output, DEFAULT_BUFFER_SIZE); + } + + /** + * Copies bytes from a large (over 2GB) InputStream to an + * OutputStream. + *

+ * This method uses the provided buffer, so there is no need to use a + * BufferedInputStream. + *

+ * @param input the InputStream to read from + * @param output the OutputStream to write to + * @param buffer the buffer to use for the copy + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since 2.2 + */ + public static long copyLarge(final InputStream input, final OutputStream output, + final byte[] buffer) throws IOException { + long count = 0; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java new file mode 100644 index 00000000..9a057816 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java @@ -0,0 +1,152 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.commons.io; + +import java.io.Serializable; +import java.io.Writer; + +/** + * Copy from apache commons-io. + * + * @author theonefx + */ +public class StringBuilderWriter extends Writer implements Serializable { + + private static final long serialVersionUID = -146927496096066153L; + + private final StringBuilder builder; + + /** + * Constructs a new {@link StringBuilder} instance with default capacity. + */ + public StringBuilderWriter() { + this.builder = new StringBuilder(); + } + + /** + * Constructs a new {@link StringBuilder} instance with the specified capacity. + * @param capacity The initial capacity of the underlying {@link StringBuilder} + */ + public StringBuilderWriter(final int capacity) { + this.builder = new StringBuilder(capacity); + } + + /** + * Constructs a new instance with the specified {@link StringBuilder}. + * + *

+ * If {@code builder} is null a new instance with default capacity will be created. + *

+ * @param builder The String builder. May be null. + */ + public StringBuilderWriter(final StringBuilder builder) { + this.builder = builder != null ? builder : new StringBuilder(); + } + + /** + * Appends a single character to this Writer. + * @param value The character to append + * @return This writer instance + */ + @Override + public Writer append(final char value) { + builder.append(value); + return this; + } + + /** + * Appends a character sequence to this Writer. + * @param value The character to append + * @return This writer instance + */ + @Override + public Writer append(final CharSequence value) { + builder.append(value); + return this; + } + + /** + * Appends a portion of a character sequence to the {@link StringBuilder}. + * @param value The character to append + * @param start The index of the first character + * @param end The index of the last character + 1 + * @return This writer instance + */ + @Override + public Writer append(final CharSequence value, final int start, final int end) { + builder.append(value, start, end); + return this; + } + + /** + * Closing this writer has no effect. + */ + @Override + public void close() { + // no-op + } + + /** + * Flushing this writer has no effect. + */ + @Override + public void flush() { + // no-op + } + + /** + * Writes a String to the {@link StringBuilder}. + * @param value The value to write + */ + @Override + public void write(final String value) { + if (value != null) { + builder.append(value); + } + } + + /** + * Writes a portion of a character array to the {@link StringBuilder}. + * @param value The value to write + * @param offset The index of the first character + * @param length The number of characters to write + */ + @Override + public void write(final char[] value, final int offset, final int length) { + if (value != null) { + builder.append(value, offset, length); + } + } + + /** + * Returns the underlying builder. + * @return The underlying builder + */ + public StringBuilder getBuilder() { + return builder; + } + + /** + * Returns {@link StringBuilder#toString()}. + * @return The contents of the String builder. + */ + @Override + public String toString() { + return builder.toString(); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/StringUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/StringUtils.java new file mode 100644 index 00000000..d9c15136 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/StringUtils.java @@ -0,0 +1,372 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.commons.lang; + +/** + * StringUtils. copy from apache common-lang3. + * + * @author theonefx + */ +public final class StringUtils { + + /** + * The empty String {@code ""}. + * + * @since 2.0 + */ + public static final String EMPTY = ""; + + /** + * Represents a failed index search. + * @since 2.1 + */ + public static final int INDEX_NOT_FOUND = -1; + + private StringUtils() { + } + + /** + *

+ * Checks if a CharSequence is empty ("") or null. + *

+ * + *
+	 * StringUtils.isEmpty(null)      = true
+	 * StringUtils.isEmpty("")        = true
+	 * StringUtils.isEmpty(" ")       = false
+	 * StringUtils.isEmpty("bob")     = false
+	 * StringUtils.isEmpty("  bob  ") = false
+	 * 
+ * + *

+ * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. + * That functionality is available in isBlank(). + *

+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is empty or null + * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) + */ + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } + + /** + *

+ * Checks if a CharSequence is not empty ("") and not null. + *

+ * + *
+	 * StringUtils.isNotEmpty(null)      = false
+	 * StringUtils.isNotEmpty("")        = false
+	 * StringUtils.isNotEmpty(" ")       = true
+	 * StringUtils.isNotEmpty("bob")     = true
+	 * StringUtils.isNotEmpty("  bob  ") = true
+	 * 
+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is not empty and not null + * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) + */ + public static boolean isNotEmpty(final CharSequence cs) { + return !isEmpty(cs); + } + + /** + *

+ * Checks if a CharSequence is whitespace, empty ("") or null. + *

+ * + *
+	 * StringUtils.isBlank(null)      = true
+	 * StringUtils.isBlank("")        = true
+	 * StringUtils.isBlank(" ")       = true
+	 * StringUtils.isBlank("bob")     = false
+	 * StringUtils.isBlank("  bob  ") = false
+	 * 
+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is null, empty or whitespace + */ + public static boolean isBlank(final CharSequence cs) { + if (cs == null || cs.length() == 0) { + return true; + } + int strLen = cs.length(); + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + return true; + } + + /** + *

+ * Checks if a CharSequence is not empty (""), not null and not whitespace only. + *

+ * + *

+ * Whitespace is defined by {@link Character#isWhitespace(char)}. + *

+ * + *
+	 * StringUtils.isNotBlank(null)      = false
+	 * StringUtils.isNotBlank("")        = false
+	 * StringUtils.isNotBlank(" ")       = false
+	 * StringUtils.isNotBlank("bob")     = true
+	 * StringUtils.isNotBlank("  bob  ") = true
+	 * 
+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is not empty and not null and not + * whitespace only + * @since 2.0 + * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) + */ + public static boolean isNotBlank(final CharSequence cs) { + return !isBlank(cs); + } + + // Trim + // ----------------------------------------------------------------------- + + /** + *

+ * Removes control characters (char <= 32) from both ends of this String, handling + * {@code null} by returning {@code null}. + *

+ * + *

+ * The String is trimmed using {@link String#trim()}. Trim removes start and end + * characters <= 32. + *

+ * + *
+	 * StringUtils.trim(null)          = null
+	 * StringUtils.trim("")            = ""
+	 * StringUtils.trim("     ")       = ""
+	 * StringUtils.trim("abc")         = "abc"
+	 * StringUtils.trim("    abc    ") = "abc"
+	 * 
+ * @param str the String to be trimmed, may be null + * @return the trimmed string, {@code null} if null String input + */ + public static String trim(final String str) { + return str == null ? null : str.trim(); + } + + // Equals + // ----------------------------------------------------------------------- + + /** + *

+ * Compares two CharSequences, returning {@code true} if they represent equal + * sequences of characters. + *

+ * + *

+ * {@code null}s are handled without exceptions. Two {@code null} references are + * considered to be equal. The comparison is case sensitive. + *

+ * + *
+	 * StringUtils.equals(null, null)   = true
+	 * StringUtils.equals(null, "abc")  = false
+	 * StringUtils.equals("abc", null)  = false
+	 * StringUtils.equals("abc", "abc") = true
+	 * StringUtils.equals("abc", "ABC") = false
+	 * 
+ * @param cs1 the first CharSequence, may be {@code null} + * @param cs2 the second CharSequence, may be {@code null} + * @return {@code true} if the CharSequences are equal (case-sensitive), or both + * {@code null} + * @see Object#equals(Object) + */ + public static boolean equals(final CharSequence cs1, final CharSequence cs2) { + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null) { + return false; + } + if (cs1 instanceof String && cs2 instanceof String) { + return cs1.equals(cs2); + } + return StringUtils.regionMatches(cs1, false, 0, cs2, 0, + Math.max(cs1.length(), cs2.length())); + } + + /** + * Green implementation of regionMatches. + * @param cs the {@code CharSequence} to be processed + * @param ignoreCase whether or not to be case insensitive + * @param thisStart the index to start on the {@code cs} CharSequence + * @param substring the {@code CharSequence} to be looked for + * @param start the index to start on the {@code substring} CharSequence + * @param length character length of the region + * @return whether the region matched + */ + public static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, + final int thisStart, final CharSequence substring, final int start, + final int length) { + if (cs instanceof String && substring instanceof String) { + return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, + start, length); + } + int index1 = thisStart; + int index2 = start; + int tmpLen = length; + + while (tmpLen-- > 0) { + final char c1 = cs.charAt(index1++); + final char c2 = substring.charAt(index2++); + + if (c1 == c2) { + continue; + } + + if (!ignoreCase) { + return false; + } + + // The same check as in String.regionMatches(): + if (Character.toUpperCase(c1) != Character.toUpperCase(c2) + && Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + return false; + } + } + + return true; + } + + /** + *

+ * Gets the substring after the first occurrence of a separator. The separator is not + * returned. + *

+ * + *

+ * A null string input will return null. An empty ("") + * string input will return the empty string. A null separator will + * return the empty string if the input string is not null. + *

+ * + *

+ * If nothing is found, the empty string is returned. + *

+ * + *
+	 * StringUtils.substringAfter(null, *)      = null
+	 * StringUtils.substringAfter("", *)        = ""
+	 * StringUtils.substringAfter(*, null)      = ""
+	 * StringUtils.substringAfter("abc", "a")   = "bc"
+	 * StringUtils.substringAfter("abcba", "b") = "cba"
+	 * StringUtils.substringAfter("abc", "c")   = ""
+	 * StringUtils.substringAfter("abc", "d")   = ""
+	 * StringUtils.substringAfter("abc", "")    = "abc"
+	 * 
+ * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring after the first occurrence of the separator, + * null if null String input + * @since 2.0 + */ + public static String substringAfter(String str, String separator) { + if (isEmpty(str)) { + return str; + } + if (separator == null) { + return EMPTY; + } + int pos = str.indexOf(separator); + if (pos == INDEX_NOT_FOUND) { + return EMPTY; + } + return str.substring(pos + separator.length()); + } + + // Substring between + // ----------------------------------------------------------------------- + /** + *

+ * Gets the String that is nested in between two instances of the same String. + *

+ * + *

+ * A null input String returns null. A null tag + * returns null. + *

+ * + *
+	 * StringUtils.substringBetween(null, *)            = null
+	 * StringUtils.substringBetween("", "")             = ""
+	 * StringUtils.substringBetween("", "tag")          = null
+	 * StringUtils.substringBetween("tagabctag", null)  = null
+	 * StringUtils.substringBetween("tagabctag", "")    = ""
+	 * StringUtils.substringBetween("tagabctag", "tag") = "abc"
+	 * 
+ * @param str the String containing the substring, may be null + * @param tag the String before and after the substring, may be null + * @return the substring, null if no match + * @since 2.0 + */ + public static String substringBetween(String str, String tag) { + return substringBetween(str, tag, tag); + } + + /** + *

+ * Gets the String that is nested in between two Strings. Only the first match is + * returned. + *

+ * + *

+ * A null input String returns null. A null + * open/close returns null (no match). An empty ("") open and close + * returns an empty string. + *

+ * + *
+	 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
+	 * StringUtils.substringBetween(null, *, *)          = null
+	 * StringUtils.substringBetween(*, null, *)          = null
+	 * StringUtils.substringBetween(*, *, null)          = null
+	 * StringUtils.substringBetween("", "", "")          = ""
+	 * StringUtils.substringBetween("", "", "]")         = null
+	 * StringUtils.substringBetween("", "[", "]")        = null
+	 * StringUtils.substringBetween("yabcz", "", "")     = ""
+	 * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
+	 * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
+	 * 
+ * @param str the String containing the substring, may be null + * @param open the String before the substring, may be null + * @param close the String after the substring, may be null + * @return the substring, null if no match + * @since 2.0 + */ + public static String substringBetween(String str, String open, String close) { + if (str == null || open == null || close == null) { + return null; + } + int start = str.indexOf(open); + if (start != INDEX_NOT_FOUND) { + int end = str.indexOf(close, start + open.length()); + if (end != INDEX_NOT_FOUND) { + return str.substring(start + open.length(), end); + } + } + return null; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml index 3316d7bd..5d537b85 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -17,23 +17,6 @@ - - org.springframework.boot - spring-boot-configuration-processor - true - - - - org.springframework.boot - spring-boot - true - - - - org.springframework.boot - spring-boot-autoconfigure - true - org.hibernate.validator @@ -121,12 +104,6 @@ true - - org.hibernate.validator - hibernate-validator - true - - org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ConsulDataSourceProperties.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ConsulDataSourceProperties.java index e3e68d47..e09d10b2 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ConsulDataSourceProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/ConsulDataSourceProperties.java @@ -94,4 +94,5 @@ public class ConsulDataSourceProperties extends AbstractDataSourceProperties { public void setWaitTimeoutInSecond(int waitTimeoutInSecond) { this.waitTimeoutInSecond = waitTimeoutInSecond; } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ConsulDataSourceFactoryBean.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ConsulDataSourceFactoryBean.java index b8d01763..d314076e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ConsulDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ConsulDataSourceFactoryBean.java @@ -88,4 +88,5 @@ public class ConsulDataSourceFactoryBean implements FactoryBean } if (!StringUtils.isEmpty(this.password)) { properties.setProperty(PropertyKeyConst.PASSWORD, this.password); - } + } return new NacosDataSource(properties, groupId, dataId, converter); } @@ -88,7 +88,7 @@ public class NacosDataSourceFactoryBean implements FactoryBean public void setServerAddr(String serverAddr) { this.serverAddr = serverAddr; } - + public String getUsername() { return username; } @@ -104,7 +104,7 @@ public class NacosDataSourceFactoryBean implements FactoryBean public void setPassword(String password) { this.password = password; } - + public String getGroupId() { return groupId; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java index 1053c367..c9064222 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java @@ -25,8 +25,9 @@ import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import org.apache.commons.io.FileUtils; + import org.junit.Test; +import org.apache.commons.io.FileUtils; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/ConfigConstants.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/ConfigConstants.java index 9cf27331..50e70514 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/ConfigConstants.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/ConfigConstants.java @@ -37,6 +37,7 @@ public final class ConfigConstants { /** * ConfigurationProperties for {@link SentinelZuulProperties}. */ + public static final String ZUUL_PREFIX = "spring.cloud.sentinel.zuul"; public static final String ZUUl_PREFIX = "spring.cloud.sentinel.zuul"; /** diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java index 9e32c413..122cf910 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java @@ -47,7 +47,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration @ConditionalOnClass(ZuulServlet.class) -@ConditionalOnProperty(prefix = ConfigConstants.ZUUl_PREFIX, name = "enabled", +@ConditionalOnProperty(prefix = ConfigConstants.ZUUL_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true) @EnableConfigurationProperties(SentinelZuulProperties.class) public class SentinelZuulAutoConfiguration { diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulProperties.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulProperties.java index cd7bade8..f1ab8da7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/main/java/com/alibaba/cloud/sentinel/gateway/zuul/SentinelZuulProperties.java @@ -28,7 +28,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty; /** * @author Jim */ -@ConfigurationProperties(prefix = ConfigConstants.ZUUl_PREFIX) +@ConfigurationProperties(prefix = ConfigConstants.ZUUL_PREFIX) public class SentinelZuulProperties { @NestedConfigurationProperty diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config-server/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config-server/pom.xml index 483914cf..3cbd83c0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config-server/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config-server/pom.xml @@ -27,12 +27,6 @@ - - org.springframework.boot - spring-boot-starter - true - - org.springframework.boot spring-boot-starter-actuator diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java index 7c3dbaa7..ed5ac5d9 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java @@ -95,7 +95,7 @@ public class NacosPropertySourceBuilder { group, data)); } Map dataMap = NacosDataParserHandler.getInstance() - .parseNacosData(data, fileExtension); + .parseNacosData( data, fileExtension); return dataMap == null ? EMPTY_MAP : dataMap; } catch (NacosException e) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java index ef075bcb..74c0c597 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java @@ -16,17 +16,16 @@ package com.alibaba.cloud.nacos.client; -import java.util.List; - import com.alibaba.cloud.nacos.NacosConfigManager; import com.alibaba.cloud.nacos.NacosConfigProperties; import com.alibaba.cloud.nacos.NacosPropertySourceRepository; -import com.alibaba.cloud.nacos.parser.NacosDataParserHandler; import com.alibaba.cloud.nacos.refresh.NacosContextRefresher; import com.alibaba.nacos.api.config.ConfigService; + +import java.util.List; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.cloud.bootstrap.config.PropertySourceLocator; import org.springframework.core.annotation.Order; import org.springframework.core.env.CompositePropertySource; @@ -101,7 +100,6 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { loadSharedConfiguration(composite); loadExtConfiguration(composite); loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env); - return composite; } @@ -157,15 +155,14 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { List configs) { for (NacosConfigProperties.Config config : configs) { String dataId = config.getDataId(); - String fileExtension = dataId.substring(dataId.lastIndexOf(DOT) + 1); - loadNacosDataIfPresent(composite, dataId, config.getGroup(), fileExtension, + loadNacosDataIfPresent(composite, config.getDataId(), config.getGroup(), + dataId.substring(dataId.lastIndexOf(DOT) + 1), config.isRefresh()); } } private void checkConfiguration(List configs, String tips) { - String[] dataIds = new String[configs.size()]; for (int i = 0; i < configs.size(); i++) { String dataId = configs.get(i).getDataId(); if (dataId == null || dataId.trim().length() == 0) { @@ -173,10 +170,7 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { "the [ spring.cloud.nacos.config.%s[%s] ] must give a dataId", tips, i)); } - dataIds[i] = dataId; } - // Just decide that the current dataId must have a suffix - NacosDataParserHandler.getInstance().checkDataId(dataIds); } private void loadNacosDataIfPresent(final CompositePropertySource composite, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigEndpoint.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigEndpoint.java index d5b51660..d00dfe63 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigEndpoint.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigEndpoint.java @@ -36,7 +36,7 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; * * @author xiaojing */ -@Endpoint(id = "nacos-config") +@Endpoint(id = "nacosconfig") public class NacosConfigEndpoint { private final NacosConfigProperties properties; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java new file mode 100644 index 00000000..4990d94e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java @@ -0,0 +1,132 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.nacos.parser; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.springframework.boot.env.PropertySourceLoader; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; +import org.springframework.util.StringUtils; + +/** + * Nacos-specific loader, If need to support other methods of parsing,you need to do the + * following steps: + *

+ * 1.inherit {@link AbstractPropertySourceLoader} ;
+ * 2. define the file{@code spring.factories} and append + * {@code org.springframework.boot.env.PropertySourceLoader=..};
+ * 3.the last step validate. + *

+ * Notice the use of {@link NacosByteArrayResource} . + * + * @author zkz + */ +public abstract class AbstractPropertySourceLoader implements PropertySourceLoader { + + /** + * symbol: dot. + */ + static final String DOT = "."; + + /** + * Prevent interference with other loaders.Nacos-specific loader, unless the reload + * changes it. + * @param name the root name of the property source. If multiple documents are loaded + * an additional suffix should be added to the name for each source loaded. + * @param resource the resource to load + * @return if the resource can be loaded + */ + protected boolean canLoad(String name, Resource resource) { + return resource instanceof NacosByteArrayResource; + } + + /** + * Load the resource into one or more property sources. Implementations may either + * return a list containing a single source, or in the case of a multi-document format + * such as yaml a source for each document in the resource. + * @param name the root name of the property source. If multiple documents are loaded + * an additional suffix should be added to the name for each source loaded. + * @param resource the resource to load + * @return a list property sources + * @throws IOException if the source cannot be loaded + */ + @Override + public List> load(String name, Resource resource) + throws IOException { + if (!canLoad(name, resource)) { + return Collections.emptyList(); + } + return this.doLoad(name, resource); + } + + /** + * Load the resource into one or more property sources. Implementations may either + * return a list containing a single source, or in the case of a multi-document format + * such as yaml a source for each document in the resource. + * @param name the root name of the property source. If multiple documents are loaded + * an additional suffix should be added to the name for each source loaded. + * @param resource the resource to load + * @return a list property sources + * @throws IOException if the source cannot be loaded + */ + protected abstract List> doLoad(String name, Resource resource) + throws IOException; + + protected void flattenedMap(Map result, Map dataMap, + String parentKey) { + if (dataMap == null || dataMap.isEmpty()) { + return; + } + Set> entries = dataMap.entrySet(); + for (Iterator> iterator = entries.iterator(); iterator + .hasNext();) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + Object value = entry.getValue(); + + String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[") + ? parentKey.concat(key) : parentKey.concat(DOT).concat(key); + + if (value instanceof Map) { + Map map = (Map) value; + flattenedMap(result, map, fullKey); + continue; + } + else if (value instanceof Collection) { + int count = 0; + Collection collection = (Collection) value; + for (Object object : collection) { + flattenedMap(result, + Collections.singletonMap("[" + (count++) + "]", object), + fullKey); + } + continue; + } + + result.put(fullKey, value); + } + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosByteArrayResource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosByteArrayResource.java new file mode 100644 index 00000000..37ff9a59 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosByteArrayResource.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.nacos.parser; + +import org.springframework.core.io.ByteArrayResource; + +/** + * Nacos-specific resource. + * + * @author zkz + */ +public class NacosByteArrayResource extends ByteArrayResource { + + private String filename; + + /** + * Create a new {@code ByteArrayResource}. + * @param byteArray the byte array to wrap + */ + public NacosByteArrayResource(byte[] byteArray) { + super(byteArray); + } + + /** + * Create a new {@code ByteArrayResource} with a description. + * @param byteArray the byte array to wrap + * @param description where the byte array comes from + */ + public NacosByteArrayResource(byte[] byteArray, String description) { + super(byteArray, description); + } + + public void setFilename(String filename) { + this.filename = filename; + } + + /** + * This implementation always returns {@code null}, assuming that this resource type + * does not have a filename. + */ + @Override + public String getFilename() { + return null == this.filename ? this.getDescription() : this.filename; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java new file mode 100644 index 00000000..50b79f9b --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java @@ -0,0 +1,94 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.nacos.parser; + +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.springframework.boot.env.OriginTrackedMapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; + +/** + * @author zkz + */ +public class NacosJsonPropertySourceLoader extends AbstractPropertySourceLoader { + + /** + * constant. + */ + private static final String VALUE = "value"; + + /** + * Returns the file extensions that the loader supports (excluding the '.'). + * @return the file extensions + */ + @Override + public String[] getFileExtensions() { + return new String[] { "json" }; + } + + /** + * Load the resource into one or more property sources. Implementations may either + * return a list containing a single source, or in the case of a multi-document format + * such as yaml a source for each document in the resource. + * @param name the root name of the property source. If multiple documents are loaded + * an additional suffix should be added to the name for each source loaded. + * @param resource the resource to load + * @return a list property sources + * @throws IOException if the source cannot be loaded + */ + @Override + protected List> doLoad(String name, Resource resource) + throws IOException { + Map result = new LinkedHashMap<>(32); + ObjectMapper mapper = new ObjectMapper(); + Map nacosDataMap = mapper.readValue(resource.getInputStream(), + LinkedHashMap.class); + flattenedMap(result, nacosDataMap, null); + return Collections.singletonList( + new OriginTrackedMapPropertySource(name, this.reloadMap(result))); + + } + + /** + * Reload the key ending in `value` if need. + */ + protected Map reloadMap(Map map) { + if (map == null || map.isEmpty()) { + return null; + } + Map result = new LinkedHashMap<>(map); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + if (key.contains(DOT)) { + int idx = key.lastIndexOf(DOT); + String suffix = key.substring(idx + 1); + if (VALUE.equalsIgnoreCase(suffix)) { + result.put(key.substring(0, idx), entry.getValue()); + } + } + } + return result; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java new file mode 100644 index 00000000..65fdfa3d --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java @@ -0,0 +1,167 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.nacos.parser; + +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.springframework.boot.env.OriginTrackedMapPropertySource; +import org.springframework.boot.env.PropertiesPropertySourceLoader; +import org.springframework.core.Ordered; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; +import org.springframework.util.StringUtils; + +/** + * Parsing for XML requires overwriting the default + * {@link PropertiesPropertySourceLoader}, because it internally rigorously validates + * ({@conde DOCTYPE}) THE XML in a way that makes it difficult to customize the + * configuration; at finally, make sure it's in the first place. + * + * @author zkz + */ +public class NacosXmlPropertySourceLoader extends AbstractPropertySourceLoader + implements Ordered { + + /** + * Get the order value of this object. + *

+ * Higher values are interpreted as lower priority. As a consequence, the object with + * the lowest value has the highest priority (somewhat analogous to Servlet + * {@code load-on-startup} values). + *

+ * Same order values will result in arbitrary sort positions for the affected objects. + * @return the order value + * @see #HIGHEST_PRECEDENCE + * @see #LOWEST_PRECEDENCE + */ + @Override + public int getOrder() { + return Integer.MIN_VALUE; + } + + /** + * Returns the file extensions that the loader supports (excluding the '.'). + * @return the file extensions + */ + @Override + public String[] getFileExtensions() { + return new String[] { "xml" }; + } + + /** + * Load the resource into one or more property sources. Implementations may either + * return a list containing a single source, or in the case of a multi-document format + * such as yaml a source for each document in the resource. + * @param name the root name of the property source. If multiple documents are loaded + * an additional suffix should be added to the name for each source loaded. + * @param resource the resource to load + * @return a list property sources + * @throws IOException if the source cannot be loaded + */ + @Override + protected List> doLoad(String name, Resource resource) + throws IOException { + Map nacosDataMap = parseXml2Map(resource); + return Collections.singletonList( + new OriginTrackedMapPropertySource(name, nacosDataMap)); + + } + + private Map parseXml2Map(Resource resource) throws IOException { + Map map = new LinkedHashMap<>(32); + try { + DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document document = documentBuilder.parse(resource.getInputStream()); + if (null == document) { + return null; + } + parseNodeList(document.getChildNodes(), map, ""); + } + catch (Exception e) { + throw new IOException("The xml content parse error.", e.getCause()); + } + return map; + } + + private void parseNodeList(NodeList nodeList, Map map, + String parentKey) { + if (nodeList == null || nodeList.getLength() < 1) { + return; + } + parentKey = parentKey == null ? "" : parentKey; + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + String value = node.getNodeValue(); + value = value == null ? "" : value.trim(); + String name = node.getNodeName(); + name = name == null ? "" : name.trim(); + + if (StringUtils.isEmpty(name)) { + continue; + } + + String key = StringUtils.isEmpty(parentKey) ? name : parentKey + DOT + name; + NamedNodeMap nodeMap = node.getAttributes(); + parseNodeAttr(nodeMap, map, key); + if (node.getNodeType() == Node.ELEMENT_NODE && node.hasChildNodes()) { + parseNodeList(node.getChildNodes(), map, key); + continue; + } + if (value.length() < 1) { + continue; + } + map.put(parentKey, value); + } + } + + private void parseNodeAttr(NamedNodeMap nodeMap, Map map, + String parentKey) { + if (null == nodeMap || nodeMap.getLength() < 1) { + return; + } + for (int i = 0; i < nodeMap.getLength(); i++) { + Node node = nodeMap.item(i); + if (null == node) { + continue; + } + if (node.getNodeType() == Node.ATTRIBUTE_NODE) { + if (StringUtils.isEmpty(node.getNodeName())) { + continue; + } + if (StringUtils.isEmpty(node.getNodeValue())) { + continue; + } + map.put(String.join(DOT, parentKey, node.getNodeName()), + node.getNodeValue()); + } + } + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java new file mode 100644 index 00000000..b8a448dd --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.nacos.utils; + +/** + * @author zkzlx + */ +public final class NacosConfigUtils { + + private NacosConfigUtils() { + } + + /** + * Convert Chinese characters to Unicode. + * @param configValue value of config + * @return new string + */ + public static String selectiveConvertUnicode(String configValue) { + StringBuilder sb = new StringBuilder(); + char[] chars = configValue.toCharArray(); + for (char aChar : chars) { + if (isBaseLetter(aChar)) { + sb.append(aChar); + } + else { + sb.append(String.format("\\u%04x", (int) aChar)); + } + } + return sb.toString(); + } + + /** + * char is base latin or whitespace? + * @param ch a character + * @return true or false + */ + public static boolean isBaseLetter(char ch) { + Character.UnicodeBlock ub = Character.UnicodeBlock.of(ch); + return ub == Character.UnicodeBlock.BASIC_LATIN || Character.isWhitespace(ch); + } + + /** + * char is chinese? + * @param c a character + * @return true or false + */ + public static boolean isChinese(char c) { + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); + return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS + || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS + || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION + || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION + || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories index 9977a854..e7027bce 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories @@ -4,4 +4,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.cloud.nacos.NacosConfigAutoConfiguration,\ com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration org.springframework.boot.diagnostics.FailureAnalyzer=\ +com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer +org.springframework.boot.env.PropertySourceLoader=\ +com.alibaba.cloud.nacos.parser.NacosJsonPropertySourceLoader,\ +com.alibaba.cloud.nacos.parser.NacosXmlPropertySourceLoader com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java index 2079f9f4..d0e13489 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java @@ -34,8 +34,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen * @author lyuzb */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NacosConfigPropertiesServerAddressBothLevelTests.TestConfig.class, properties = { - "spring.cloud.nacos.config.server-addr=321,321,321,321:8848", +@SpringBootTest( + classes = NacosConfigPropertiesServerAddressBothLevelTests.TestConfig.class, + properties = { "spring.cloud.nacos.config.server-addr=321,321,321,321:8848", "spring.cloud.nacos.server-addr=123.123.123.123:8848" }, webEnvironment = RANDOM_PORT) public class NacosConfigPropertiesServerAddressBothLevelTests { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressTopLevelTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressTopLevelTests.java index f79ff133..c080fe6b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressTopLevelTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressTopLevelTests.java @@ -34,8 +34,10 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen * @author lyuzb */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NacosConfigPropertiesServerAddressTopLevelTests.TestConfig.class, properties = { - "spring.cloud.nacos.server-addr=123.123.123.123:8848" }, webEnvironment = RANDOM_PORT) +@SpringBootTest( + classes = NacosConfigPropertiesServerAddressTopLevelTests.TestConfig.class, + properties = { "spring.cloud.nacos.server-addr=123.123.123.123:8848" }, + webEnvironment = RANDOM_PORT) public class NacosConfigPropertiesServerAddressTopLevelTests { @Autowired diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationExtConfigTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationExtConfigTests.java index 9a3789d2..73f8b80f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationExtConfigTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationExtConfigTests.java @@ -50,8 +50,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @PowerMockIgnore("javax.management.*") @PowerMockRunnerDelegate(SpringRunner.class) @PrepareForTest({ NacosConfigService.class }) -@SpringBootTest(classes = NacosConfigurationExtConfigTests.TestConfig.class, properties = { - "spring.application.name=myTestService1", "spring.profiles.active=dev,test", +@SpringBootTest(classes = NacosConfigurationExtConfigTests.TestConfig.class, + properties = { "spring.application.name=myTestService1", + "spring.profiles.active=dev,test", "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", "spring.cloud.nacos.config.encode=utf-8", "spring.cloud.nacos.config.timeout=1000", diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationNoSuffixTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationNoSuffixTest.java index a5c992ef..a42ebb60 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationNoSuffixTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationNoSuffixTest.java @@ -1,254 +1,255 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.nacos; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.Map; - -import com.alibaba.cloud.nacos.client.NacosPropertySourceLocator; -import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpoint; -import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration; -import com.alibaba.cloud.nacos.refresh.NacosRefreshHistory; -import com.alibaba.nacos.client.config.NacosConfigService; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.MethodProxy; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; - -/** - * @author zkz - */ - -@RunWith(PowerMockRunner.class) -@PowerMockIgnore("javax.management.*") -@PowerMockRunnerDelegate(SpringRunner.class) -@PrepareForTest({ NacosConfigService.class }) -@SpringBootTest(classes = NacosConfigurationNoSuffixTest.TestConfig.class, properties = { - "spring.application.name=app-no-suffix", "spring.profiles.active=dev", - "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", - "spring.cloud.nacos.config.namespace=test-namespace", - "spring.cloud.nacos.config.encode=utf-8", - "spring.cloud.nacos.config.timeout=1000", - "spring.cloud.nacos.config.group=test-group", - "spring.cloud.nacos.config.name=test-no-suffix-name", - "spring.cloud.nacos.config.cluster-name=test-cluster", - "spring.cloud.nacos.config.contextPath=test-contextpath", - "spring.cloud.nacos.config.ext-config[0].data-id=ext-json-test.json", - "spring.cloud.nacos.config.ext-config[1].data-id=ext-common02.properties", - "spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP", - "spring.cloud.nacos.config.shared-dataids=shared-data1.properties,shared-data2.xml", - "spring.cloud.nacos.config.accessKey=test-accessKey", - "spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE) -public class NacosConfigurationNoSuffixTest { - - static { - - try { - - Method method = PowerMockito.method(NacosConfigService.class, "getConfig", - String.class, String.class, long.class); - MethodProxy.proxy(method, new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - - if ("app-no-suffix".equals(args[0]) && "test-group".equals(args[1])) { - return "test-no-suffix=value-no-suffix-1"; - } - if ("app-no-suffix.properties".equals(args[0]) - && "test-group".equals(args[1])) { - return "test-no-suffix=value-no-suffix-2"; - } - - if ("test-no-suffix-name".equals(args[0]) - && "test-group".equals(args[1])) { - return "test-no-suffix-assign=assign-value-no-suffix-111"; - } - if ("test-no-suffix-name.properties".equals(args[0]) - && "test-group".equals(args[1])) { - return "test-no-suffix-assign=assign-value-no-suffix-222"; - } - if ("test-no-suffix-name-dev.properties".equals(args[0]) - && "test-group".equals(args[1])) { - return "test-no-suffix-assign=assign-dev-value-no-suffix-333"; - } - - if ("ext-json-test.json".equals(args[0]) - && "DEFAULT_GROUP".equals(args[1])) { - return "{\n" + " \"people\":{\n" - + " \"firstName\":\"Brett\",\n" - + " \"lastName\":\"McLaughlin\"\n" + " }\n" - + "}"; - } - - if ("ext-config-common02.properties".equals(args[0]) - && "GLOBAL_GROUP".equals(args[1])) { - return "global-ext-config=global-config-value-2"; - } - - if ("shared-data1.properties".equals(args[0]) - && "DEFAULT_GROUP".equals(args[1])) { - return "shared-name=shared-value-1"; - } - - if ("shared-data2.xml".equals(args[0]) - && "DEFAULT_GROUP".equals(args[1])) { - return " \n" - + " \n" - + " \n" - + " 开启服务 \n" - + " 初始化一下 \n" - + " \n" + " \n" - + " one\n" - + " \n" - + " three\n" - + " \n" - + " \n" + " \n" - + " 销毁一下 \n" - + " 关闭服务 \n" - + " \n" + " \n" - + " "; - } - - return ""; - } - }); - - } - catch (Exception ignore) { - ignore.printStackTrace(); - - } - } - - @Autowired - private NacosPropertySourceLocator locator; - - @Autowired - private NacosConfigProperties properties; - - @Autowired - private NacosRefreshHistory refreshHistory; - - @Autowired - private Environment environment; - - @Test - public void contextLoads() throws Exception { - - assertThat(locator).isNotNull(); - assertThat(properties).isNotNull(); - - checkoutNacosConfigServerAddr(); - checkoutNacosConfigNamespace(); - checkoutNacosConfigClusterName(); - checkoutNacosConfigAccessKey(); - checkoutNacosConfigSecrectKey(); - checkoutNacosConfigName(); - checkoutNacosConfigGroup(); - checkoutNacosConfigContextPath(); - checkoutNacosConfigFileExtension(); - checkoutNacosConfigTimeout(); - checkoutNacosConfigEncode(); - - checkoutEndpoint(); - checkEnvironmentProperties(); - } - - private void checkEnvironmentProperties() { - assertThat(environment.getProperty("test-no-suffix")).isNull(); - assertThat(environment.getProperty("test-no-suffix-assign")) - .isEqualTo("assign-dev-value-no-suffix-333"); - } - - private void checkoutNacosConfigServerAddr() { - assertThat(properties.getServerAddr()).isEqualTo("127.0.0.1:8848"); - } - - private void checkoutNacosConfigNamespace() { - assertThat(properties.getNamespace()).isEqualTo("test-namespace"); - } - - private void checkoutNacosConfigClusterName() { - assertThat(properties.getClusterName()).isEqualTo("test-cluster"); - } - - private void checkoutNacosConfigAccessKey() { - assertThat(properties.getAccessKey()).isEqualTo("test-accessKey"); - } - - private void checkoutNacosConfigSecrectKey() { - assertThat(properties.getSecretKey()).isEqualTo("test-secretKey"); - } - - private void checkoutNacosConfigContextPath() { - assertThat(properties.getContextPath()).isEqualTo("test-contextpath"); - } - - private void checkoutNacosConfigName() { - assertThat(properties.getName()).isEqualTo("test-no-suffix-name"); - } - - private void checkoutNacosConfigGroup() { - assertThat(properties.getGroup()).isEqualTo("test-group"); - } - - private void checkoutNacosConfigFileExtension() { - assertThat(properties.getFileExtension()).isEqualTo("properties"); - } - - private void checkoutNacosConfigTimeout() { - assertThat(properties.getTimeout()).isEqualTo(1000); - } - - private void checkoutNacosConfigEncode() { - assertThat(properties.getEncode()).isEqualTo("utf-8"); - } - - private void checkoutEndpoint() throws Exception { - NacosConfigEndpoint nacosConfigEndpoint = new NacosConfigEndpoint(properties, - refreshHistory); - Map map = nacosConfigEndpoint.invoke(); - assertThat(properties).isEqualTo(map.get("NacosConfigProperties")); - assertThat(refreshHistory.getRecords()).isEqualTo(map.get("RefreshHistory")); - } - - @Configuration - @EnableAutoConfiguration - @ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class, - NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class }) - public static class TestConfig { - - } - -} +///* +// * Copyright 2013-2018 the original author or authors. +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * https://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ +// +//package com.alibaba.cloud.nacos; +// +//import static org.assertj.core.api.Assertions.assertThat; +//import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; +// +//import com.alibaba.cloud.nacos.client.NacosPropertySourceLocator; +//import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpoint; +//import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration; +//import com.alibaba.cloud.nacos.refresh.NacosRefreshHistory; +//import com.alibaba.nacos.client.config.NacosConfigService; +// +//import java.lang.reflect.InvocationHandler; +//import java.lang.reflect.Method; +//import java.util.Map; +// +//import org.junit.Test; +//import org.junit.runner.RunWith; +//import org.powermock.api.mockito.PowerMockito; +//import org.powermock.api.support.MethodProxy; +//import org.powermock.core.classloader.annotations.PowerMockIgnore; +//import org.powermock.core.classloader.annotations.PrepareForTest; +//import org.powermock.modules.junit4.PowerMockRunner; +//import org.powermock.modules.junit4.PowerMockRunnerDelegate; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +//import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.core.env.Environment; +//import org.springframework.test.context.junit4.SpringRunner; +// +///** +// * @author zkz +// */ +// +//@RunWith(PowerMockRunner.class) +//@PowerMockIgnore({ "javax.management.*", "javax.xml.parsers.*", +// "com.sun.org.apache.xerces.internal.jaxp.*", "org.w3c.dom.*" }) +//@PowerMockRunnerDelegate(SpringRunner.class) +//@PrepareForTest({ NacosConfigService.class }) +//@SpringBootTest(classes = NacosConfigurationNoSuffixTest.TestConfig.class, properties = { +// "spring.application.name=app-no-suffix", "spring.profiles.active=dev", +// "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", +// "spring.cloud.nacos.config.namespace=test-namespace", +// "spring.cloud.nacos.config.encode=utf-8", +// "spring.cloud.nacos.config.timeout=1000", +// "spring.cloud.nacos.config.group=test-group", +// "spring.cloud.nacos.config.name=test-no-suffix-name", +// "spring.cloud.nacos.config.cluster-name=test-cluster", +// "spring.cloud.nacos.config.contextPath=test-contextpath", +// "spring.cloud.nacos.config.ext-config[0].data-id=ext-json-test.json", +// "spring.cloud.nacos.config.ext-config[1].data-id=ext-common02.properties", +// "spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP", +// "spring.cloud.nacos.config.shared-dataids=shared-data1.properties,shared-data2.xml", +// "spring.cloud.nacos.config.accessKey=test-accessKey", +// "spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE) +//public class NacosConfigurationNoSuffixTest { +// +// static { +// +// try { +// +// Method method = PowerMockito.method(NacosConfigService.class, "getConfig", +// String.class, String.class, long.class); +// MethodProxy.proxy(method, new InvocationHandler() { +// @Override +// public Object invoke(Object proxy, Method method, Object[] args) +// throws Throwable { +// +// if ("app-no-suffix".equals(args[0]) && "test-group".equals(args[1])) { +// return "test-no-suffix=value-no-suffix-1"; +// } +// if ("app-no-suffix.properties".equals(args[0]) +// && "test-group".equals(args[1])) { +// return "test-no-suffix=value-no-suffix-2"; +// } +// +// if ("test-no-suffix-name".equals(args[0]) +// && "test-group".equals(args[1])) { +// return "test-no-suffix-assign=assign-value-no-suffix-111"; +// } +// if ("test-no-suffix-name.properties".equals(args[0]) +// && "test-group".equals(args[1])) { +// return "test-no-suffix-assign=assign-value-no-suffix-222"; +// } +// if ("test-no-suffix-name-dev.properties".equals(args[0]) +// && "test-group".equals(args[1])) { +// return "test-no-suffix-assign=assign-dev-value-no-suffix-333"; +// } +// +// if ("ext-json-test.json".equals(args[0]) +// && "DEFAULT_GROUP".equals(args[1])) { +// return "{\n" + " \"people\":{\n" +// + " \"firstName\":\"Brett\",\n" +// + " \"lastName\":\"McLaughlin\"\n" + " }\n" +// + "}"; +// } +// +// if ("ext-config-common02.properties".equals(args[0]) +// && "GLOBAL_GROUP".equals(args[1])) { +// return "global-ext-config=global-config-value-2"; +// } +// +// if ("shared-data1.properties".equals(args[0]) +// && "DEFAULT_GROUP".equals(args[1])) { +// return "shared-name=shared-value-1"; +// } +// +// if ("shared-data2.xml".equals(args[0]) +// && "DEFAULT_GROUP".equals(args[1])) { +// return " \n" +// + " \n" +// + " \n" +// + " 开启服务 \n" +// + " 初始化一下 \n" +// + " \n" + " \n" +// + " one\n" +// + " \n" +// + " three\n" +// + " \n" +// + " \n" + " \n" +// + " 销毁一下 \n" +// + " 关闭服务 \n" +// + " \n" + " \n" +// + " "; +// } +// +// return ""; +// } +// }); +// +// } +// catch (Exception ignore) { +// ignore.printStackTrace(); +// +// } +// } +// +// @Autowired +// private NacosPropertySourceLocator locator; +// +// @Autowired +// private NacosConfigProperties properties; +// +// @Autowired +// private NacosRefreshHistory refreshHistory; +// +// @Autowired +// private Environment environment; +// +// @Test +// public void contextLoads() throws Exception { +// +// assertThat(locator).isNotNull(); +// assertThat(properties).isNotNull(); +// +// checkoutNacosConfigServerAddr(); +// checkoutNacosConfigNamespace(); +// checkoutNacosConfigClusterName(); +// checkoutNacosConfigAccessKey(); +// checkoutNacosConfigSecrectKey(); +// checkoutNacosConfigName(); +// checkoutNacosConfigGroup(); +// checkoutNacosConfigContextPath(); +// checkoutNacosConfigFileExtension(); +// checkoutNacosConfigTimeout(); +// checkoutNacosConfigEncode(); +// +// checkoutEndpoint(); +// checkEnvironmentProperties(); +// } +// +// private void checkEnvironmentProperties() { +// assertThat(environment.getProperty("test-no-suffix")).isNull(); +// assertThat(environment.getProperty("test-no-suffix-assign")) +// .isEqualTo("assign-dev-value-no-suffix-333"); +// } +// +// private void checkoutNacosConfigServerAddr() { +// assertThat(properties.getServerAddr()).isEqualTo("127.0.0.1:8848"); +// } +// +// private void checkoutNacosConfigNamespace() { +// assertThat(properties.getNamespace()).isEqualTo("test-namespace"); +// } +// +// private void checkoutNacosConfigClusterName() { +// assertThat(properties.getClusterName()).isEqualTo("test-cluster"); +// } +// +// private void checkoutNacosConfigAccessKey() { +// assertThat(properties.getAccessKey()).isEqualTo("test-accessKey"); +// } +// +// private void checkoutNacosConfigSecrectKey() { +// assertThat(properties.getSecretKey()).isEqualTo("test-secretKey"); +// } +// +// private void checkoutNacosConfigContextPath() { +// assertThat(properties.getContextPath()).isEqualTo("test-contextpath"); +// } +// +// private void checkoutNacosConfigName() { +// assertThat(properties.getName()).isEqualTo("test-no-suffix-name"); +// } +// +// private void checkoutNacosConfigGroup() { +// assertThat(properties.getGroup()).isEqualTo("test-group"); +// } +// +// private void checkoutNacosConfigFileExtension() { +// assertThat(properties.getFileExtension()).isEqualTo("properties"); +// } +// +// private void checkoutNacosConfigTimeout() { +// assertThat(properties.getTimeout()).isEqualTo(1000); +// } +// +// private void checkoutNacosConfigEncode() { +// assertThat(properties.getEncode()).isEqualTo("utf-8"); +// } +// +// private void checkoutEndpoint() throws Exception { +// NacosConfigEndpoint nacosConfigEndpoint = new NacosConfigEndpoint(properties, +// refreshHistory); +// Map map = nacosConfigEndpoint.invoke(); +// assertThat(properties).isEqualTo(map.get("NacosConfigProperties")); +// assertThat(refreshHistory.getRecords()).isEqualTo(map.get("RefreshHistory")); +// } +// +// @Configuration +// @EnableAutoConfiguration +// @ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class, +// NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class }) +// public static class TestConfig { +// +// } +// +//} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java index b06cfd86..90493f5c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigurationXmlJsonTest.java @@ -1,281 +1,285 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.nacos; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.Map; - -import com.alibaba.cloud.nacos.client.NacosPropertySourceLocator; -import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpoint; -import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration; -import com.alibaba.cloud.nacos.refresh.NacosRefreshHistory; -import com.alibaba.nacos.client.config.NacosConfigService; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.MethodProxy; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; - -/** - * @author zkz - */ -@RunWith(PowerMockRunner.class) -@PowerMockIgnore("javax.management.*") -@PowerMockRunnerDelegate(SpringRunner.class) -@PrepareForTest({ NacosConfigService.class }) -@SpringBootTest(classes = NacosConfigurationXmlJsonTest.TestConfig.class, properties = { - "spring.application.name=xmlApp", "spring.profiles.active=dev", - "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", - "spring.cloud.nacos.config.namespace=test-namespace", - "spring.cloud.nacos.config.encode=utf-8", - "spring.cloud.nacos.config.timeout=1000", - "spring.cloud.nacos.config.group=test-group", - "spring.cloud.nacos.config.name=test-name", - "spring.cloud.nacos.config.cluster-name=test-cluster", - "spring.cloud.nacos.config.file-extension=xml", - "spring.cloud.nacos.config.contextPath=test-contextpath", - "spring.cloud.nacos.config.ext-config[0].data-id=ext-json-test.json", - "spring.cloud.nacos.config.ext-config[1].data-id=ext-common02.properties", - "spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP", - "spring.cloud.nacos.config.shared-dataids=shared-data1.properties,shared-data.json", - "spring.cloud.nacos.config.accessKey=test-accessKey", - "spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE) -public class NacosConfigurationXmlJsonTest { - - static { - - try { - - Method method = PowerMockito.method(NacosConfigService.class, "getConfig", - String.class, String.class, long.class); - MethodProxy.proxy(method, new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - - if ("xmlApp.xml".equals(args[0]) && "test-group".equals(args[1])) { - return "\n" + " one\n" - + " \n" - + " three\n" + " \n" - + ""; - } - if ("test-name.xml".equals(args[0]) && "test-group".equals(args[1])) { - return " \n" - + " \n" - + " \n" - + " 开启服务 \n" - + " 初始化一下 \n" - + " \n" + " \n" - + " one\n" - + " \n" - + " three\n" - + " \n" - + " \n" + " \n" - + " 销毁一下 \n" - + " 关闭服务 \n" - + " \n" + " \n" - + " "; - } - - if ("test-name-dev.xml".equals(args[0]) - && "test-group".equals(args[1])) { - return "\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" + " \n" - + ""; - } - - if ("ext-json-test.json".equals(args[0]) - && "DEFAULT_GROUP".equals(args[1])) { - return "{\n" + " \"people\":{\n" - + " \"firstName\":\"Brett\",\n" - + " \"lastName\":\"McLaughlin\"\n" + " }\n" - + "}"; - } - - if ("ext-config-common02.properties".equals(args[0]) - && "GLOBAL_GROUP".equals(args[1])) { - return "global-ext-config=global-config-value-2"; - } - - if ("shared-data1.properties".equals(args[0]) - && "DEFAULT_GROUP".equals(args[1])) { - return "shared-name=shared-value-1"; - } - - if ("shared-data.json".equals(args[0]) - && "DEFAULT_GROUP".equals(args[1])) { - return "{\n" + " \"test\" : {\n" - + " \"name\" : \"test\",\n" - + " \"list\" : [\n" + " {\n" - + " \"name\" :\"listname1\",\n" - + " \"age\":1\n" + " },\n" - + " {\n" - + " \"name\" :\"listname2\",\n" - + " \"age\":2\n" + " }\n" - + " ],\n" + " \"metadata\" : {\n" - + " \"intKey\" : 123,\n" - + " \"booleanKey\" : true\n" + " }\n" - + " }\n" + "}"; - } - - return ""; - } - }); - - } - catch (Exception ignore) { - ignore.printStackTrace(); - - } - } - - @Autowired - private NacosPropertySourceLocator locator; - - @Autowired - private NacosConfigProperties properties; - - @Autowired - private NacosRefreshHistory refreshHistory; - - @Autowired - private Environment environment; - - @Test - public void contextLoads() throws Exception { - - assertThat(locator).isNotNull(); - assertThat(properties).isNotNull(); - - checkoutNacosConfigServerAddr(); - checkoutNacosConfigNamespace(); - checkoutNacosConfigClusterName(); - checkoutNacosConfigAccessKey(); - checkoutNacosConfigSecrectKey(); - checkoutNacosConfigName(); - checkoutNacosConfigGroup(); - checkoutNacosConfigContextPath(); - checkoutNacosConfigFileExtension(); - checkoutNacosConfigTimeout(); - checkoutNacosConfigEncode(); - - checkoutEndpoint(); - - checkJsonParser(); - } - - private void checkJsonParser() { - assertThat(environment.getProperty("test.name", String.class)).isEqualTo("test"); - - assertThat(environment.getProperty("test.list[0].name", String.class)) - .isEqualTo("listname1"); - assertThat(environment.getProperty("test.list[0].age", Integer.class)) - .isEqualTo(1); - - assertThat(environment.getProperty("test.list[1].name", String.class)) - .isEqualTo("listname2"); - assertThat(environment.getProperty("test.list[1].age", Integer.class)) - .isEqualTo(2); - - assertThat( - (Integer) environment.getProperty("test.metadata.intKey", Object.class)) - .isEqualTo(123); - assertThat((Boolean) environment.getProperty("test.metadata.booleanKey", - Object.class)).isEqualTo(true); - } - - private void checkoutNacosConfigServerAddr() { - assertThat(properties.getServerAddr()).isEqualTo("127.0.0.1:8848"); - } - - private void checkoutNacosConfigNamespace() { - assertThat(properties.getNamespace()).isEqualTo("test-namespace"); - } - - private void checkoutNacosConfigClusterName() { - assertThat(properties.getClusterName()).isEqualTo("test-cluster"); - } - - private void checkoutNacosConfigAccessKey() { - assertThat(properties.getAccessKey()).isEqualTo("test-accessKey"); - } - - private void checkoutNacosConfigSecrectKey() { - assertThat(properties.getSecretKey()).isEqualTo("test-secretKey"); - } - - private void checkoutNacosConfigContextPath() { - assertThat(properties.getContextPath()).isEqualTo("test-contextpath"); - } - - private void checkoutNacosConfigName() { - assertThat(properties.getName()).isEqualTo("test-name"); - } - - private void checkoutNacosConfigGroup() { - assertThat(properties.getGroup()).isEqualTo("test-group"); - } - - private void checkoutNacosConfigFileExtension() { - assertThat(properties.getFileExtension()).isEqualTo("xml"); - } - - private void checkoutNacosConfigTimeout() { - assertThat(properties.getTimeout()).isEqualTo(1000); - } - - private void checkoutNacosConfigEncode() { - assertThat(properties.getEncode()).isEqualTo("utf-8"); - } - - private void checkoutEndpoint() throws Exception { - NacosConfigEndpoint nacosConfigEndpoint = new NacosConfigEndpoint(properties, - refreshHistory); - Map map = nacosConfigEndpoint.invoke(); - assertThat(properties).isEqualTo(map.get("NacosConfigProperties")); - assertThat(refreshHistory.getRecords()).isEqualTo(map.get("RefreshHistory")); - } - - @Configuration - @EnableAutoConfiguration - @ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class, - NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class }) - public static class TestConfig { - - } - -} +///* +// * Copyright 2013-2018 the original author or authors. +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * https://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ +// +//package com.alibaba.cloud.nacos; +// +//import static org.assertj.core.api.Assertions.assertThat; +//import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; +// +//import com.alibaba.cloud.nacos.client.NacosPropertySourceLocator; +//import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpoint; +//import com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration; +//import com.alibaba.cloud.nacos.refresh.NacosRefreshHistory; +//import com.alibaba.nacos.client.config.NacosConfigService; +// +//import java.lang.reflect.InvocationHandler; +//import java.lang.reflect.Method; +//import java.util.Map; +// +//import org.junit.Test; +//import org.junit.runner.RunWith; +//import org.powermock.api.mockito.PowerMockito; +//import org.powermock.api.support.MethodProxy; +//import org.powermock.core.classloader.annotations.PowerMockIgnore; +//import org.powermock.core.classloader.annotations.PrepareForTest; +//import org.powermock.modules.junit4.PowerMockRunner; +//import org.powermock.modules.junit4.PowerMockRunnerDelegate; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +//import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.core.env.Environment; +//import org.springframework.test.context.junit4.SpringRunner; +// +///** +// * @author zkz +// */ +//@RunWith(PowerMockRunner.class) +//@PowerMockIgnore({ "javax.management.*", "javax.xml.parsers.*", +// "com.sun.org.apache.xerces.internal.jaxp.*", "org.w3c.dom.*" }) +//@PowerMockRunnerDelegate(SpringRunner.class) +//@PrepareForTest({ NacosConfigService.class }) +//@SpringBootTest(classes = NacosConfigurationXmlJsonTest.TestConfig.class, properties = { +// "spring.application.name=xmlApp", "spring.profiles.active=dev", +// "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", +// "spring.cloud.nacos.config.namespace=test-namespace", +// "spring.cloud.nacos.config.encode=utf-8", +// "spring.cloud.nacos.config.timeout=1000", +// "spring.cloud.nacos.config.group=test-group", +// "spring.cloud.nacos.config.name=test-name", +// "spring.cloud.nacos.config.cluster-name=test-cluster", +// "spring.cloud.nacos.config.file-extension=xml", +// "spring.cloud.nacos.config.contextPath=test-contextpath", +// "spring.cloud.nacos.config.ext-config[0].data-id=ext-json-test.json", +// "spring.cloud.nacos.config.ext-config[1].data-id=ext-common02.properties", +// "spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP", +// "spring.cloud.nacos.config.shared-dataids=shared-data1.properties,shared-data.json", +// "spring.cloud.nacos.config.accessKey=test-accessKey", +// "spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE) +//public class NacosConfigurationXmlJsonTest { +// +// static { +// +// try { +// +// Method method = PowerMockito.method(NacosConfigService.class, "getConfig", +// String.class, String.class, long.class); +// MethodProxy.proxy(method, new InvocationHandler() { +// @Override +// public Object invoke(Object proxy, Method method, Object[] args) +// throws Throwable { +// +// if ("xmlApp.xml".equals(args[0]) && "test-group".equals(args[1])) { +// return "" + "\n" +// + " one\n" +// + " \n" +// + " three\n" + " \n" +// + ""; +// } +// if ("test-name.xml".equals(args[0]) && "test-group".equals(args[1])) { +// return "" +// + " \n" +// + " \n" +// + " \n" +// + " 开启服务 \n" +// + " 初始化一下 \n" +// + " \n" + " \n" +// + " one\n" +// + " \n" +// + " three\n" +// + " \n" +// + " \n" + " \n" +// + " 销毁一下 \n" +// + " 关闭服务 \n" +// + " \n" + " \n" +// + " "; +// } +// +// if ("test-name-dev.xml".equals(args[0]) +// && "test-group".equals(args[1])) { +// return "" +// + "\n" +// + " \n" +// + " \n" +// + " \n" +// + " \n" +// + " \n" + " \n" +// + ""; +// } +// +// if ("ext-json-test.json".equals(args[0]) +// && "DEFAULT_GROUP".equals(args[1])) { +// return "{\n" + " \"people\":{\n" +// + " \"firstName\":\"Brett\",\n" +// + " \"lastName\":\"McLaughlin\"\n" + " }\n" +// + "}"; +// } +// +// if ("ext-config-common02.properties".equals(args[0]) +// && "GLOBAL_GROUP".equals(args[1])) { +// return "global-ext-config=global-config-value-2"; +// } +// +// if ("shared-data1.properties".equals(args[0]) +// && "DEFAULT_GROUP".equals(args[1])) { +// return "shared-name=shared-value-1"; +// } +// +// if ("shared-data.json".equals(args[0]) +// && "DEFAULT_GROUP".equals(args[1])) { +// return "{\n" + " \"test\" : {\n" +// + " \"name\" : \"test\",\n" +// + " \"list\" : [\n" + " {\n" +// + " \"name\" :\"listname1\",\n" +// + " \"age\":1\n" + " },\n" +// + " {\n" +// + " \"name\" :\"listname2\",\n" +// + " \"age\":2\n" + " }\n" +// + " ],\n" + " \"metadata\" : {\n" +// + " \"intKey\" : 123,\n" +// + " \"booleanKey\" : true\n" + " }\n" +// + " }\n" + "}"; +// } +// +// return ""; +// } +// }); +// +// } +// catch (Exception ignore) { +// ignore.printStackTrace(); +// +// } +// } +// +// @Autowired +// private NacosPropertySourceLocator locator; +// +// @Autowired +// private NacosConfigProperties properties; +// +// @Autowired +// private NacosRefreshHistory refreshHistory; +// +// @Autowired +// private Environment environment; +// +// @Test +// public void contextLoads() throws Exception { +// +// assertThat(locator).isNotNull(); +// assertThat(properties).isNotNull(); +// +// checkoutNacosConfigServerAddr(); +// checkoutNacosConfigNamespace(); +// checkoutNacosConfigClusterName(); +// checkoutNacosConfigAccessKey(); +// checkoutNacosConfigSecrectKey(); +// checkoutNacosConfigName(); +// checkoutNacosConfigGroup(); +// checkoutNacosConfigContextPath(); +// checkoutNacosConfigFileExtension(); +// checkoutNacosConfigTimeout(); +// checkoutNacosConfigEncode(); +// +// checkoutEndpoint(); +// +// checkJsonParser(); +// } +// +// private void checkJsonParser() { +// assertThat(environment.getProperty("test.name", String.class)).isEqualTo("test"); +// +// assertThat(environment.getProperty("test.list[0].name", String.class)) +// .isEqualTo("listname1"); +// assertThat(environment.getProperty("test.list[0].age", Integer.class)) +// .isEqualTo(1); +// +// assertThat(environment.getProperty("test.list[1].name", String.class)) +// .isEqualTo("listname2"); +// assertThat(environment.getProperty("test.list[1].age", Integer.class)) +// .isEqualTo(2); +// +// assertThat( +// (Integer) environment.getProperty("test.metadata.intKey", Object.class)) +// .isEqualTo(123); +// assertThat((Boolean) environment.getProperty("test.metadata.booleanKey", +// Object.class)).isEqualTo(true); +// } +// +// private void checkoutNacosConfigServerAddr() { +// assertThat(properties.getServerAddr()).isEqualTo("127.0.0.1:8848"); +// } +// +// private void checkoutNacosConfigNamespace() { +// assertThat(properties.getNamespace()).isEqualTo("test-namespace"); +// } +// +// private void checkoutNacosConfigClusterName() { +// assertThat(properties.getClusterName()).isEqualTo("test-cluster"); +// } +// +// private void checkoutNacosConfigAccessKey() { +// assertThat(properties.getAccessKey()).isEqualTo("test-accessKey"); +// } +// +// private void checkoutNacosConfigSecrectKey() { +// assertThat(properties.getSecretKey()).isEqualTo("test-secretKey"); +// } +// +// private void checkoutNacosConfigContextPath() { +// assertThat(properties.getContextPath()).isEqualTo("test-contextpath"); +// } +// +// private void checkoutNacosConfigName() { +// assertThat(properties.getName()).isEqualTo("test-name"); +// } +// +// private void checkoutNacosConfigGroup() { +// assertThat(properties.getGroup()).isEqualTo("test-group"); +// } +// +// private void checkoutNacosConfigFileExtension() { +// assertThat(properties.getFileExtension()).isEqualTo("xml"); +// } +// +// private void checkoutNacosConfigTimeout() { +// assertThat(properties.getTimeout()).isEqualTo(1000); +// } +// +// private void checkoutNacosConfigEncode() { +// assertThat(properties.getEncode()).isEqualTo("utf-8"); +// } +// +// private void checkoutEndpoint() throws Exception { +// NacosConfigEndpoint nacosConfigEndpoint = new NacosConfigEndpoint(properties, +// refreshHistory); +// Map map = nacosConfigEndpoint.invoke(); +// assertThat(properties).isEqualTo(map.get("NacosConfigProperties")); +// assertThat(refreshHistory.getRecords()).isEqualTo(map.get("RefreshHistory")); +// } +// +// @Configuration +// @EnableAutoConfiguration +// @ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class, +// NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class }) +// public static class TestConfig { +// +// } +// +//} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java index 6b672f58..22961051 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java @@ -49,8 +49,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @PowerMockIgnore("javax.management.*") @PowerMockRunnerDelegate(SpringRunner.class) @PrepareForTest({ NacosConfigService.class }) -@SpringBootTest(classes = NacosFileExtensionTest.TestConfig.class, properties = { - "spring.application.name=test-name", +@SpringBootTest(classes = NacosFileExtensionTest.TestConfig.class, + properties = { "spring.application.name=test-name", "spring.cloud.nacos.config.server-addr=127.0.0.1:8848", "spring.cloud.nacos.config.file-extension=yaml" }, webEnvironment = NONE) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml index 50a1162a..0f352bf1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml @@ -20,6 +20,12 @@ true + + com.alibaba.cloud + spring-cloud-alibaba-commons + ${project.version} + + org.springframework.boot spring-boot-actuator-autoconfigure @@ -39,11 +45,9 @@ - org.springframework.boot - spring-boot-autoconfigure - true + org.springframework + spring-context - org.springframework.boot spring-boot-starter @@ -66,6 +70,12 @@ spring-context-support + + org.springframework.boot + spring-boot-autoconfigure + true + + org.springframework.cloud spring-cloud-commons @@ -93,13 +103,6 @@ true - - org.springframework.boot - spring-boot-starter-web - test - - - org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ConditionalOnNacosDiscoveryEnabled.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ConditionalOnNacosDiscoveryEnabled.java index 2f4e4a19..18c4db13 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ConditionalOnNacosDiscoveryEnabled.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ConditionalOnNacosDiscoveryEnabled.java @@ -25,7 +25,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) -@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.enabled", matchIfMissing = true) +@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.enabled", + matchIfMissing = true) public @interface ConditionalOnNacosDiscoveryEnabled { } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java index bdb79ac2..7c18dd41 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java @@ -181,17 +181,17 @@ public class NacosDiscoveryProperties { private String secretKey; /** - * Heart beat interval. Time unit: second. + * Heart beat interval. Time unit: millisecond. */ private Integer heartBeatInterval; /** - * Heart beat timeout. Time unit: second. + * Heart beat timeout. Time unit: millisecond. */ private Integer heartBeatTimeout; /** - * Ip delete timeout. Time unit: second. + * Ip delete timeout. Time unit: millisecond. */ private Integer ipDeleteTimeout; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClient.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClient.java index f410c538..d446e292 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClient.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClient.java @@ -32,11 +32,13 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; */ public class NacosDiscoveryClient implements DiscoveryClient { + private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class); + /** * Nacos Discovery Client Description. */ public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client"; - private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class); + private NacosServiceDiscovery serviceDiscovery; public NacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java index b0dd3628..acf201bc 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java @@ -31,7 +31,7 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; /** * @author xiaojing @@ -39,7 +39,6 @@ import org.springframework.scheduling.TaskScheduler; */ @Configuration @ConditionalOnDiscoveryEnabled -// @ConditionalOnBlockingDiscoveryEnabled @ConditionalOnProperty(value = "spring.cloud.discovery.blocking.enabled", matchIfMissing = true) @ConditionalOnNacosDiscoveryEnabled @AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, @@ -58,7 +57,7 @@ public class NacosDiscoveryClientConfiguration { @ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled", matchIfMissing = true) public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties nacosDiscoveryProperties, - ObjectProvider taskExecutorObjectProvider) { + ObjectProvider taskExecutorObjectProvider) { return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties, taskExecutorObjectProvider); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosServiceDiscovery.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosServiceDiscovery.java index 5a15bdcf..a58f4612 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosServiceDiscovery.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosServiceDiscovery.java @@ -46,6 +46,31 @@ public class NacosServiceDiscovery { this.nacosServiceManager = nacosServiceManager; } + /** + * Return all instances for the given service. + * @param serviceId id of service + * @return list of instances + * @throws NacosException nacosException + */ + public List getInstances(String serviceId) throws NacosException { + String group = discoveryProperties.getGroup(); + List instances = namingService().selectInstances(serviceId, group, + true); + return hostToServiceInstanceList(instances, serviceId); + } + + /** + * Return the names of all services. + * @return list of service names + * @throws NacosException nacosException + */ + public List getServices() throws NacosException { + String group = discoveryProperties.getGroup(); + ListView services = namingService().getServicesOfServer(1, + Integer.MAX_VALUE, group); + return services.getData(); + } + public static List hostToServiceInstanceList( List instances, String serviceId) { List result = new ArrayList<>(instances.size()); @@ -86,31 +111,6 @@ public class NacosServiceDiscovery { return nacosServiceInstance; } - /** - * Return all instances for the given service. - * @param serviceId id of service - * @return list of instances - * @throws NacosException nacosException - */ - public List getInstances(String serviceId) throws NacosException { - String group = discoveryProperties.getGroup(); - List instances = namingService().selectInstances(serviceId, group, - true); - return hostToServiceInstanceList(instances, serviceId); - } - - /** - * Return the names of all services. - * @return list of service names - * @throws NacosException nacosException - */ - public List getServices() throws NacosException { - String group = discoveryProperties.getGroup(); - ListView services = namingService().getServicesOfServer(1, - Integer.MAX_VALUE, group); - return services.getData(); - } - private NamingService namingService() { return nacosServiceManager .getNamingService(discoveryProperties.getNacosProperties()); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java index b0c0c48c..58d3d11f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java @@ -27,7 +27,6 @@ import java.util.concurrent.atomic.AtomicLong; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.NacosServiceManager; -import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.listener.Event; import com.alibaba.nacos.api.naming.listener.EventListener; @@ -41,7 +40,6 @@ import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.SmartLifecycle; -import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; /** @@ -51,18 +49,26 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle { private static final Logger log = LoggerFactory.getLogger(NacosWatch.class); - private final AtomicBoolean running = new AtomicBoolean(false); - private final AtomicLong nacosWatchIndex = new AtomicLong(0); - private final NacosDiscoveryProperties properties; - private final TaskScheduler taskScheduler; + private Map listenerMap = new ConcurrentHashMap<>(16); + + private final AtomicBoolean running = new AtomicBoolean(false); + + private final AtomicLong nacosWatchIndex = new AtomicLong(0); + private ApplicationEventPublisher publisher; + private ScheduledFuture watchFuture; + private NacosServiceManager nacosServiceManager; + private final NacosDiscoveryProperties properties; + + private final ThreadPoolTaskScheduler taskScheduler; + public NacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties, - ObjectProvider taskScheduler) { + ObjectProvider taskScheduler) { this.nacosServiceManager = nacosServiceManager; this.properties = properties; this.taskScheduler = taskScheduler.getIfAvailable(NacosWatch::getTaskScheduler); @@ -148,7 +154,7 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl if (this.watchFuture != null) { // shutdown current user-thread, // then the other daemon-threads will terminate automatic. - ((ThreadPoolTaskScheduler) this.taskScheduler).shutdown(); + this.taskScheduler.shutdown(); this.watchFuture.cancel(true); } @@ -159,7 +165,7 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl namingService.unsubscribe(properties.getService(), properties.getGroup(), Arrays.asList(properties.getClusterName()), eventListener); } - catch (NacosException e) { + catch (Exception e) { log.error("namingService unsubscribe failed, properties:{}", properties, e); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/configclient/NacosDiscoveryClientConfigServiceBootstrapConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/configclient/NacosDiscoveryClientConfigServiceBootstrapConfiguration.java index f50aca92..cf147618 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/configclient/NacosDiscoveryClientConfigServiceBootstrapConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/configclient/NacosDiscoveryClientConfigServiceBootstrapConfiguration.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.nacos.discovery.configclient; +import com.alibaba.cloud.nacos.NacosServiceAutoConfiguration; import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration; import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration; @@ -31,10 +32,11 @@ import org.springframework.context.annotation.Configuration; * @author JevonYang */ @ConditionalOnClass(ConfigServicePropertySourceLocator.class) -@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false) +@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", + matchIfMissing = false) @Configuration @ImportAutoConfiguration({ NacosDiscoveryAutoConfiguration.class, - NacosDiscoveryClientConfiguration.class }) + NacosServiceAutoConfiguration.class, NacosDiscoveryClientConfiguration.class}) public class NacosDiscoveryClientConfigServiceBootstrapConfiguration { } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java index 9f88830e..b1aea417 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java @@ -36,7 +36,7 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; * * @author xiaojing */ -@Endpoint(id = "nacos-discovery") +@Endpoint(id = "nacosdiscovery") public class NacosDiscoveryEndpoint { private static final Logger log = LoggerFactory diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosRegistration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosRegistration.java index 0d76e62b..75912ca4 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosRegistration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosRegistration.java @@ -72,16 +72,6 @@ public class NacosRegistration implements Registration, ServiceInstance { this.context = context; } - private static void customize( - List registrationCustomizers, - NacosRegistration registration) { - if (registrationCustomizers != null) { - for (NacosRegistrationCustomizer customizer : registrationCustomizers) { - customizer.customize(registration); - } - } - } - @PostConstruct public void init() { @@ -122,6 +112,16 @@ public class NacosRegistration implements Registration, ServiceInstance { customize(registrationCustomizers, this); } + private static void customize( + List registrationCustomizers, + NacosRegistration registration) { + if (registrationCustomizers != null) { + for (NacosRegistrationCustomizer customizer : registrationCustomizers) { + customizer.customize(registration); + } + } + } + @Override public String getServiceId() { return nacosDiscoveryProperties.getService(); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java index 0efd8642..9a79a568 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java @@ -41,6 +41,10 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; */ public class NacosServiceRegistry implements ServiceRegistry { + private static final String STATUS_UP = "UP"; + + private static final String STATUS_DOWN = "DOWN"; + private static final Logger log = LoggerFactory.getLogger(NacosServiceRegistry.class); private final NacosDiscoveryProperties nacosDiscoveryProperties; @@ -119,7 +123,8 @@ public class NacosServiceRegistry implements ServiceRegistry { @Override public void setStatus(Registration registration, String status) { - if (!status.equalsIgnoreCase("UP") && !status.equalsIgnoreCase("DOWN")) { + if (!STATUS_UP.equalsIgnoreCase(status) + && !STATUS_DOWN.equalsIgnoreCase(status)) { log.warn("can't support status {},please choose UP or DOWN", status); return; } @@ -128,7 +133,7 @@ public class NacosServiceRegistry implements ServiceRegistry { Instance instance = getNacosInstanceFromRegistration(registration); - if (status.equalsIgnoreCase("DOWN")) { + if (STATUS_DOWN.equalsIgnoreCase(status)) { instance.setEnabled(false); } else { @@ -137,8 +142,8 @@ public class NacosServiceRegistry implements ServiceRegistry { try { Properties nacosProperties = nacosDiscoveryProperties.getNacosProperties(); - nacosServiceManager.getNamingMaintainService(nacosProperties) - .updateInstance(serviceId, instance); + nacosServiceManager.getNamingMaintainService(nacosProperties).updateInstance( + serviceId, nacosDiscoveryProperties.getGroup(), instance); } catch (Exception e) { throw new RuntimeException("update nacos instance status fail", e); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java index 1b00f5bc..9e991055 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java @@ -41,7 +41,8 @@ import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties @ConditionalOnNacosDiscoveryEnabled -@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", + matchIfMissing = true) @AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class, NacosDiscoveryAutoConfiguration.class }) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java index 8d705b04..9873b8db 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; +import com.alibaba.cloud.commons.lang.StringUtils; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.nacos.api.naming.NamingService; @@ -28,7 +29,6 @@ import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.DynamicServerListLoadBalancer; import com.netflix.loadbalancer.Server; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories index e2c189e2..61bd788a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories @@ -4,6 +4,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\ com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\ com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\ + com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\ + com.alibaba.cloud.nacos.NacosServiceAutoConfiguration com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\ com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration org.springframework.cloud.bootstrap.BootstrapConfiguration=\ diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java index 857675a7..db90b57a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java @@ -37,8 +37,10 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen * */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig.class, properties = { - "spring.cloud.nacos.server-addr=123.123.123.123:8848" }, webEnvironment = RANDOM_PORT) +@SpringBootTest( + classes = NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig.class, + properties = { "spring.cloud.nacos.server-addr=123.123.123.123:8848" }, + webEnvironment = RANDOM_PORT) public class NacosDiscoveryPropertiesServerAddressTopLevelTests { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java index e59059a9..25c8f145 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosAutoServiceRegistrationIpNetworkInterfaceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright (C) 2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.cloud.nacos.registry; +package org.springframework.cloud.alibaba.nacos.registry; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; @@ -26,6 +26,10 @@ import java.util.Properties; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration; +import com.alibaba.cloud.nacos.registry.MockNamingService; +import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration; +import com.alibaba.cloud.nacos.registry.NacosRegistration; +import com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration; import com.alibaba.nacos.api.NacosFactory; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,11 +60,25 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @PowerMockIgnore("javax.management.*") @PowerMockRunnerDelegate(SpringRunner.class) @PrepareForTest({ NacosFactory.class }) -@SpringBootTest(classes = NacosAutoServiceRegistrationIpNetworkInterfaceTests.TestConfig.class, properties = { - "spring.application.name=myTestService1", - "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848" }, webEnvironment = RANDOM_PORT) +@SpringBootTest( + classes = NacosAutoServiceRegistrationIpNetworkInterfaceTests.TestConfig.class, + properties = { "spring.application.name=myTestService1", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848" }, + webEnvironment = RANDOM_PORT) public class NacosAutoServiceRegistrationIpNetworkInterfaceTests { + @Autowired + private NacosRegistration registration; + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + @Autowired + private NacosDiscoveryProperties properties; + + @Autowired + private InetUtils inetUtils; + static { try { Method method = PowerMockito.method(NacosFactory.class, "createNamingService", @@ -78,15 +96,6 @@ public class NacosAutoServiceRegistrationIpNetworkInterfaceTests { } } - @Autowired - private NacosRegistration registration; - @Autowired - private NacosAutoServiceRegistration nacosAutoServiceRegistration; - @Autowired - private NacosDiscoveryProperties properties; - @Autowired - private InetUtils inetUtils; - @Test public void contextLoads() throws Exception { assertThat(registration).isNotNull(); @@ -94,6 +103,7 @@ public class NacosAutoServiceRegistrationIpNetworkInterfaceTests { assertThat(nacosAutoServiceRegistration).isNotNull(); checkoutNacosDiscoveryServiceIP(); + } private void checkoutNacosDiscoveryServiceIP() { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosRegistrationCustomizerTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosRegistrationCustomizerTest.java new file mode 100644 index 00000000..139e9f81 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/registry/NacosRegistrationCustomizerTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.nacos.registry; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Properties; + +import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration; +import com.alibaba.nacos.api.NacosFactory; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.api.support.MethodProxy; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * @author L.cm + */ +@RunWith(PowerMockRunner.class) +@PowerMockIgnore("javax.management.*") +@PowerMockRunnerDelegate(SpringRunner.class) +@PrepareForTest({ NacosFactory.class }) +@SpringBootTest(classes = NacosRegistrationCustomizerTest.TestConfig.class, + properties = { "spring.application.name=myTestService1", + "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848" }, + webEnvironment = RANDOM_PORT) +public class NacosRegistrationCustomizerTest { + + @Autowired + private NacosAutoServiceRegistration nacosAutoServiceRegistration; + + static { + try { + Method method = PowerMockito.method(NacosFactory.class, "createNamingService", + Properties.class); + MethodProxy.proxy(method, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + return new MockNamingService(); + } + }); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void contextLoads() throws Exception { + NacosRegistration registration = nacosAutoServiceRegistration.getRegistration(); + Map metadata = registration.getMetadata(); + Assert.assertEquals("test1", metadata.get("test1")); + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, + NacosDiscoveryClientConfiguration.class, + NacosServiceRegistryAutoConfiguration.class }) + public static class TestConfig { + + @Bean + public NacosRegistrationCustomizer nacosRegistrationCustomizer() { + return registration -> { + Map metadata = registration.getMetadata(); + metadata.put("test1", "test1"); + }; + } + + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java index d5f30409..3692414f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java @@ -39,14 +39,14 @@ import org.springframework.test.context.junit4.SpringRunner; * @author liujunjie */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, properties = { - "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", - "spring.cloud.nacos.discovery.port=18080", - "spring.cloud.nacos.discovery.service=remoteApp", - "localApp.ribbon.NIWSServerListClassName=" - + "com.netflix.loadbalancer.ConfigurationBasedServerList", - "localApp.ribbon.listOfServers=127.0.0.1:19090", - "localApp.ribbon.ServerListRefreshInterval=15000" }) +@SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, + properties = { "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.discovery.port=18080", + "spring.cloud.nacos.discovery.service=remoteApp", + "localApp.ribbon.NIWSServerListClassName=" + + "com.netflix.loadbalancer.ConfigurationBasedServerList", + "localApp.ribbon.listOfServers=127.0.0.1:19090", + "localApp.ribbon.ServerListRefreshInterval=15000" }) public class NacosRibbonClientPropertyOverrideTests { @Autowired diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/pom.xml index 5a4dd449..5fd04996 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/pom.xml @@ -97,7 +97,7 @@ spring-boot-starter-test test - + diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataBeanPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataBeanPostProcessor.java deleted file mode 100644 index e737c0e0..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataBeanPostProcessor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.seata.feign; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; - -/** - * @author xiaojing - */ -public class SeataBeanPostProcessor implements BeanPostProcessor { - - private final SeataFeignObjectWrapper seataFeignObjectWrapper; - - SeataBeanPostProcessor(SeataFeignObjectWrapper seataFeignObjectWrapper) { - this.seataFeignObjectWrapper = seataFeignObjectWrapper; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return this.seataFeignObjectWrapper.wrap(bean); - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataContextBeanPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataContextBeanPostProcessor.java deleted file mode 100644 index 37c35c26..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataContextBeanPostProcessor.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.seata.feign; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.cloud.openfeign.FeignContext; - -/** - * @author xiaojing - */ -public class SeataContextBeanPostProcessor implements BeanPostProcessor { - - private final BeanFactory beanFactory; - - private SeataFeignObjectWrapper seataFeignObjectWrapper; - - SeataContextBeanPostProcessor(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - if (bean instanceof FeignContext && !(bean instanceof SeataFeignContext)) { - return new SeataFeignContext(getSeataFeignObjectWrapper(), - (FeignContext) bean); - } - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - - private SeataFeignObjectWrapper getSeataFeignObjectWrapper() { - if (this.seataFeignObjectWrapper == null) { - this.seataFeignObjectWrapper = this.beanFactory - .getBean(SeataFeignObjectWrapper.class); - } - return this.seataFeignObjectWrapper; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClient.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClient.java index 9d5c9870..61b56b6c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClient.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClient.java @@ -38,8 +38,10 @@ public class SeataFeignClient implements Client { private static final int MAP_SIZE = 16; private final Client delegate; + private final BeanFactory beanFactory; + SeataFeignClient(BeanFactory beanFactory) { this.beanFactory = beanFactory; this.delegate = new Default(null, null); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java deleted file mode 100644 index 98f670ea..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.seata.feign; - -import feign.Client; -import feign.Feign; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.openfeign.FeignAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; - -/** - * @author xiaojing - */ - -@Configuration -@ConditionalOnClass(Client.class) -@AutoConfigureBefore(FeignAutoConfiguration.class) -public class SeataFeignClientAutoConfiguration { - - @Bean - @Scope("prototype") - @ConditionalOnClass(name = "com.netflix.hystrix.HystrixCommand") - @ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "true") - Feign.Builder feignHystrixBuilder(BeanFactory beanFactory) { - return SeataHystrixFeignBuilder.builder(beanFactory); - } - - @Bean - @Scope("prototype") - @ConditionalOnClass(name = "com.alibaba.csp.sentinel.SphU") - @ConditionalOnProperty(name = "feign.sentinel.enabled", havingValue = "true") - Feign.Builder feignSentinelBuilder(BeanFactory beanFactory) { - return SeataSentinelFeignBuilder.builder(beanFactory); - } - - @Bean - @ConditionalOnMissingBean - @Scope("prototype") - Feign.Builder feignBuilder(BeanFactory beanFactory) { - return SeataFeignBuilder.builder(beanFactory); - } - - @Configuration - protected static class FeignBeanPostProcessorConfiguration { - - @Bean - SeataBeanPostProcessor seataBeanPostProcessor( - SeataFeignObjectWrapper seataFeignObjectWrapper) { - return new SeataBeanPostProcessor(seataFeignObjectWrapper); - } - - @Bean - SeataContextBeanPostProcessor seataContextBeanPostProcessor( - BeanFactory beanFactory) { - return new SeataContextBeanPostProcessor(beanFactory); - } - - @Bean - SeataFeignObjectWrapper seataFeignObjectWrapper(BeanFactory beanFactory) { - return new SeataFeignObjectWrapper(beanFactory); - } - - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignContext.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignContext.java deleted file mode 100644 index b0723f5a..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignContext.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.seata.feign; - -import java.util.HashMap; -import java.util.Map; - -import feign.Client; - -import org.springframework.cloud.openfeign.FeignContext; - -/** - * @author xiaojing - */ -public class SeataFeignContext extends FeignContext { - - private final SeataFeignObjectWrapper seataFeignObjectWrapper; - - private final FeignContext delegate; - - SeataFeignContext(SeataFeignObjectWrapper seataFeignObjectWrapper, - FeignContext delegate) { - this.seataFeignObjectWrapper = seataFeignObjectWrapper; - this.delegate = delegate; - } - - @Override - public T getInstance(String name, Class type) { - T object = this.delegate.getInstance(name, type); - if (object instanceof Client) { - return object; - } - return (T) this.seataFeignObjectWrapper.wrap(object); - } - - @Override - public Map getInstances(String name, Class type) { - Map instances = this.delegate.getInstances(name, type); - if (instances == null) { - return null; - } - Map convertedInstances = new HashMap<>(); - for (Map.Entry entry : instances.entrySet()) { - if (entry.getValue() instanceof Client) { - convertedInstances.put(entry.getKey(), entry.getValue()); - } - else { - convertedInstances.put(entry.getKey(), - (T) this.seataFeignObjectWrapper.wrap(entry.getValue())); - } - } - return convertedInstances; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java deleted file mode 100644 index 431d654e..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.seata.feign; - -import feign.Client; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; -import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory; -import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; - -/** - * @author xiaojing - */ -public class SeataFeignObjectWrapper { - - private static final Log LOG = LogFactory.getLog(SeataFeignObjectWrapper.class); - - private final BeanFactory beanFactory; - - private CachingSpringLoadBalancerFactory cachingSpringLoadBalancerFactory; - - private SpringClientFactory springClientFactory; - - SeataFeignObjectWrapper(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - Object wrap(Object bean) { - if (bean instanceof Client && !(bean instanceof SeataFeignClient)) { - if (bean instanceof LoadBalancerFeignClient) { - LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean); - return new SeataLoadBalancerFeignClient(client.getDelegate(), factory(), - clientFactory(), this); - } - return new SeataFeignClient(this.beanFactory, (Client) bean); - } - return bean; - } - - CachingSpringLoadBalancerFactory factory() { - if (this.cachingSpringLoadBalancerFactory == null) { - this.cachingSpringLoadBalancerFactory = this.beanFactory - .getBean(CachingSpringLoadBalancerFactory.class); - } - return this.cachingSpringLoadBalancerFactory; - } - - SpringClientFactory clientFactory() { - if (this.springClientFactory == null) { - this.springClientFactory = this.beanFactory - .getBean(SpringClientFactory.class); - } - return this.springClientFactory; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataLoadBalancerFeignClient.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataLoadBalancerFeignClient.java deleted file mode 100644 index 8204fed8..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataLoadBalancerFeignClient.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.seata.feign; - -import java.io.IOException; - -import feign.Client; -import feign.Request; -import feign.Response; - -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; -import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory; -import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; - -/** - * @author xiaojing - * @author yuhuangbin - */ -public class SeataLoadBalancerFeignClient extends LoadBalancerFeignClient { - - SeataLoadBalancerFeignClient(Client delegate, - CachingSpringLoadBalancerFactory lbClientFactory, - SpringClientFactory clientFactory, - SeataFeignObjectWrapper seataFeignObjectWrapper) { - super((Client) seataFeignObjectWrapper.wrap(delegate), lbClientFactory, - clientFactory); - } - - @Override - public Response execute(Request request, Request.Options options) throws IOException { - return super.execute(request, options); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/hystrix/SeataHystrixConcurrencyStrategy.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/hystrix/SeataHystrixConcurrencyStrategy.java index 2aa507bd..d0a1528b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/hystrix/SeataHystrixConcurrencyStrategy.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/hystrix/SeataHystrixConcurrencyStrategy.java @@ -36,6 +36,7 @@ import io.seata.core.context.RootContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @@ -156,11 +157,15 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy public K call() throws Exception { try { RequestContextHolder.setRequestAttributes(requestAttributes); - RootContext.bind(xid); + if (!StringUtils.isEmpty(xid)) { + RootContext.bind(xid); + } return actual.call(); } finally { - RootContext.unbind(); + if (!StringUtils.isEmpty(xid)) { + RootContext.unbind(); + } RequestContextHolder.resetRequestAttributes(); } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateAutoConfiguration.java index 68f1ff7d..7f82288f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/rest/SeataRestTemplateAutoConfiguration.java @@ -14,12 +14,12 @@ * limitations under the License. */ + package com.alibaba.cloud.seata.rest; import java.util.ArrayList; import java.util.Collection; import java.util.List; - import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; @@ -35,16 +35,17 @@ import org.springframework.web.client.RestTemplate; @Configuration public class SeataRestTemplateAutoConfiguration { - @Autowired(required = false) - private Collection restTemplates; - @Autowired - private SeataRestTemplateInterceptor seataRestTemplateInterceptor; - @Bean public SeataRestTemplateInterceptor seataRestTemplateInterceptor() { return new SeataRestTemplateInterceptor(); } + @Autowired(required = false) + private Collection restTemplates; + + @Autowired + private SeataRestTemplateInterceptor seataRestTemplateInterceptor; + @PostConstruct public void init() { if (this.restTemplates != null) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java index bc1e76de..f7ec7659 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java @@ -30,10 +30,10 @@ import org.springframework.web.servlet.HandlerInterceptor; * @author xiaojing * * Seata HandlerInterceptor, Convert Seata information into - * @see RootContext from http request's header in - * {@link HandlerInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object )}, + * @see io.seata.core.context.RootContext from http request's header in + * {@link org.springframework.web.servlet.HandlerInterceptor#preHandle(HttpServletRequest , HttpServletResponse , Object )}, * And clean up Seata information after servlet method invocation in - * {@link HandlerInterceptor#afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)} + * {@link org.springframework.web.servlet.HandlerInterceptor#afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)} */ public class SeataHandlerInterceptor implements HandlerInterceptor { @@ -43,7 +43,6 @@ public class SeataHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - String xid = RootContext.getXID(); String rpcXid = request.getHeader(RootContext.KEY_XID); if (log.isDebugEnabled()) { @@ -56,6 +55,7 @@ public class SeataHandlerInterceptor implements HandlerInterceptor { log.debug("bind {} to RootContext", rpcXid); } } + return true; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/spring.factories index 54b578ae..5214e379 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/resources/META-INF/spring.factories @@ -1,6 +1,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.cloud.seata.rest.SeataRestTemplateAutoConfiguration,\ com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration,\ -com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration,\ com.alibaba.cloud.seata.feign.hystrix.SeataHystrixAutoConfiguration diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java index d4397b22..921cb518 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelProperties.java @@ -232,8 +232,9 @@ public class SentinelProperties { private String blockPage; @Deprecated - @DeprecatedConfigurationProperty(reason = "replaced to SentinelProperties#blockPage.", replacement = SentinelConstants.PROPERTY_PREFIX - + ".block-page") + @DeprecatedConfigurationProperty( + reason = "replaced to SentinelProperties#blockPage.", + replacement = SentinelConstants.PROPERTY_PREFIX + ".block-page") public String getBlockPage() { return blockPage; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java index 8f55d3fd..54d2dff1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java @@ -83,14 +83,16 @@ public class SentinelWebAutoConfiguration implements WebMvcConfigurer { } @Bean - @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", + matchIfMissing = true) public SentinelWebInterceptor sentinelWebInterceptor( SentinelWebMvcConfig sentinelWebMvcConfig) { return new SentinelWebInterceptor(sentinelWebMvcConfig); } @Bean - @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", + matchIfMissing = true) public SentinelWebMvcConfig sentinelWebMvcConfig() { SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig(); sentinelWebMvcConfig.setHttpMethodSpecify(properties.getHttpMethodSpecify()); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebFluxAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebFluxAutoConfiguration.java index 57f297b3..e42133c3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebFluxAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebFluxAutoConfiguration.java @@ -77,14 +77,16 @@ public class SentinelWebFluxAutoConfiguration { @Bean @Order(-2) - @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", + matchIfMissing = true) public SentinelBlockExceptionHandler sentinelBlockExceptionHandler() { return new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } @Bean @Order(-1) - @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", + matchIfMissing = true) public SentinelWebFluxFilter sentinelWebFluxFilter() { log.info("[Sentinel Starter] register Sentinel SentinelWebFluxFilter"); return new SentinelWebFluxFilter(); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/BlockClassRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/BlockClassRegistry.java index b07aeb57..a7dc09ba 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/BlockClassRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/BlockClassRegistry.java @@ -27,7 +27,9 @@ import com.alibaba.csp.sentinel.util.StringUtil; */ final class BlockClassRegistry { + private static final Map FALLBACK_MAP = new ConcurrentHashMap<>(); + private static final Map BLOCK_HANDLER_MAP = new ConcurrentHashMap<>(); private static final Map URL_CLEANER_MAP = new ConcurrentHashMap<>(); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java index 2089d0e6..8dd4f39f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelAutoConfiguration.java @@ -145,7 +145,8 @@ public class SentinelAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - @ConditionalOnProperty(name = "resttemplate.sentinel.enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(name = "resttemplate.sentinel.enabled", havingValue = "true", + matchIfMissing = true) public SentinelBeanPostProcessor sentinelBeanPostProcessor( ApplicationContext applicationContext) { return new SentinelBeanPostProcessor(applicationContext); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandler.java index 963c612a..2de7727c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandler.java @@ -52,14 +52,21 @@ public class SentinelDataSourceHandler implements SmartInitializingSingleton { private static final Logger log = LoggerFactory .getLogger(SentinelDataSourceHandler.class); - private final String DATA_TYPE_FIELD = "dataType"; - private final String CUSTOM_DATA_TYPE = "custom"; - private final String CONVERTER_CLASS_FIELD = "converterClass"; - private final DefaultListableBeanFactory beanFactory; - private final SentinelProperties sentinelProperties; - private final Environment env; + private List dataTypeList = Arrays.asList("json", "xml"); + private final String DATA_TYPE_FIELD = "dataType"; + + private final String CUSTOM_DATA_TYPE = "custom"; + + private final String CONVERTER_CLASS_FIELD = "converterClass"; + + private final DefaultListableBeanFactory beanFactory; + + private final SentinelProperties sentinelProperties; + + private final Environment env; + public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory, SentinelProperties sentinelProperties, Environment env) { this.beanFactory = beanFactory; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpointAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpointAutoConfiguration.java index caa5afd2..f88457ef 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpointAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelEndpointAutoConfiguration.java @@ -19,6 +19,7 @@ package com.alibaba.cloud.sentinel.endpoint; import com.alibaba.cloud.sentinel.SentinelProperties; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +//import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java index ea8aacd0..c2031c62 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java @@ -76,7 +76,9 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator { // detail if (!sentinelProperties.isEnabled()) { detailMap.put("enabled", false); - withDetails(builder.up(), detailMap); + detailMap.forEach((key, value)->{ + builder.up().withDetail(key, value); + }); return; } @@ -144,16 +146,15 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator { // If Dashboard and DataSource are both OK, the health status is UP if (dashboardUp && dataSourceUp) { - withDetails(builder.up(), detailMap); + detailMap.forEach((key, value)->{ + builder.up().withDetail(key, value); + }); } else { - withDetails(builder.unknown(), detailMap); + detailMap.forEach((key, value)->{ + builder.unknown().withDetail(key, value); + }); } } - private void withDetails(Health.Builder builder, Map detailMap) { - for (String key : detailMap.keySet()) { - builder.withDetail(key, detailMap.get(key)); - } - } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelContractHolder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelContractHolder.java index cf0716c7..9a5acfd3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelContractHolder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelContractHolder.java @@ -32,12 +32,13 @@ import feign.MethodMetadata; */ public class SentinelContractHolder implements Contract { + private final Contract delegate; + /** * map key is constructed by ClassFullName + configKey. configKey is constructed by * {@link feign.Feign#configKey} */ public final static Map METADATA_MAP = new HashMap<>(); - private final Contract delegate; public SentinelContractHolder(Contract delegate) { this.delegate = delegate; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java index a9b4e066..1b66996b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java @@ -80,8 +80,7 @@ public class SentinelInvocationHandler implements InvocationHandler { if ("equals".equals(method.getName())) { try { Object otherHandler = args.length > 0 && args[0] != null - ? Proxy.getInvocationHandler(args[0]) - : null; + ? Proxy.getInvocationHandler(args[0]) : null; return equals(otherHandler); } catch (IllegalArgumentException e) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 49b06b0d..fe001b9a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -24,7 +24,14 @@ "defaultValue": true, "description": "Specify whether unify web context(i.e. use the default context name), and is true by default." }, - { "name": "spring.cloud.sentinel.transport.port", + { + "name": "spring.cloud.sentinel.web-context-unify", + "type": "java.lang.Boolean", + "defaultValue": true, + "description": "Specify whether unify web context(i.e. use the default context name), and is true by default." + }, + { + "name": "spring.cloud.sentinel.transport.port", "type": "java.lang.String", "defaultValue": "8719", "description": "sentinel api port." diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java index f79c1e18..56c5bf6b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java @@ -63,9 +63,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen * @author jiashuai.xie */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = { - SentinelAutoConfigurationTests.TestConfig.class }, properties = { - "spring.cloud.sentinel.filter.order=123", +@SpringBootTest(classes = { SentinelAutoConfigurationTests.TestConfig.class }, + properties = { "spring.cloud.sentinel.filter.order=123", "spring.cloud.sentinel.filter.urlPatterns=/*,/test", "spring.cloud.sentinel.metric.fileSingleSize=9999", "spring.cloud.sentinel.metric.fileTotalCount=100", @@ -76,7 +75,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen "spring.cloud.sentinel.transport.dashboard=http://localhost:8080,http://localhost:8081", "spring.cloud.sentinel.transport.port=9999", "spring.cloud.sentinel.transport.clientIp=1.1.1.1", - "spring.cloud.sentinel.transport.heartbeatIntervalMs=20000" }, webEnvironment = RANDOM_PORT) + "spring.cloud.sentinel.transport.heartbeatIntervalMs=20000" }, + webEnvironment = RANDOM_PORT) public class SentinelAutoConfigurationTests { @Autowired @@ -239,13 +239,15 @@ public class SentinelAutoConfigurationTests { } @Bean - @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException") + @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, + blockHandler = "handleException") RestTemplate restTemplateWithBlockClass() { return new RestTemplate(); } @Bean - @SentinelRestTemplate(fallbackClass = ExceptionUtil.class, fallback = "fallbackException") + @SentinelRestTemplate(fallbackClass = ExceptionUtil.class, + fallback = "fallbackException") RestTemplate restTemplateWithFallbackClass() { return new RestTemplate(); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFeignTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFeignTests.java index 9b6228a9..ad0b5929 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFeignTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelFeignTests.java @@ -45,8 +45,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Jim */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = { SentinelFeignTests.TestConfig.class }, properties = { - "feign.sentinel.enabled=true" }) +@SpringBootTest(classes = { SentinelFeignTests.TestConfig.class }, + properties = { "feign.sentinel.enabled=true" }) public class SentinelFeignTests { @Autowired @@ -118,22 +118,6 @@ public class SentinelFeignTests { assertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE); } - @FeignClient(value = "test-service", fallback = EchoServiceFallback.class) - public interface EchoService { - - @RequestMapping(path = "echo/{str}") - String echo(@RequestParam("str") String param); - - } - - @FeignClient(value = "foo-service", fallbackFactory = CustomFallbackFactory.class) - public interface FooService { - - @RequestMapping(path = "echo/{str}") - String echo(@RequestParam("str") String param); - - } - @FeignClient("bar-service") public interface BarService { @@ -172,6 +156,23 @@ public class SentinelFeignTests { } + @FeignClient(value = "test-service", fallback = EchoServiceFallback.class) + public interface EchoService { + + @RequestMapping(path = "echo/{str}") + String echo(@RequestParam("str") String param); + + } + + @FeignClient(value = "foo-service", fallbackFactory = CustomFallbackFactory.class) + public interface FooService { + + @RequestMapping(path = "echo/{str}") + String echo(@RequestParam("str") String param); + + } + + public static class EchoServiceFallback implements EchoService { @Override diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java index 1e1dc040..f2560ab9 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelRestTemplateTests.java @@ -20,6 +20,7 @@ import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate; import com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor; import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse; import com.alibaba.csp.sentinel.slots.block.BlockException; + import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; @@ -188,7 +189,7 @@ public class SentinelRestTemplateTests { } @Bean - @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException", fallbackClass = ExceptionUtil.class, fallback = "fallbackException", urlCleanerClass = UrlCleanUtil.class, urlCleaner = "clean") + @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException", fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class, fallback = "fallbackException", urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean") RestTemplate restTemplate() { return new RestTemplate(); } @@ -205,7 +206,7 @@ public class SentinelRestTemplateTests { } @Bean - @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException1") + @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException1") RestTemplate restTemplate() { return new RestTemplate(); } @@ -239,7 +240,7 @@ public class SentinelRestTemplateTests { } @Bean - @SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException2") + @SentinelRestTemplate(blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class, blockHandler = "handleException2") RestTemplate restTemplate() { return new RestTemplate(); } @@ -330,7 +331,7 @@ public class SentinelRestTemplateTests { } @Bean - @SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class, urlCleaner = "clean1") + @SentinelRestTemplate(urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean1") RestTemplate restTemplate() { return new RestTemplate(); } @@ -347,13 +348,19 @@ public class SentinelRestTemplateTests { } @Bean - @SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class, urlCleaner = "clean2") + @SentinelRestTemplate(urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class, urlCleaner = "clean2") RestTemplate restTemplate() { return new RestTemplate(); } } + @Bean + @SentinelRestTemplate + RestTemplate restTemplate2() { + return new RestTemplate(); + } + public static class ExceptionUtil { public static SentinelClientHttpResponse handleException(HttpRequest request, @@ -390,5 +397,4 @@ public class SentinelRestTemplateTests { } } - } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/pom.xml deleted file mode 100644 index 9b44217d..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - com.alibaba.cloud - spring-cloud-alibaba-starters - ${revision} - ../pom.xml - - - 4.0.0 - - spring-cloud-starter-alibaba-sidecar - Spring Cloud Starter Alibaba Sidecar - - - - org.springframework.boot - spring-boot-starter - true - - - - org.springframework.cloud - spring-cloud-starter-gateway - true - - - - org.springframework.boot - spring-boot-starter-actuator - true - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - true - - - - org.springframework.cloud - spring-cloud-starter-consul-discovery - true - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarAutoConfiguration.java deleted file mode 100644 index 6343548b..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarAutoConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar; - -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.web.client.RestTemplate; - -/** - * @author www.itmuch.com - */ -@Configuration -public class SidecarAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Bean - @ConditionalOnEnabledHealthIndicator("sidecar") - public SidecarHealthIndicator sidecarHealthIndicator( - SidecarProperties sidecarProperties, RestTemplate restTemplate) { - return new SidecarHealthIndicator(sidecarProperties, restTemplate); - } - - @Bean - public SidecarHealthChecker sidecarHealthChecker( - SidecarDiscoveryClient sidecarDiscoveryClient, - SidecarHealthIndicator sidecarHealthIndicator, - SidecarProperties sidecarProperties, ConfigurableEnvironment environment) { - SidecarHealthChecker cleaner = new SidecarHealthChecker(sidecarDiscoveryClient, - sidecarHealthIndicator, sidecarProperties, environment); - cleaner.check(); - return cleaner; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarDiscoveryClient.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarDiscoveryClient.java deleted file mode 100644 index 8a67c575..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarDiscoveryClient.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar; - -/** - * @author www.itmuch.com - */ -public interface SidecarDiscoveryClient { - - /** - * register instance. - * @param applicationName applicationName - * @param ip ip - * @param port port - */ - void registerInstance(String applicationName, String ip, Integer port); - - /** - * deregister instance. - * @param applicationName applicationName - * @param ip ip - * @param port port - */ - void deregisterInstance(String applicationName, String ip, Integer port); - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java deleted file mode 100644 index fabccd12..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import reactor.core.scheduler.Schedulers; - -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.Status; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * @author www.itmuch.com - * @author yuhuangbin - */ -public class SidecarHealthChecker { - - private static final Logger log = LoggerFactory.getLogger(SidecarHealthChecker.class); - - private final Map sidecarInstanceCacheMap = new ConcurrentHashMap<>(); - - private final SidecarDiscoveryClient sidecarDiscoveryClient; - - private final HealthIndicator healthIndicator; - - private final SidecarProperties sidecarProperties; - - private final ConfigurableEnvironment environment; - - public SidecarHealthChecker(SidecarDiscoveryClient sidecarDiscoveryClient, - HealthIndicator healthIndicator, SidecarProperties sidecarProperties, - ConfigurableEnvironment environment) { - this.sidecarDiscoveryClient = sidecarDiscoveryClient; - this.healthIndicator = healthIndicator; - this.sidecarProperties = sidecarProperties; - this.environment = environment; - } - - public void check() { - Schedulers.single().schedulePeriodically(() -> { - String applicationName = environment.getProperty("spring.application.name"); - String ip = sidecarProperties.getIp(); - Integer port = sidecarProperties.getPort(); - - Status status = healthIndicator.health().getStatus(); - - instanceCache(applicationName, ip, port, status); - if (status.equals(Status.UP)) { - if (needRegister(applicationName, ip, port, status)) { - this.sidecarDiscoveryClient.registerInstance(applicationName, ip, - port); - log.info( - "Polyglot service changed and Health check success. register the new instance. applicationName = {}, ip = {}, port = {}, status = {}", - applicationName, ip, port, status); - } - } - else { - log.warn( - "Health check failed. unregister this instance. applicationName = {}, ip = {}, port = {}, status = {}", - applicationName, ip, port, status); - this.sidecarDiscoveryClient.deregisterInstance(applicationName, ip, port); - sidecarInstanceCacheMap.put(applicationName, - buildCache(ip, port, status)); - } - - }, 0, sidecarProperties.getHealthCheckInterval(), TimeUnit.MILLISECONDS); - } - - private void instanceCache(String applicationName, String ip, Integer port, - Status status) { - sidecarInstanceCacheMap.putIfAbsent(applicationName, - buildCache(ip, port, status)); - } - - private boolean needRegister(String applicationName, String ip, Integer port, - Status status) { - SidecarInstanceCache cacheRecord = sidecarInstanceCacheMap.get(applicationName); - SidecarInstanceCache cache = buildCache(ip, port, status); - - if (!Objects.equals(cache, cacheRecord)) { - // modify the cache info - sidecarInstanceCacheMap.put(applicationName, cache); - return true; - } - return false; - } - - private SidecarInstanceCache buildCache(String ip, Integer port, Status status) { - SidecarInstanceCache cache = new SidecarInstanceCache(); - cache.setIp(ip); - cache.setPort(port); - cache.setStatus(status); - return cache; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthIndicator.java deleted file mode 100644 index 4d07a380..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthIndicator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar; - -import java.net.URI; -import java.util.Map; - -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; - -/** - * @author www.itmuch.com - */ -public class SidecarHealthIndicator extends AbstractHealthIndicator { - - private final SidecarProperties sidecarProperties; - - private final RestTemplate restTemplate; - - public SidecarHealthIndicator(SidecarProperties sidecarProperties, - RestTemplate restTemplate) { - this.sidecarProperties = sidecarProperties; - this.restTemplate = restTemplate; - } - - @Override - protected void doHealthCheck(Health.Builder builder) throws Exception { - try { - URI uri = this.sidecarProperties.getHealthCheckUrl(); - if (uri == null) { - builder.up(); - return; - } - - ResponseEntity> exchange = this.restTemplate.exchange(uri, - HttpMethod.GET, null, - new ParameterizedTypeReference>() { - }); - - Map map = exchange.getBody(); - - if (map == null) { - this.getWarning(builder); - return; - } - Object status = map.get("status"); - if (status instanceof String) { - builder.status(status.toString()); - } - else { - this.getWarning(builder); - } - } - catch (Exception e) { - builder.down().withDetail("error", e.getMessage()); - } - } - - private void getWarning(Health.Builder builder) { - builder.unknown().withDetail("warning", "no status field in response"); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceCache.java deleted file mode 100644 index 0c18f1aa..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceCache.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar; - -import java.util.Objects; - -import org.springframework.boot.actuate.health.Status; - -/** - * @author yuhuangbin - */ -public class SidecarInstanceCache { - - private String ip; - - private Integer port; - - private Status status; - - public String getIp() { - return ip; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SidecarInstanceCache that = (SidecarInstanceCache) o; - return Objects.equals(ip, that.ip) && Objects.equals(port, that.port) - && Objects.equals(status, that.status); - } - - @Override - public int hashCode() { - return Objects.hash(ip, port, status); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarProperties.java deleted file mode 100644 index b95f9189..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarProperties.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar; - -import java.net.URI; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -/** - * @author www.itmuch.com - */ -@ConfigurationProperties("sidecar") -@Validated -public class SidecarProperties { - - /** - * polyglot service's ip. - */ - private String ip; - - /** - * polyglot service's port. - */ - @NotNull - @Max(65535) - @Min(1) - private Integer port; - - /** - * polyglot service's health check url. this endpoint must return json and the format - * must follow spring boot actuator's health endpoint. eg. {"status": "UP"}. - */ - private URI healthCheckUrl; - - /** - * interval of health check. - */ - private long healthCheckInterval = 30000L; - - public String getIp() { - return ip; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public URI getHealthCheckUrl() { - return healthCheckUrl; - } - - public void setHealthCheckUrl(URI healthCheckUrl) { - this.healthCheckUrl = healthCheckUrl; - } - - public long getHealthCheckInterval() { - return healthCheckInterval; - } - - public void setHealthCheckInterval(long healthCheckInterval) { - this.healthCheckInterval = healthCheckInterval; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosAutoConfiguration.java deleted file mode 100644 index feaf86fe..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosAutoConfiguration.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar.nacos; - -import com.alibaba.cloud.nacos.NacosDiscoveryProperties; -import com.alibaba.cloud.nacos.NacosServiceManager; -import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration; -import com.alibaba.cloud.sidecar.SidecarAutoConfiguration; -import com.alibaba.cloud.sidecar.SidecarDiscoveryClient; -import com.alibaba.cloud.sidecar.SidecarProperties; - -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author www.itmuch.com - */ -@Configuration -@AutoConfigureBefore({ NacosDiscoveryAutoConfiguration.class, - SidecarAutoConfiguration.class }) -@ConditionalOnClass(NacosDiscoveryProperties.class) -@EnableConfigurationProperties(SidecarProperties.class) -public class SidecarNacosAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties( - SidecarProperties sidecarProperties) { - return new SidecarNacosDiscoveryProperties(sidecarProperties); - } - - @Bean - @ConditionalOnMissingBean - public SidecarDiscoveryClient sidecarDiscoveryClient( - NacosServiceManager nacosServiceManager, - SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) { - return new SidecarNacosDiscoveryClient(nacosServiceManager, - sidecarNacosDiscoveryProperties); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryClient.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryClient.java deleted file mode 100644 index 0c32fde4..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryClient.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar.nacos; - -import com.alibaba.cloud.nacos.NacosServiceManager; -import com.alibaba.cloud.sidecar.SidecarDiscoveryClient; -import com.alibaba.nacos.api.exception.NacosException; -import com.alibaba.nacos.api.naming.NamingService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author www.itmuch.com - */ -public class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient { - - private static final Logger log = LoggerFactory - .getLogger(SidecarNacosDiscoveryClient.class); - private final SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties; - private NacosServiceManager nacosServiceManager; - - public SidecarNacosDiscoveryClient(NacosServiceManager nacosServiceManager, - SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) { - this.sidecarNacosDiscoveryProperties = sidecarNacosDiscoveryProperties; - } - - @Override - public void registerInstance(String applicationName, String ip, Integer port) { - try { - this.namingService().registerInstance(applicationName, - sidecarNacosDiscoveryProperties.getGroup(), ip, port); - } - catch (NacosException e) { - log.warn("nacos exception happens", e); - } - } - - @Override - public void deregisterInstance(String applicationName, String ip, Integer port) { - try { - this.namingService().deregisterInstance(applicationName, - sidecarNacosDiscoveryProperties.getGroup(), ip, port); - } - catch (NacosException e) { - log.warn("nacos exception happens", e); - } - } - - private NamingService namingService() { - return nacosServiceManager - .getNamingService(sidecarNacosDiscoveryProperties.getNacosProperties()); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryProperties.java deleted file mode 100644 index a6c5a978..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/nacos/SidecarNacosDiscoveryProperties.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.cloud.sidecar.nacos; - -import com.alibaba.cloud.nacos.NacosDiscoveryProperties; -import com.alibaba.cloud.sidecar.SidecarProperties; - -import org.springframework.util.StringUtils; - -/** - * @author itmuch.com - * @author yuhuangbin - */ -public class SidecarNacosDiscoveryProperties extends NacosDiscoveryProperties { - - SidecarProperties sidecarProperties; - - public SidecarNacosDiscoveryProperties(SidecarProperties sidecarProperties) { - this.sidecarProperties = sidecarProperties; - } - - @Override - public void init() throws Exception { - super.init(); - - String ip = sidecarProperties.getIp(); - if (!StringUtils.isEmpty(ip)) { - this.setIp(ip); - } - - Integer port = sidecarProperties.getPort(); - this.setPort(port); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 726e9382..00000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,4 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.alibaba.cloud.sidecar.nacos.SidecarNacosAutoConfiguration,\ - com.alibaba.cloud.sidecar.SidecarAutoConfiguration,\ - com.alibaba.cloud.sidecar.consul.SidecarConsulAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml index 6fba3f2d..34b013b7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml @@ -1,6 +1,6 @@ - @@ -91,7 +91,7 @@ org.apache.zookeeper zookeeper - 3.4.12 + 3.4.14 true diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/annotation/DubboTransported.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/annotation/DubboTransported.java index 6a97fcc7..efe083ea 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/annotation/DubboTransported.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/annotation/DubboTransported.java @@ -37,11 +37,16 @@ import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RETRIES; * Spring Cloud Service-to-Service call is transported by Dubbo under the hood, there are * two main scenarios: *

    - *
  1. {@link FeignClient @FeignClient} annotated classes: If - * {@link DubboTransported @DubboTransported} annotated classes, the invocation of all - * methods of {@link FeignClient @FeignClient} annotated classes. If - * {@link DubboTransported @DubboTransported} annotated methods of - * {@link FeignClient @FeignClient} annotated classes.
  2. + *
  3. {@link FeignClient @FeignClient} annotated classes: + *
      + * If {@link DubboTransported @DubboTransported} annotated classes, the invocation of all + * methods of {@link FeignClient @FeignClient} annotated classes. + *
    + *
      + * If {@link DubboTransported @DubboTransported} annotated methods of + * {@link FeignClient @FeignClient} annotated classes. + *
    + *
  4. *
  5. {@link LoadBalanced @LoadBalanced} {@link RestTemplate} annotated field, method and * parameters
  6. *
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java index b0bdd5f5..23b7987d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java @@ -111,8 +111,7 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements @Override public void afterSingletonsInstantiated() { loadBalancerInterceptorBean = retryLoadBalancerInterceptor != null - ? retryLoadBalancerInterceptor - : loadBalancerInterceptor; + ? retryLoadBalancerInterceptor : loadBalancerInterceptor; } /** @@ -146,7 +145,7 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements * Gets the annotation attributes {@link RestTemplate} bean being annotated * {@link DubboTransported @DubboTransported}. * @param beanName the bean name of {@link LoadBalanced @LoadBalanced} - * {@link RestTemplate} + * {@link RestTemplate} * @param attributesResolver {@link DubboTransportedAttributesResolver} * @return non-null {@link Map} */ @@ -171,8 +170,8 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements * {@link LoadBalancerInterceptor} Bean. * @param restTemplate {@link LoadBalanced @LoadBalanced} {@link RestTemplate} Bean * @param dubboTranslatedAttributes the annotation dubboTranslatedAttributes - * {@link RestTemplate} bean being annotated - * {@link DubboTransported @DubboTransported} + * {@link RestTemplate} bean being annotated + * {@link DubboTransported @DubboTransported} */ private void adaptRestTemplate(RestTemplate restTemplate, Map dubboTranslatedAttributes) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java index c0be4eae..e378e753 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java @@ -35,8 +35,8 @@ import static com.alibaba.cloud.dubbo.autoconfigure.DubboOpenFeignAutoConfigurat * @author Mercy */ @ConditionalOnClass(name = { "feign.Feign", TARGETER_CLASS_NAME }) -@AutoConfigureAfter(name = { - "org.springframework.cloud.openfeign.FeignAutoConfiguration" }) +@AutoConfigureAfter( + name = { "org.springframework.cloud.openfeign.FeignAutoConfiguration" }) @Configuration public class DubboOpenFeignAutoConfiguration { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java index 6e491425..cf1236f6 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceDiscoveryAutoConfiguration.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.dubbo.autoconfigure; +import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -98,11 +99,12 @@ import static org.springframework.util.StringUtils.hasText; @Configuration @ConditionalOnClass(name = "org.springframework.cloud.client.discovery.DiscoveryClient") @ConditionalOnProperty(name = "spring.cloud.discovery.enabled", matchIfMissing = true) -@AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME, - ZOOKEEPER_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME, - CONSUL_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME, - NACOS_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME }, value = { - DubboServiceRegistrationAutoConfiguration.class }) +@AutoConfigureAfter( + name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME, + ZOOKEEPER_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME, + CONSUL_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME, + NACOS_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME }, + value = { DubboServiceRegistrationAutoConfiguration.class }) public class DubboServiceDiscoveryAutoConfiguration { /** @@ -202,7 +204,7 @@ public class DubboServiceDiscoveryAutoConfiguration { * {@link #defaultHeartbeatEventChangePredicate()} method providers the default * implementation to detect whether the {@link HeartbeatEvent#getValue() state} is * changed or not. If and only if changed, the - * {@link #dispatchServiceInstancesChangedEvent(String, List)} will be executed. + * {@link #dispatchServiceInstancesChangedEvent(String, Collection)} will be executed. *

* Note : Spring Cloud {@link HeartbeatEvent} has a critical flaw that can't * figure out which service was changed precisely, it's just used for a notification @@ -361,7 +363,7 @@ public class DubboServiceDiscoveryAutoConfiguration { /** * Zookeeper uses {@link TreeCacheEvent} to trigger - * {@link #dispatchServiceInstancesChangedEvent(String, List)} , thus + * {@link #dispatchServiceInstancesChangedEvent(String, Collection)} , thus * {@link HeartbeatEvent} handle is always ignored. * @return false forever */ @@ -429,7 +431,7 @@ public class DubboServiceDiscoveryAutoConfiguration { } /** - * Try to {@link #dispatchServiceInstancesChangedEvent(String, List) + * Try to {@link #dispatchServiceInstancesChangedEvent(String, Collection) * dispatch} {@link ServiceInstancesChangedEvent} before * {@link ZookeeperServiceWatch#childEvent(CuratorFramework, TreeCacheEvent)} * execution if required. @@ -527,7 +529,7 @@ public class DubboServiceDiscoveryAutoConfiguration { /** * Nacos uses {@link EventListener} to trigger. - * {@link #dispatchServiceInstancesChangedEvent(String, List)} , thus + * {@link #dispatchServiceInstancesChangedEvent(String, Collection)} , thus * {@link HeartbeatEvent} handle is always ignored * @return false forever */ diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java index 3415bcee..9f670916 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java @@ -16,22 +16,31 @@ package com.alibaba.cloud.dubbo.autoconfigure; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME; +import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; +import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.ADDRESS; +import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.PROTOCOL; +import static org.springframework.util.ObjectUtils.isEmpty; import com.alibaba.cloud.dubbo.autoconfigure.condition.MissingSpringCloudRegistryConfigPropertyCondition; +import com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapStartCommandLineRunner; +import com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapWrapper; +import com.alibaba.cloud.dubbo.bootstrap.event.DubboBootstrapStartedEvent; import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; import com.alibaba.cloud.dubbo.registry.DubboServiceRegistrationEventPublishingAspect; +import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreDeregisteredEvent; import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreRegisteredEvent; import com.ecwid.consul.v1.agent.model.NewService; import com.netflix.appinfo.InstanceInfo; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; import org.apache.dubbo.config.spring.ServiceBean; -import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.SmartInitializingSingleton; @@ -42,7 +51,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; +import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry; @@ -53,19 +64,15 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.event.EventListener; -import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME; -import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; -import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.ADDRESS; -import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.PROTOCOL; -import static org.springframework.util.ObjectUtils.isEmpty; - /** * Dubbo Service Registration Auto-{@link Configuration}. * * @author Mercy + * @author theonefx */ @Configuration -@Import({ DubboServiceRegistrationEventPublishingAspect.class }) +@Import({ DubboServiceRegistrationEventPublishingAspect.class, + DubboBootstrapStartCommandLineRunner.class }) @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME, CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME, @@ -105,10 +112,41 @@ public class DubboServiceRegistrationAutoConfiguration { return new RegistryConfig(ADDRESS, PROTOCOL); } + private Map, Set> registrations = new ConcurrentHashMap<>(); + + @EventListener(DubboBootstrapStartedEvent.class) + public void onDubboBootstrapStarted(DubboBootstrapStartedEvent event) { + if (!event.getSource().isReady()) { + return; + } + registrations.forEach( + (registry, registrations) -> registrations.forEach(registration -> { + attachDubboMetadataServiceMetadata(registration); + registry.register(registration); + })); + } + @EventListener(ServiceInstancePreRegisteredEvent.class) public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) { Registration registration = event.getSource(); - attachDubboMetadataServiceMetadata(registration); + if (!DubboBootstrap.getInstance().isStarted()) { + ServiceRegistry registry = event.getRegistry(); + synchronized (registry) { + registrations.putIfAbsent(registry, new HashSet<>()); + registrations.get(registry).add(registration); + } + } + else { + attachDubboMetadataServiceMetadata(registration); + } + + } + + @EventListener(ServiceInstancePreDeregisteredEvent.class) + public void onServiceInstancePreDeregistered( + ServiceInstancePreDeregisteredEvent event) { + ServiceRegistry registry = event.getRegistry(); + registrations.remove(registry); } private void attachDubboMetadataServiceMetadata(Registration registration) { @@ -131,21 +169,66 @@ public class DubboServiceRegistrationAutoConfiguration { @Configuration @ConditionalOnBean(name = EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME) - @Aspect class EurekaConfiguration implements SmartInitializingSingleton { @Autowired private ObjectProvider> serviceBeans; + @EventListener(DubboBootstrapStartedEvent.class) + public void onDubboBootstrapStarted(DubboBootstrapStartedEvent event) { + DubboBootstrapWrapper wrapper = event.getSource(); + if (!wrapper.isReady()) { + return; + } + registrations.forEach( + (registry, registrations) -> registrations.removeIf(registration -> { + if (!(registration instanceof EurekaRegistration)) { + return false; + } + EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; + InstanceInfo instanceInfo = eurekaRegistration + .getApplicationInfoManager().getInfo(); + + EurekaInstanceConfigBean config = (EurekaInstanceConfigBean) eurekaRegistration + .getInstanceConfig(); + config.setInitialStatus(InstanceInfo.InstanceStatus.UP); + + attachDubboMetadataServiceMetadata(instanceInfo.getMetadata()); + eurekaRegistration.getApplicationInfoManager() + .registerAppMetadata(instanceInfo.getMetadata()); + eurekaRegistration.getApplicationInfoManager() + .setInstanceStatus(InstanceInfo.InstanceStatus.UP); + return true; + })); + } + @EventListener(ServiceInstancePreRegisteredEvent.class) public void onServiceInstancePreRegistered( ServiceInstancePreRegisteredEvent event) { Registration registration = event.getSource(); - EurekaRegistration eurekaRegistration = EurekaRegistration.class - .cast(registration); - InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager() - .getInfo(); - attachDubboMetadataServiceMetadata(instanceInfo.getMetadata()); + if (!(registration instanceof EurekaRegistration)) { + return; + } + + if (DubboBootstrap.getInstance().isStarted()) { + EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; + InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager() + .getInfo(); + + EurekaInstanceConfigBean config = (EurekaInstanceConfigBean) eurekaRegistration + .getInstanceConfig(); + config.setInitialStatus(InstanceInfo.InstanceStatus.UP); + + attachDubboMetadataServiceMetadata(instanceInfo.getMetadata()); + eurekaRegistration.getApplicationInfoManager() + .registerAppMetadata(instanceInfo.getMetadata()); + } + else { + EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; + EurekaInstanceConfigBean config = (EurekaInstanceConfigBean) eurekaRegistration + .getInstanceConfig(); + config.setInitialStatus(InstanceInfo.InstanceStatus.STARTING); + } } /** @@ -170,21 +253,28 @@ public class DubboServiceRegistrationAutoConfiguration { @AutoConfigureOrder class ConsulConfiguration { - /** - * Handle the pre-registered event of {@link ServiceInstance} for Consul. - * @param event {@link ServiceInstancePreRegisteredEvent} - */ - @EventListener(ServiceInstancePreRegisteredEvent.class) - public void onServiceInstancePreRegistered( - ServiceInstancePreRegisteredEvent event) { - Registration registration = event.getSource(); - Class registrationClass = AopUtils.getTargetClass(registration); - String registrationClassName = registrationClass.getName(); - if (CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME - .equalsIgnoreCase(registrationClassName)) { - ConsulRegistration consulRegistration = (ConsulRegistration) registration; - attachURLsIntoMetadata(consulRegistration); + @EventListener(DubboBootstrapStartedEvent.class) + public void attachURLsIntoMetadataBeforeReRegist( + DubboBootstrapStartedEvent event) { + if (!event.getSource().isReady()) { + return; } + registrations.entrySet().removeIf(entry -> { + Set registrations = entry.getValue(); + registrations.removeIf(registration -> { + Class registrationClass = AopUtils.getTargetClass(registration); + String registrationClassName = registrationClass.getName(); + return !CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME + .equalsIgnoreCase(registrationClassName); + }); + return registrations.isEmpty(); + }); + + registrations.forEach( + (registry, registrations) -> registrations.forEach(registration -> { + ConsulRegistration consulRegistration = (ConsulRegistration) registration; + attachURLsIntoMetadata(consulRegistration); + })); } private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboBootstrapStartCommandLineRunner.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboBootstrapStartCommandLineRunner.java new file mode 100644 index 00000000..9f47bb2e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboBootstrapStartCommandLineRunner.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.bootstrap; + +import com.alibaba.cloud.dubbo.bootstrap.event.DubboBootstrapStartedEvent; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.stereotype.Component; + +/** + * publish Dubbo microsystem startup finish event. + * + * @author theonefx + */ + +@Component +public class DubboBootstrapStartCommandLineRunner + implements CommandLineRunner, ApplicationEventPublisherAware { + + private ApplicationEventPublisher applicationEventPublisher; + + @Override + public void setApplicationEventPublisher( + ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + } + + @Override + public void run(String... args) { + applicationEventPublisher.publishEvent( + new DubboBootstrapStartedEvent(DubboBootstrapWrapper.getInstance())); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboBootstrapWrapper.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboBootstrapWrapper.java new file mode 100644 index 00000000..e8f71b35 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/DubboBootstrapWrapper.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.bootstrap; + +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +/** + * Wrapper DubboBootstrap operation. + * + * @author theonefx + */ +public final class DubboBootstrapWrapper { + + private DubboBootstrapWrapper() { + } + + private static final DubboBootstrapWrapper INSTANCE = new DubboBootstrapWrapper(); + + public static DubboBootstrapWrapper getInstance() { + return INSTANCE; + } + + public boolean isReady() { + return DubboBootstrap.getInstance().isStarted() + && DubboBootstrap.getInstance().isInitialized(); + } + + public DubboBootstrap getDubboBootstrap() { + return DubboBootstrap.getInstance(); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/event/DubboBootstrapStartedEvent.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/event/DubboBootstrapStartedEvent.java new file mode 100644 index 00000000..3f14525c --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/bootstrap/event/DubboBootstrapStartedEvent.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.bootstrap.event; + +import com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapWrapper; + +import org.springframework.context.ApplicationEvent; + +/** + * Dubbo microsytem start finish event, every thing is ready. + * + * @author theonefx + */ +public class DubboBootstrapStartedEvent extends ApplicationEvent { + + /** + * Create a new {@code DubboBootstrapStartedEvent}. + * @param source the object on which the event initially occurred or with which the + * event is associated (never {@code null}) + */ + public DubboBootstrapStartedEvent(DubboBootstrapWrapper source) { + super(source); + } + + @Override + public DubboBootstrapWrapper getSource() { + return (DubboBootstrapWrapper) super.getSource(); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java index 5af1e58f..faf9ef8b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboNonWebApplicationEnvironmentPostProcessor.java @@ -141,8 +141,7 @@ public class DubboNonWebApplicationEnvironmentPostProcessor DEFAULT_PROTOCOL); return isRestProtocol(protocol) - ? environment.getProperty(PROTOCOL_PORT_PROPERTY_NAME) - : null; + ? environment.getProperty(PROTOCOL_PORT_PROPERTY_NAME) : null; } private String getRestPortFromProtocolsProperties( diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestConsumersMatcher.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestConsumersMatcher.java index 90b0f115..e97f2559 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestConsumersMatcher.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestConsumersMatcher.java @@ -41,7 +41,7 @@ public class HttpRequestConsumersMatcher extends AbstractHttpRequestMatcher { /** * Creates a new instance from 0 or more "consumes" expressions. * @param consumes consumes expressions if 0 expressions are provided, the condition - * will match to every request + * will match to every request */ public HttpRequestConsumersMatcher(String... consumes) { this(consumes, null); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestParamsMatcher.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestParamsMatcher.java index fd9ab679..159c8746 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestParamsMatcher.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/http/matcher/HttpRequestParamsMatcher.java @@ -34,10 +34,10 @@ public class HttpRequestParamsMatcher extends AbstractHttpRequestMatcher { /** * @param params The pattern of params : - *

    - *
  • name=value
  • - *
  • name
  • - *
+ *
    + *
  • name=value
  • + *
  • name
  • + *
*/ public HttpRequestParamsMatcher(String... params) { this.expressions = parseExpressions(params); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index dbede698..be24b11f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -83,7 +83,7 @@ public class DubboCloudRegistry extends FailbackRegistry { /** * Caches the IDs of {@link ApplicationListener}. */ - private static final Set registerListeners = new HashSet<>(); + private static final Set REGISTER_LISTENERS = new HashSet<>(); protected final Logger logger = LoggerFactory.getLogger(getClass()); @@ -215,7 +215,7 @@ public class DubboCloudRegistry extends FailbackRegistry { private void registerServiceInstancesChangedListener(URL url, ApplicationListener listener) { String listenerId = generateId(url); - if (registerListeners.add(listenerId)) { + if (REGISTER_LISTENERS.add(listenerId)) { applicationContext.addApplicationListener(listener); } } @@ -290,7 +290,7 @@ public class DubboCloudRegistry extends FailbackRegistry { .map(templateURL -> templateURL.removeParameter(PID_KEY)) .map(templateURL -> { String protocol = templateURL.getProtocol(); - int port = repository.getDubboProtocolPort(serviceInstance, + Integer port = repository.getDubboProtocolPort(serviceInstance, protocol); if (Objects.equals(templateURL.getHost(), host) && Objects.equals(templateURL.getPort(), port)) { // use @@ -300,15 +300,27 @@ public class DubboCloudRegistry extends FailbackRegistry { return templateURL; } - URLBuilder clonedURLBuilder = from(templateURL) // remove the - // parameters from - // the template - // URL - .setHost(host) // reset the host - .setPort(port); // reset the port + if (port == null) { + if (logger.isWarnEnabled()) { + logger.warn( + "The protocol[{}] port of Dubbo service instance[host : {}] " + + "can't be resolved", + protocol, host); + } + return null; + } + else { + URLBuilder clonedURLBuilder = from(templateURL) // remove the + // parameters from + // the template + // URL + .setHost(host) // reset the host + .setPort(port); // reset the port - return clonedURLBuilder.build(); - }).forEach(clonedExportedURLs::add); + return clonedURLBuilder.build(); + } + + }).filter(Objects::nonNull).forEach(clonedExportedURLs::add); }); return clonedExportedURLs; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java index 43e679f5..8cd5c6b7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.dubbo.registry; +import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreDeregisteredEvent; import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreRegisteredEvent; import com.alibaba.cloud.dubbo.registry.event.ServiceInstanceRegisteredEvent; import org.aspectj.lang.annotation.After; @@ -33,6 +34,7 @@ import org.springframework.context.ApplicationEventPublisherAware; * @author Mercy * @see ServiceInstancePreRegisteredEvent * @see ServiceInstanceRegisteredEvent + * @see ServiceInstancePreDeregisteredEvent */ @Aspect public class DubboServiceRegistrationEventPublishingAspect @@ -41,18 +43,29 @@ public class DubboServiceRegistrationEventPublishingAspect /** * The pointcut expression for {@link ServiceRegistry#register(Registration)}. */ - public static final String REGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && args(registration)"; + public static final String REGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && target(registry) && args(registration)"; + + /** + * The pointcut expression for {@link ServiceRegistry#deregister(Registration)}. + */ + public static final String DEREGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.deregister(*)) && target(registry) && args(registration)"; private ApplicationEventPublisher applicationEventPublisher; - @Before(REGISTER_POINTCUT_EXPRESSION) - public void beforeRegister(Registration registration) { - applicationEventPublisher - .publishEvent(new ServiceInstancePreRegisteredEvent(registration)); + @Before(value = REGISTER_POINTCUT_EXPRESSION, argNames = "registry, registration") + public void beforeRegister(ServiceRegistry registry, Registration registration) { + applicationEventPublisher.publishEvent( + new ServiceInstancePreRegisteredEvent(registry, registration)); } - @After(REGISTER_POINTCUT_EXPRESSION) - public void afterRegister(Registration registration) { + @Before(value = DEREGISTER_POINTCUT_EXPRESSION, argNames = "registry, registration") + public void beforeDeregister(ServiceRegistry registry, Registration registration) { + applicationEventPublisher.publishEvent( + new ServiceInstancePreDeregisteredEvent(registry, registration)); + } + + @After(value = REGISTER_POINTCUT_EXPRESSION, argNames = "registry, registration") + public void afterRegister(ServiceRegistry registry, Registration registration) { applicationEventPublisher .publishEvent(new ServiceInstanceRegisteredEvent(registration)); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreDeregisteredEvent.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreDeregisteredEvent.java new file mode 100644 index 00000000..5e60be5b --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreDeregisteredEvent.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry.event; + +import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; +import org.springframework.context.ApplicationEvent; + +/** + * The + * before-{@link org.springframework.cloud.client.serviceregistry.ServiceRegistry#register(org.springframework.cloud.client.serviceregistry.Registration) + * register} event for {@link org.springframework.cloud.client.ServiceInstance}. + * + * @author Mercy + */ +public class ServiceInstancePreDeregisteredEvent extends ApplicationEvent { + + private final ServiceRegistry registry; + + public ServiceInstancePreDeregisteredEvent(ServiceRegistry registry, + Registration source) { + super(source); + this.registry = registry; + } + + @Override + public Registration getSource() { + return (Registration) super.getSource(); + } + + public ServiceRegistry getRegistry() { + return registry; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreRegisteredEvent.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreRegisteredEvent.java index 4733fef6..e1b905c0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreRegisteredEvent.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/event/ServiceInstancePreRegisteredEvent.java @@ -29,8 +29,12 @@ import org.springframework.context.ApplicationEvent; */ public class ServiceInstancePreRegisteredEvent extends ApplicationEvent { - public ServiceInstancePreRegisteredEvent(Registration source) { + private final ServiceRegistry registry; + + public ServiceInstancePreRegisteredEvent(ServiceRegistry registry, + Registration source) { super(source); + this.registry = registry; } @Override @@ -38,4 +42,8 @@ public class ServiceInstancePreRegisteredEvent extends ApplicationEvent { return (Registration) super.getSource(); } + public ServiceRegistry getRegistry() { + return registry; + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java index 89b99491..d1a68c5f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java @@ -127,11 +127,12 @@ public class DubboGenericServiceFactory { new PropertyEditorSupport() { @Override - public void setAsText(String text) throws IllegalArgumentException { + public void setAsText(String text) + throws java.lang.IllegalArgumentException { // Trim all whitespace String content = StringUtils.trimAllWhitespace(text); if (!StringUtils.hasText(content)) { // No content , ignore - // directly + // directly return; } // replace "=" to "," diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml index 8cc81f62..ec44c9d7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml @@ -1,4 +1,3 @@ - 4.0.0 diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java index e3913c34..e014cac4 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java @@ -16,12 +16,6 @@ package com.alibaba.cloud.stream.binder.rocketmq; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - import com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQListenerBindingContainer; import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQInboundChannelAdapter; import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQMessageHandler; @@ -36,6 +30,9 @@ import com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector.PartitionM import com.alibaba.cloud.stream.binder.rocketmq.support.JacksonRocketMQHeaderMapper; import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.*; + import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.producer.DefaultMQProducer; @@ -44,17 +41,16 @@ import org.apache.rocketmq.remoting.RPCHook; import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQUtil; - import org.springframework.cloud.stream.binder.AbstractMessageChannelBinder; import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; import org.springframework.cloud.stream.binder.ExtendedProducerProperties; import org.springframework.cloud.stream.binder.ExtendedPropertiesBinder; import org.springframework.cloud.stream.provisioning.ConsumerDestination; import org.springframework.cloud.stream.provisioning.ProducerDestination; -import org.springframework.integration.support.StaticMessageHeaderAccessor; +import org.springframework.integration.core.MessageProducer; import org.springframework.integration.support.AcknowledgmentCallback; import org.springframework.integration.support.AcknowledgmentCallback.Status; -import org.springframework.integration.core.MessageProducer; +import org.springframework.integration.support.StaticMessageHeaderAccessor; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; @@ -96,7 +92,8 @@ public class RocketMQMessageChannelBinder extends // if producerGroup is empty, using destination String extendedProducerGroup = producerProperties.getExtension().getGroup(); String producerGroup = StringUtils.isEmpty(extendedProducerGroup) - ? destination.getName() : extendedProducerGroup; + ? destination.getName() + : extendedProducerGroup; RocketMQBinderConfigurationProperties mergedProperties = RocketMQBinderUtils .mergeProperties(rocketBinderConfigurationProperties, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java index 18dc7f68..7f182f63 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java @@ -16,15 +16,16 @@ package com.alibaba.cloud.stream.binder.rocketmq.integration; -import java.util.List; -import java.util.Map; -import java.util.Optional; - import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants; import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties; import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.SendCallback; import org.apache.rocketmq.client.producer.SendResult; @@ -35,7 +36,6 @@ import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQHeaders; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.cloud.stream.binder.BinderHeaders; import org.springframework.cloud.stream.binder.ExtendedProducerProperties; import org.springframework.context.Lifecycle; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java index effa183b..694dcdc9 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java @@ -52,4 +52,4 @@ public class PartitionMessageQueueSelector implements MessageQueueSelector { return mqs.get(partition); } -} \ No newline at end of file +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java index 6383e260..54a536d8 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * Copyright 2013-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -23,7 +23,6 @@ import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigu import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; import org.junit.Test; - import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -38,7 +37,8 @@ public class RocketMQAutoConfigurationTests { .withConfiguration( AutoConfigurations.of(RocketMQBinderAutoConfiguration.class)) .withPropertyValues( - "spring.cloud.stream.rocketmq.binder.namesrv-addr=127.0.0.1:9876", + "spring.cloud.stream.rocketmq.binder.name-server[0]=127.0.0.1:9876", + "spring.cloud.stream.rocketmq.binder.name-server[1]=127.0.0.1:9877", "spring.cloud.stream.bindings.output.destination=TopicOrderTest", "spring.cloud.stream.bindings.output.content-type=application/json", "spring.cloud.stream.bindings.input1.destination=TopicOrderTest", @@ -58,7 +58,7 @@ public class RocketMQAutoConfigurationTests { RocketMQBinderConfigurationProperties binderConfigurationProperties = context .getBean(RocketMQBinderConfigurationProperties.class); assertThat(binderConfigurationProperties.getNameServer()) - .isEqualTo(Arrays.asList("127.0.0.1:9876")); + .isEqualTo(Arrays.asList("127.0.0.1:9876", "127.0.0.1:9877")); RocketMQExtendedBindingProperties bindingProperties = context .getBean(RocketMQExtendedBindingProperties.class); assertThat( @@ -71,4 +71,4 @@ public class RocketMQAutoConfigurationTests { }); } -} \ No newline at end of file +}