1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

Merge pull request #1958 from ppzzyy11/finchley

Merge Master to Finchley
This commit is contained in:
TheoneFx 2021-02-26 15:46:24 +08:00 committed by GitHub
commit 21902dd852
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
196 changed files with 4475 additions and 2213 deletions

View File

@ -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

8
.gitignore vendored
View File

@ -33,3 +33,11 @@ target
.DS_Store
.flattened-pom.xml
# temp ignore
*.cache
*.diff
*.patch
*.tmp
# Maven ignore
.flattened-pom.xml

View File

@ -1 +0,0 @@
-DaltSnapshotDeploymentRepository=repo.spring.io::default::https://repo.spring.io/libs-snapshot-local -P spring

View File

@ -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
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.1.RELEASE</version>
<version>2.2.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -81,19 +79,6 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone
然后在 `dependencies` 中添加自己所需使用的依赖即可使用。
如果您想体验最新的 BUILD-SNAPSHOT 的新功能,则可以将版本换成最新的版本,但是需要在 pom.xml 中配置 Spring BUILDSNAPSHOT 仓库,**注意: SNAPSHOT 版本随时可能更新**
<repositories>
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
## 演示 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
## 社区相关开源

View File

@ -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
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<version>2.2.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -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.

1
mvnw vendored
View File

@ -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} "$@"

121
pom.xml
View File

@ -80,7 +80,7 @@
<properties>
<!-- Project revision -->
<revision>2.0.3.RELEASE</revision>
<revision>2.0.4.RELEASE</revision>
<!-- Dependency Versions -->
<spring-cloud-commons.version>2.0.4.RELEASE</spring-cloud-commons.version>
@ -146,7 +146,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -380,6 +380,31 @@
<reuseForks>false</reuseForks>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@ -393,69 +418,6 @@
</reporting>
<profiles>
<profile>
<id>spring</id>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>release</id>
<build>
@ -500,32 +462,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@ -542,9 +478,6 @@
</repository>
</distributionManagement>
</profile>
</profiles>
</project>

View File

@ -28,6 +28,12 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-commons</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
@ -63,11 +69,11 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
<version>${revision}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>-->
<!-- <version>${revision}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alibaba.cloud</groupId>

View File

@ -18,7 +18,8 @@
<description>Spring Cloud Alibaba Dependencies</description>
<properties>
<revision>2.0.3.RELEASE</revision>
<!-- Project revision -->
<revision>2.0.4.RELEASE</revision>
<sentinel.version>1.8.0</sentinel.version>
<seata.version>1.3.0</seata.version>
@ -161,6 +162,7 @@
<artifactId>sentinel-spring-webflux-adapter</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-api-gateway-adapter-common</artifactId>
@ -234,9 +236,15 @@
<version>${revision}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>-->
<!-- <version>${revision}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
<artifactId>spring-cloud-alibaba-commons</artifactId>
<version>${revision}</version>
</dependency>
@ -260,68 +268,6 @@
<profiles>
<profile>
<id>spring</id>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>release</id>
<build>
@ -401,12 +347,44 @@
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</project>

View File

@ -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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
</dependency>
----
=== 使用 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` 对应的是动态刷新的历史记录。

View File

@ -0,0 +1,96 @@
== Spring Cloud AliCloud ANS
ANSApplication 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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
</dependency>
----
=== 使用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 将会自动为你填充所有配置。

View File

@ -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)

View File

@ -0,0 +1,140 @@
== Spring Cloud AliCloud OSS
OSSObject 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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
----
=== 如何使用 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。

View File

@ -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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-schedulerX</artifactId>
</dependency>
----
=== 启动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官方文档]。

View File

@ -150,11 +150,13 @@ server.listen(8060, function() {
===== 测试1Spring 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所以也带有了断路器。

View File

@ -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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-sms</artifactId>
</dependency>
----
=== 如何使用 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[参考这里]。

View File

@ -23,4 +23,6 @@ include::rocketmq.adoc[]
include::sidecar.adoc[]
include::sidecar.adoc[]

View File

@ -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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
</dependency>
----
=== 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.

View File

@ -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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
</dependency>
----
=== 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 havent 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.

View File

@ -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<SentinelCircuitBreakerFactory> 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<ReactiveSentinelCircuitBreakerFactory> 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<SentinelCircuitBreakerFactory> slowCustomizer() {
String slowId = "slow";
List<DegradeRule> 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<ReactiveSentinelCircuitBreakerFactory> customizer() {
List<DegradeRule> rules = Collections.singletonList(
new DegradeRule().setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(100)
.setTimeWindow(10)
);
return factory -> factory.configure(builder -> builder.rules(rules), "foo", "bar");
}
----
====

View File

@ -17,4 +17,3 @@ If youre a Maven Central user, add our BOM to your pom.xml <dependencyManagem
```
In the following sections, it will be assumed you are using the Spring Cloud Alibaba BOM and the dependency snippets will not contain versions.

View File

@ -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.

View File

@ -0,0 +1,157 @@
== Spring Cloud Alibaba Cloud OSS
OSSObject Storage Serviceis 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
Weve released Spring Cloud Alibaba version 0.2.1. You will need to add dependency management POM first.
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
Next we need to introduce Spring Cloud Alibaba Cloud OSS Starter.
[source,xml]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
----
=== 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 dont 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 havent 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.

View File

@ -0,0 +1,114 @@
== Spring Cloud Alibaba Cloud SchedulerX
SchedulerXDistributed 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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-schedulerX</artifactId>
</dependency>
----
=== 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 interfaceSimpleTask
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.

View File

@ -301,6 +301,8 @@ If you want to use Sentinel Starter with Spring Cloud Gateway, you need to add t
</dependency>
```
include::circuitbreaker-sentinel.adoc[]
=== Sentinel Endpoint
Sentinel provides an Endpoint internally with a corresponding endpoint id of `sentinel`.

View File

@ -0,0 +1,210 @@
== Spring Cloud Alibaba Cloud SMS
SMSShort Message Serviceis 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]
----
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-sms</artifactId>
</dependency>
----
=== 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 dont 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 havent 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].

View File

@ -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[]

View File

@ -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|

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.alibaba.cloud</groupId>
<artifactId>nacos-discovery-example</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-reactivediscovery-consumer-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery Reactive Example</name>
<description>Example demonstrating how to use nacos discovery</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@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<String> serviceCall(@PathVariable("name") String name) {
return webClientBuilder.build().get()
.uri("http://service-provider/echo/" + name).retrieve()
.bodyToMono(String.class);
}
}
}

View File

@ -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

View File

@ -17,6 +17,7 @@
<modules>
<module>nacos-discovery-consumer-example</module>
<module>nacos-reactivediscovery-consumer-example</module>
<module>nacos-discovery-provider-example</module>
<module>nacos-discovery-spring-cloud-config-server-example</module>
<module>nacos-discovery-spring-cloud-config-client-example</module>

View File

@ -30,7 +30,7 @@
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
SpringApplication.run(ProviderApplication.class, args);
}
@RestController

View File

@ -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

View File

@ -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

View File

@ -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<String>() {
});
Thread.sleep(2_000);
Thread.sleep(5_00);
}
}

View File

@ -9,6 +9,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>account-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Account Service</name>
<packaging>jar</packaging>
@ -43,7 +44,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>log4j</groupId>

View File

@ -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

View File

@ -10,7 +10,6 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>business-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Business Service</name>
<packaging>jar</packaging>

View File

@ -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

View File

@ -10,7 +10,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Business Service</name>
<name>Spring Cloud Starter Alibaba Seata Example - Order Service</name>
<packaging>jar</packaging>
<dependencies>
@ -43,7 +43,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>log4j</groupId>

View File

@ -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

View File

@ -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

View File

@ -42,7 +42,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>log4j</groupId>

View File

@ -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

View File

@ -22,6 +22,11 @@
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@ -35,10 +40,10 @@
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba.csp</groupId>-->
<!--<artifactId>sentinel-datasource-nacos</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba.csp</groupId>-->
<!--<artifactId>sentinel-datasource-zookeeper</artifactId>-->
@ -51,6 +56,10 @@
<!--<groupId>com.alibaba.csp</groupId>-->
<!--<artifactId>sentinel-datasource-redis</artifactId>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>com.alibaba.csp</groupId>-->
<!--<artifactId>sentinel-datasource-redis</artifactId>-->
<!--</dependency>-->
<!-- define in spring-boot-autoconfigure module -->
<!--<dependency>-->
<!--<groupId>com.fasterxml.jackson.dataformat</groupId>-->

View File

@ -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

View File

@ -31,7 +31,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>sentinel-dubbo-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<dependency>

View File

@ -31,7 +31,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>sentinel-dubbo-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<dependency>

View File

@ -34,7 +34,7 @@ public class EchoServiceFallback implements EchoService {
/**
* 调用服务提供方的输出接口.
* @param str 用户输入
* @return response
* @return String
*/
@Override
public String echo(String str) {

View File

@ -27,7 +27,8 @@ import org.springframework.web.bind.annotation.PathVariable;
* <p>
* example feign client
*/
@FeignClient(name = "service-provider", fallbackFactory = EchoServiceFallbackFactory.class)
@FeignClient(name = "service-provider",
fallbackFactory = EchoServiceFallbackFactory.class)
public interface EchoService {
/**

View File

@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@Configuration
public class MyConfiguration {
@Bean
public BlockRequestHandler blockRequestHandler() {
return new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange,
Throwable t) {
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON).body(fromObject("block"));
}
};
}
}

View File

@ -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 <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@RestController
public class SentinelWebFluxController {
@GetMapping("/mono")
public Mono<String> mono() {
return Mono.just("simple string")
// transform the publisher here.
.transform(new SentinelReactorTransformer<>("mono"));
}
@GetMapping("/test")
public Mono<String> test() {
return Mono.just("simple string")
// transform the publisher here.
.transform(new SentinelReactorTransformer<>("test"));
}
@GetMapping("/flux")
public Flux<String> flux() {
return Flux.fromArray(new String[] { "a", "b", "c" })
// transform the publisher here.
.transform(new SentinelReactorTransformer<>("flux"));
}
}

View File

@ -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 {

View File

@ -20,7 +20,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot dependencies -->

View File

@ -27,6 +27,8 @@ import org.springframework.web.bind.annotation.RestController;
/**
* Dubbo Spring Cloud Client Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

View File

@ -1,6 +1,9 @@
dubbo:
cloud:
subscribed-services: spring-cloud-alibaba-dubbo-server
protocols:
dubbo:
port: -1
spring:
application:

View File

@ -52,6 +52,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Dubbo Spring Cloud Consumer Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@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")

View File

@ -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,

View File

@ -8,6 +8,8 @@ spring:
# default disable all
cloud:
nacos:
username: nacos
password: nacos
discovery:
enabled: false
register-enabled: false

View File

@ -42,7 +42,6 @@
</dependency>
<!-- List all Spring Cloud starters for Service Discovery -->
<!-- Spring Cloud Nacos Service Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>

View File

@ -23,6 +23,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Provider Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

View File

@ -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 {

View File

@ -42,8 +42,9 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@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());

View File

@ -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

View File

@ -33,6 +33,7 @@ spring:
enabled: true
register-enabled: true
server-addr: 127.0.0.1:8848
ephemeral: false
---

View File

@ -30,7 +30,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<!-- Dubbo Spring Cloud Starter -->

View File

@ -22,6 +22,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Provider Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

View File

@ -3,7 +3,6 @@ dubbo:
base-packages: com.alibaba.cloud.dubbo.service
protocols:
dubbo:
name: dubbo
port: -1
registries:
new:

View File

@ -8,6 +8,8 @@ spring:
# default disable all
cloud:
nacos:
username: nacos
password: nacos
discovery:
enabled: false
register-enabled: false

View File

@ -25,6 +25,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Server Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

View File

@ -15,6 +15,12 @@
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@ -29,7 +35,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<!-- Dubbo Spring Cloud Starter -->

View File

@ -24,6 +24,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* Dubbo Spring Cloud Servlet Gateway Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

View File

@ -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/*")

View File

@ -15,16 +15,16 @@
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@ -20,19 +20,27 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>

View File

@ -7,10 +7,12 @@ spring:
password: nacos
discovery:
server-addr: localhost:8848
group: test
gateway:
discovery:
locator:
enabled: true
application:
name: node-service
sidecar:

View File

@ -22,10 +22,12 @@
<module>spring-cloud-starter-stream-rocketmq</module>
<module>spring-cloud-starter-bus-rocketmq</module>
<module>spring-cloud-starter-dubbo</module>
<module>spring-cloud-starter-alibaba-sidecar</module>
<!-- <module>spring-cloud-starter-alibaba-sidecar</module>-->
<module>spring-cloud-starter-alibaba-sentinel</module>
<module>spring-cloud-alibaba-sentinel-datasource</module>
<module>spring-cloud-alibaba-sentinel-gateway</module>
<!-- <module>spring-cloud-circuitbreaker-sentinel</module>-->
<module>spring-cloud-alibaba-commons</module>
</modules>
<build>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-starters</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-alibaba-commons</artifactId>
<name>Spring Cloud Alibaba Commons</name>
</project>

View File

@ -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 <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
*/
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.
* <p>
* From the Java documentation
* <a href="https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">
* Standard charsets</a>:
* </p>
* @return An immutable, case-insensitive map from canonical charset names to charset
* objects.
* @see Charset#availableCharsets()
*/
public static SortedMap<String, Charset> requiredCharsets() {
// maybe cache?
final TreeMap<String, Charset> 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.
* <p>
* Every implementation of the Java platform is required to support this character
* encoding.
* </p>
*
* @see <a href=
* "https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
/**
* <p>
* Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of
* the Unicode character set.
* </p>
* <p>
* Every implementation of the Java platform is required to support this character
* encoding.
* </p>
*
* @see <a href=
* "https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
/**
* <p>
* 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)
* </p>
* <p>
* Every implementation of the Java platform is required to support this character
* encoding.
* </p>
*
* @see <a href=
* "https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_16 = StandardCharsets.UTF_16;
/**
* <p>
* Sixteen-bit Unicode Transformation Format, big-endian byte order.
* </p>
* <p>
* Every implementation of the Java platform is required to support this character
* encoding.
* </p>
*
* @see <a href=
* "https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_16BE = StandardCharsets.UTF_16BE;
/**
* <p>
* Sixteen-bit Unicode Transformation Format, little-endian byte order.
* </p>
* <p>
* Every implementation of the Java platform is required to support this character
* encoding.
* </p>
*
* @see <a href=
* "https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_16LE = StandardCharsets.UTF_16LE;
/**
* <p>
* Eight-bit Unicode Transformation Format.
* </p>
* <p>
* Every implementation of the Java platform is required to support this character
* encoding.
* </p>
*
* @see <a href=
* "https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html">Standard
* charsets</a>
* @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
*/
@Deprecated
public static final Charset UTF_8 = StandardCharsets.UTF_8;
}

View File

@ -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 <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
*/
public final class FileUtils {
private FileUtils() {
}
// -----------------------------------------------------------------------
/**
* Opens a {@link java.io.FileInputStream} for the specified file, providing better
* error messages than simply calling <code>new FileInputStream(file)</code>.
* <p>
* At the end of the method either the stream will be successfully opened, or an
* exception will have been thrown.
* <p>
* 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());
}
}

View File

@ -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 <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
*/
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 <code>InputStream</code> as a String using the specified
* character encoding.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* </p>
* @param input the <code>InputStream</code> 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 <code>Reader</code> to a <code>Writer</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedReader</code>.
* <p>
* Large streams (over 2GB) will return a chars copied value of <code>-1</code> after
* the copy has completed since the correct number of chars cannot be returned as an
* int. For large streams use the <code>copyLarge(Reader, Writer)</code> method.
* @param input the <code>Reader</code> to read from
* @param output the <code>Writer</code> to write to
* @return the number of characters copied, or -1 if &gt; 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 <code>InputStream</code> to chars on a <code>Writer</code>
* using the specified character encoding.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* This method uses {@link java.io.InputStreamReader}.
* @param input the <code>InputStream</code> to read from
* @param output the <code>Writer</code> 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 <code>InputStream</code> to an <code>OutputStream</code> using
* an internal buffer of the given size.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* @param input the <code>InputStream</code> to read from
* @param output the <code>OutputStream</code> 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) <code>Reader</code> to a <code>Writer</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedReader</code>.
* <p>
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
* @param input the <code>Reader</code> to read from
* @param output the <code>Writer</code> 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) <code>Reader</code> to a <code>Writer</code>.
* <p>
* This method uses the provided buffer, so there is no need to use a
* <code>BufferedReader</code>.
* <p>
* @param input the <code>Reader</code> to read from
* @param output the <code>Writer</code> 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) <code>InputStream</code> to an
* <code>OutputStream</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
* @param input the <code>InputStream</code> to read from
* @param output the <code>OutputStream</code> 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) <code>InputStream</code> to an
* <code>OutputStream</code>.
* <p>
* This method uses the provided buffer, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* @param input the <code>InputStream</code> to read from
* @param output the <code>OutputStream</code> 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;
}
}

View File

@ -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 <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
*/
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}.
*
* <p>
* If {@code builder} is null a new instance with default capacity will be created.
* </p>
* @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();
}
}

View File

@ -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 <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
*/
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() {
}
/**
* <p>
* Checks if a CharSequence is empty ("") or null.
* </p>
*
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
* StringUtils.isEmpty(" ") = false
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p>
* NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence.
* That functionality is available in isBlank().
* </p>
* @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;
}
/**
* <p>
* Checks if a CharSequence is not empty ("") and not null.
* </p>
*
* <pre>
* StringUtils.isNotEmpty(null) = false
* StringUtils.isNotEmpty("") = false
* StringUtils.isNotEmpty(" ") = true
* StringUtils.isNotEmpty("bob") = true
* StringUtils.isNotEmpty(" bob ") = true
* </pre>
* @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);
}
/**
* <p>
* Checks if a CharSequence is whitespace, empty ("") or null.
* </p>
*
* <pre>
* StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true
* StringUtils.isBlank(" ") = true
* StringUtils.isBlank("bob") = false
* StringUtils.isBlank(" bob ") = false
* </pre>
* @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;
}
/**
* <p>
* Checks if a CharSequence is not empty (""), not null and not whitespace only.
* </p>
*
* <p>
* Whitespace is defined by {@link Character#isWhitespace(char)}.
* </p>
*
* <pre>
* StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false
* StringUtils.isNotBlank(" ") = false
* StringUtils.isNotBlank("bob") = true
* StringUtils.isNotBlank(" bob ") = true
* </pre>
* @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
// -----------------------------------------------------------------------
/**
* <p>
* Removes control characters (char &lt;= 32) from both ends of this String, handling
* {@code null} by returning {@code null}.
* </p>
*
* <p>
* The String is trimmed using {@link String#trim()}. Trim removes start and end
* characters &lt;= 32.
* </p>
*
* <pre>
* StringUtils.trim(null) = null
* StringUtils.trim("") = ""
* StringUtils.trim(" ") = ""
* StringUtils.trim("abc") = "abc"
* StringUtils.trim(" abc ") = "abc"
* </pre>
* @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
// -----------------------------------------------------------------------
/**
* <p>
* Compares two CharSequences, returning {@code true} if they represent equal
* sequences of characters.
* </p>
*
* <p>
* {@code null}s are handled without exceptions. Two {@code null} references are
* considered to be equal. The comparison is case sensitive.
* </p>
*
* <pre>
* 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
* </pre>
* @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;
}
/**
* <p>
* Gets the substring after the first occurrence of a separator. The separator is not
* returned.
* </p>
*
* <p>
* A <code>null</code> string input will return <code>null</code>. An empty ("")
* string input will return the empty string. A <code>null</code> separator will
* return the empty string if the input string is not <code>null</code>.
* </p>
*
* <p>
* If nothing is found, the empty string is returned.
* </p>
*
* <pre>
* 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"
* </pre>
* @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,
* <code>null</code> 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
// -----------------------------------------------------------------------
/**
* <p>
* Gets the String that is nested in between two instances of the same String.
* </p>
*
* <p>
* A <code>null</code> input String returns <code>null</code>. A <code>null</code> tag
* returns <code>null</code>.
* </p>
*
* <pre>
* StringUtils.substringBetween(null, *) = null
* StringUtils.substringBetween("", "") = ""
* StringUtils.substringBetween("", "tag") = null
* StringUtils.substringBetween("tagabctag", null) = null
* StringUtils.substringBetween("tagabctag", "") = ""
* StringUtils.substringBetween("tagabctag", "tag") = "abc"
* </pre>
* @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, <code>null</code> if no match
* @since 2.0
*/
public static String substringBetween(String str, String tag) {
return substringBetween(str, tag, tag);
}
/**
* <p>
* Gets the String that is nested in between two Strings. Only the first match is
* returned.
* </p>
*
* <p>
* A <code>null</code> input String returns <code>null</code>. A <code>null</code>
* open/close returns <code>null</code> (no match). An empty ("") open and close
* returns an empty string.
* </p>
*
* <pre>
* 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"
* </pre>
* @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, <code>null</code> 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;
}
}

View File

@ -17,23 +17,6 @@
<dependencies>
<!--spring boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
@ -121,12 +104,6 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@ -94,4 +94,5 @@ public class ConsulDataSourceProperties extends AbstractDataSourceProperties {
public void setWaitTimeoutInSecond(int waitTimeoutInSecond) {
this.waitTimeoutInSecond = waitTimeoutInSecond;
}
}

View File

@ -88,4 +88,5 @@ public class ConsulDataSourceFactoryBean implements FactoryBean<ConsulDataSource
public void setConverter(Converter converter) {
this.converter = converter;
}
}

View File

@ -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;

View File

@ -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";
/**

View File

@ -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 {

View File

@ -28,7 +28,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty;
/**
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@ConfigurationProperties(prefix = ConfigConstants.ZUUl_PREFIX)
@ConfigurationProperties(prefix = ConfigConstants.ZUUL_PREFIX)
public class SentinelZuulProperties {
@NestedConfigurationProperty

View File

@ -27,12 +27,6 @@
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>

View File

@ -105,7 +105,6 @@
<version>2.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -16,12 +16,16 @@
package com.alibaba.cloud.nacos.client;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
/**
* @author xiaojing
@ -58,6 +62,32 @@ public class NacosPropertySource extends MapPropertySource {
this.isRefreshable = isRefreshable;
}
NacosPropertySource(List<PropertySource<?>> propertySources, String group,
String dataId, Date timestamp, boolean isRefreshable) {
this(group, dataId, getSourceMap(group, dataId, propertySources), timestamp,
isRefreshable);
}
private static Map<String, Object> getSourceMap(String group, String dataId,
List<PropertySource<?>> propertySources) {
if (CollectionUtils.isEmpty(propertySources)) {
return Collections.emptyMap();
}
// If only one, return the internal element, otherwise wrap it.
if (propertySources.size() == 1) {
PropertySource propertySource = propertySources.get(0);
if (propertySource != null && propertySource.getSource() instanceof Map) {
return (Map<String, Object>) propertySource.getSource();
}
}
// If it is multiple, it will be returned as it is, and the internal elements
// cannot be directly retrieved, so the user needs to implement the retrieval
// logic by himself
return Collections.singletonMap(
String.join(NacosConfigProperties.COMMAS, dataId, group),
propertySources);
}
public String getGroup() {
return this.group;
}

View File

@ -16,17 +16,18 @@
package com.alibaba.cloud.nacos.client;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import com.alibaba.cloud.nacos.NacosPropertySourceRepository;
import com.alibaba.cloud.nacos.parser.NacosDataParserHandler;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
/**
@ -38,8 +39,6 @@ public class NacosPropertySourceBuilder {
private static final Logger log = LoggerFactory
.getLogger(NacosPropertySourceBuilder.class);
private static final Map<String, Object> EMPTY_MAP = new LinkedHashMap();
private ConfigService configService;
private long timeout;
@ -71,14 +70,15 @@ public class NacosPropertySourceBuilder {
*/
NacosPropertySource build(String dataId, String group, String fileExtension,
boolean isRefreshable) {
Map<String, Object> p = loadNacosData(dataId, group, fileExtension);
NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
p, new Date(), isRefreshable);
List<PropertySource<?>> propertySources = loadNacosData(dataId, group,
fileExtension);
NacosPropertySource nacosPropertySource = new NacosPropertySource(propertySources,
group, dataId, new Date(), isRefreshable);
NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
return nacosPropertySource;
}
private Map<String, Object> loadNacosData(String dataId, String group,
private List<PropertySource<?>> loadNacosData(String dataId, String group,
String fileExtension) {
String data = null;
try {
@ -87,24 +87,23 @@ public class NacosPropertySourceBuilder {
log.warn(
"Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]",
dataId, group);
return EMPTY_MAP;
return Collections.emptyList();
}
if (log.isDebugEnabled()) {
log.debug(String.format(
"Loading nacos data, dataId: '%s', group: '%s', data: %s", dataId,
group, data));
}
Map<String, Object> dataMap = NacosDataParserHandler.getInstance()
.parseNacosData(data, fileExtension);
return dataMap == null ? EMPTY_MAP : dataMap;
return NacosDataParserHandler.getInstance().parseNacosData(dataId, data,
fileExtension);
}
catch (NacosException e) {
log.error("get data from Nacos error,dataId:{}, ", dataId, e);
log.error("get data from Nacos error,dataId:{} ", dataId, e);
}
catch (Exception e) {
log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e);
log.error("parse data from Nacos error,dataId:{},data:{}", dataId, data, e);
}
return EMPTY_MAP;
return Collections.emptyList();
}
}

View File

@ -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<NacosConfigProperties.Config> 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<NacosConfigProperties.Config> 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,

Some files were not shown because too many files have changed in this diff Show More