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

Merge remote-tracking branch 'upstream/master' into binder-dev

This commit is contained in:
fangjian0423 2019-03-12 11:14:26 +08:00
commit 474132db42
152 changed files with 2797 additions and 2818 deletions

View File

@ -122,7 +122,7 @@ Examples
[Alibaba Cloud OSS Example](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/oss-example/readme.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 first version number is fixed to 0, that is, the version number is 0.x.x.
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.
As the interfaces and annotations of Spring Boot 1 and Spring Boot 2 have been changed significantly in the Actuator module, and spring-cloud-commons is also changed quite a lot from 1.x.x to 2.0.0, we maintain two different branches to support Spring Boot 1 and Spring Boot 2:
* 0.1.x for Spring Boot 1

13
pom.xml
View File

@ -61,6 +61,10 @@
<email>mercyblitz@gmail.com</email>
<organization>Alibaba</organization>
<url>https://github.com/mercyblitz</url>
</developer>
<developer>
<name>yunzheng</name>
<email>yunzheng1228@gmail.com</email>
</developer>
</developers>
@ -70,6 +74,7 @@
<spring-cloud-netflix.version>2.1.0.RELEASE</spring-cloud-netflix.version>
<spring-cloud-openfeign.version>2.1.0.RELEASE</spring-cloud-openfeign.version>
<spring-cloud-bus.version>2.1.0.RELEASE</spring-cloud-bus.version>
<spring-cloud-gateway.version>2.1.0.RELEASE</spring-cloud-gateway.version>
<junit.version>4.12</junit.version>
<javax-servlet-api>3.0</javax-servlet-api>
@ -167,6 +172,14 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-dependencies</artifactId>
<version>${spring-cloud-gateway.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -26,11 +26,6 @@
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config-server</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
@ -61,27 +56,16 @@
<artifactId>spring-cloud-alicloud-context</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-oss</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-schedulerx</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-sms</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rocketmq</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-fescar</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -19,8 +19,8 @@
<properties>
<sentinel.version>1.4.2</sentinel.version>
<oss.version>3.1.0</oss.version>
<fescar.version>0.1.3</fescar.version>
<nacos.client.version>0.8.2</nacos.client.version>
<fescar.version>0.2.3</fescar.version>
<nacos.client.version>0.9.1</nacos.client.version>
<nacos.config.version>0.8.0</nacos.config.version>
<acm.version>1.0.8</acm.version>
<ans.version>1.0.1</ans.version>

View File

@ -6,24 +6,7 @@ Spring Cloud AliCloud ACM 是 Config Server 和 Client 的替代方案,客户
=== 如何引入 Spring Cloud AliCloud ACM
Spring Cloud Alibaba 已经发布了 0.2.2.BUILD-SNAPSHOT 版本,需要首先导入依赖管理 POM。
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
并引入 Spring Cloud AliCloud ACM Starter 依赖。
如果要在您的项目中引入 ACM使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-acm` 的 starter。
[source,xml]
----

View File

@ -4,24 +4,7 @@ ANSApplication Naming Service 是隶属于阿里云 EDAS 产品的组件
=== 如何引入 Spring Cloud AliCloud ANS
Spring Cloud Alibaba 已经发布了 0.2.2.BUILD-SNAPSHOT 版本,需要首先导入依赖管理 POM。
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
接下来引入 Spring Cloud AliCloud ANS Starter 即可。
如果要在您的项目中引入 ANS使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-ans` 的 starter。
[source,xml]
----

View File

@ -2,3 +2,41 @@
Spring Cloud Alibaba BOM 包含了它所使用的所有依赖的版本。
### Spring Cloud Alibaba Bill of Materials (BOM)
如果您是 Maven Central 用户,请将我们的 BOM 添加到您的 pom.xml 中的 <dependencyManagement> 部分。 这将允许您省略任何Maven依赖项的版本而是将版本控制委派给BOM。
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
```
### Spring Snapshots Maven Repository
如果要使用最新的 BUILD-SNAPSHOT 版本,请在 pom.xml 中添加 Spring Snapshot Repository注意BUILD-SNAPSHOT随时可能更新:
```xml
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring SnapShots</name>
<url>https://repo.spring.io/libs-snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
```
举个例子, 0.2.0.BUILD-SNAPSHOT 版本就在这个仓库中可用。

View File

@ -28,55 +28,14 @@ NOTE: 注意dataid是以 properties(默认的文件扩展名方式)为扩展名
===== 客户端使用方式
为了能够在应用程序中使用 Nacos 来实现应用的外部化配置在构建应用的同时添加一个Spring Boot Starter org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config。以下是一个基本的 maven 依赖配置:
如果要在您的项目中使用 Nacos 来实现应用的外部化配置,使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alibaba-nacos-config` 的 starter。
[source,xml]
----
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
----
现在就可以创建一个标准的 Spring Boot 应用。

View File

@ -11,39 +11,18 @@ Discovery Starter 也将服务实例自身的一些元数据信息-例如 host
==== 如何引入 Nacos Discovery Starter
为了能够在你的工程下引入 Nacos Discovey Starter使用group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alibaba-nacos-discovery`。
pom.xml 示例如下所示:
如果要在您的项目中使用 Nacos 来实现服务发现,使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alibaba-nacos-discovery` 的 starter。
[source,xml,indent=0]
----
<!-- dependency management-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- dependencies -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
----
==== 启动一个 Provider 应用
如果您使用的 Spring Cloud 版本是 Finchley.SR1 版本,那么这个时候您的Spring Boot版本的选择可需要额外的小心了因为版本的不匹对可能会导致许多意外的效果。
Spring Cloud 的 Finchley.SR1 版本最佳实践的 Spring Boot 版本是 2.0.6.RELEASE。在启动您的一个 Provider 应用时请检查依赖的 Spring Boot 版本是否是
1.X.Y.RELEASE 或者 2.1.0.RELEASE 的版本。如果不是,请更正到 2.0.6.RELEASE 版本。
以下步骤向您展示了如何将一个服务注册到 Nacos。
1. pom.xml的配置。一个完整的 pom.xml 配置如下所示:
@ -62,7 +41,7 @@ Spring Cloud 的 Finchley.SR1 版本最佳实践的 Spring Boot 版本是 2.0.6.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<version>${spring.boot.version}</version>
<relativePath/>
</parent>
@ -77,14 +56,14 @@ Spring Cloud 的 Finchley.SR1 版本最佳实践的 Spring Boot 版本是 2.0.6.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

View File

@ -4,24 +4,7 @@ OSSObject Storage Service是阿里云的一款对象存储服务产品
=== 如何引入 Spring Cloud AliCloud OSS
Spring Cloud Alibaba 已经发布了0.2.0版本需要首先导入依赖管理POM。
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
接下来引入 Spring Cloud AliCloud OSS Starter 即可。
如果要在您的项目中引入 OSS使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-oss` 的 starter。
[source,xml]
----

View File

@ -4,24 +4,7 @@ SchedulerX分布式任务调度 是隶属于阿里云EDAS产品的组件
=== 如何引入 Spring Cloud AliCloud SchedulerX
Spring Cloud Alibaba 已经发布了0.2.1版本需要首先导入依赖管理POM。
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
接下来引入 Spring Cloud AliCloud SchedulerX Starter 即可。
如果要在您的项目中引入 SchedulerX使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-schedulerX` 的 starter。
[source,xml]
----

View File

@ -266,12 +266,13 @@ Sentinel Endpoint 里暴露的信息非常有用。包括当前应用的所有
^|配置项 ^|含义 ^|默认值
|`spring.cloud.sentinel.enabled`|Sentinel自动化配置是否生效|true
|`spring.cloud.sentinel.eager`|取消Sentinel控制台懒加载|false
|`spring.cloud.sentinel.transport.port`|应用与Sentinel控制台交互的端口应用本地会起一个该端口占用的HttpServer|8721
|`spring.cloud.sentinel.transport.port`|应用与Sentinel控制台交互的端口应用本地会起一个该端口占用的HttpServer|8719
|`spring.cloud.sentinel.transport.dashboard`|Sentinel 控制台地址|
|`spring.cloud.sentinel.transport.heartbeat-interval-ms`|应用与Sentinel控制台的心跳间隔时间|
|`spring.cloud.sentinel.transport.client-ip`|客户端IP|
|`spring.cloud.sentinel.filter.order`|Servlet Filter的加载顺序。Starter内部会构造这个filter|Integer.MIN_VALUE
|`spring.cloud.sentinel.filter.url-patterns`|数据类型是数组。表示Servlet Filter的url pattern集合|/*
|`spring.cloud.sentinel.filter.enabled`|Enable to instance CommonFilter|true
|`spring.cloud.sentinel.metric.charset`|metric文件字符集|UTF-8
|`spring.cloud.sentinel.metric.file-single-size`|Sentinel metric 单个文件的大小|
|`spring.cloud.sentinel.metric.file-total-count`|Sentinel metric 总文件数量|

View File

@ -4,31 +4,7 @@
=== 如何引入 Spring Cloud AliCloud SMS
Spring Cloud Alibaba 已经发布了 0.2.2.BUILD-SNAPSHOT 版本,需要首先导入依赖管理 POM。
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
接下来引入 Spring Cloud AliCloud SMS Starter 即可。
如果要在您的项目中引入 SMS使用 group ID 为 `org.springframework.cloud` 和 artifact ID 为 `spring-cloud-starter-alicloud-sms` 的 starter。
[source,xml]
----
@ -55,7 +31,7 @@ access-key 和 secret-key 是阿里云账号的 AK/SK需要首先注册阿里
==== 引入 SMS API
Spring Cloud Alicloud SMS 中的 SMS API 基于阿里云官方 SMS SDK 提供,具备单个短信发送、多个短信批量发送、短信查询、短信消息(`短信回执消息``上行短信消息`) 类行操作API。
Spring Cloud Alicloud SMS 中的 SMS API 基于阿里云官方 SMS SDK 提供,具备单个短信发送、多个短信批量发送、短信查询、短信消息(短信回执消息 和 上行短信消息) 类行操作API。
一个简单的使用 SMS API 发送短信的应用如下。
@ -67,13 +43,7 @@ public class SmsApplication {
@Autowired
private ISmsService smsService;
/**
* 短信发送 Example
* @param code
* @return
*/
@RequestMapping("/batch-sms-send.do")
public SendBatchSmsResponse batchsendCheckCode(
@RequestParam(name = "code") String code) {
@ -99,7 +69,6 @@ public class SmsApplication {
}
public static void main(String[] args) throws URISyntaxException {
SpringApplication.run(SmsApplication.class, args);
}
@ -119,15 +88,10 @@ Spring Cloud Alicloud SMS 封装的 API 接口为了降低学习的成本,尽
* 批量短信发送
参考以下的 Example ,来快速开发一个具有批量短信发送的功能。在 Controller 中或者新建一个 Controler 新增如下代码:
参考以下的 Example ,来快速开发一个具有批量短信发送的功能。在 Controller 中或者新建一个 Controller 新增如下代码:
[source,java]
----
/**
* 批量短信发送 Example
* @param code
* @return
*/
@RequestMapping("/batch-sms-send.do")
public SendBatchSmsResponse batchsendCheckCode(
@RequestParam(name = "code") String code) {
@ -165,16 +129,10 @@ NOTE: 这里设置请求的 MethodType 为 GET和官网给出的例子还有
* 短信查询
参考以下的 Example ,可以快速开发根据某个指定的号码查询短信历史发送状态。在 Controller 中或者新建一个 Controler 新增如下代码:
参考以下的 Example ,可以快速开发根据某个指定的号码查询短信历史发送状态。在 Controller 中或者新建一个 Controller 新增如下代码:
[source,java]
----
/**
*
* 短信查询 Example
* @param telephone
* @return
*/
@RequestMapping("/query.do")
public QuerySendDetailsResponse querySendDetailsResponse(
@RequestParam(name = "tel") String telephone) {
@ -241,7 +199,7 @@ public class SmsReportMessageListener
* 上行短信消息
通过订阅SmsUp上行短信消息可以获知终端用户回复短信的内容。这些工作也已经被 Spring Cloud AliCloud SMS 封装好了。你只需要完成以下两步即可。
通过订阅 SmsUp 上行短信消息,可以获知终端用户回复短信的内容。这些工作也已经被 Spring Cloud AliCloud SMS 封装好了。你只需要完成以下两步即可。
1、 在 `application.properties` 配置文件中(也可以是 application.yaml)配置 SmsReport 的队列名称。

View File

@ -6,24 +6,7 @@ Spring Cloud Alibaba Cloud ACM is an alternative solution for Config Server and
=== How to Introduce Spring Cloud Alibaba Cloud ACM
Weve released Spring Cloud Alibaba version 0.2.2.BUILD-SNAPSHOT. You will need to add dependency management POM first.
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.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 ACM Starter.
If you want to use ACM in your project, please use the starter with the group ID as `org.springframework.cloud` and the artifact ID as `spring-cloud-starter-alicloud-acm`.
[source,xml]
----

View File

@ -4,24 +4,7 @@ ANS(Application Naming Service) is a component of EDAS. Spring Cloud Alibaba Cl
=== How to Introduce Spring Cloud Alibaba Cloud ANS
Weve released Spring Cloud Alibaba version 0.2.1. You will need to add dependency management POM first.
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.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 AliCloud ANS Starter.
If you want to use ANS in your project, please use the starter with the group ID as `org.springframework.cloud` and the artifact ID as `spring-cloud-starter-alicloud-ans`.
[source,xml]
----

View File

@ -1,38 +1,38 @@
== Dependency Management
The Spring Cloud Alibaba Bill of Materials (BOM) contains the versions of all the dependencies it uses.
### Spring Cloud Alibaba Bill of Materials (BOM)
Version 0.2.2.BUILD-SNAPSHOT is compatible with the Spring Cloud Finchley. Version 0.1.1.RELEASE is compatible with the Spring Cloud Edgware.
If youre a Maven Central user, add our BOM to your pom.xml <dependencyManagement> section. This will allow you to omit versions for any of the Maven dependencies and instead delegate versioning to the BOM.
These artifacts are available from Maven Central and Spring Release repository via BOM:
[source,xml]
----
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
```
If you want to use the latest BUILD-SNAPSHOT version, add Spring Snapshot Repository in pom.xml , Attention: BUILD-SNAPSHOT may be updated in any time
### Spring Snapshots Maven Repository
[source,xml]
----
If you want to use the latest BUILD-SNAPSHOT version, add Spring Snapshot Repository in pom.xml , Attention: BUILD-SNAPSHOT may be updated in any time:
```xml
<repositories>
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<path>https://repo.spring.io/snapshot</path>
<id>spring-snapshots</id>
<name>Spring SnapShots</name>
<url>https://repo.spring.io/libs-snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
----
```
For example, the 0.2.0.BUILD-SNAPSHOT is available from this repository.

View File

@ -28,55 +28,14 @@ NOTE: The default file extension of dataid is properties.
===== Usage on the Client
To use Nacos to manage externalized configurations for your applications, you need to add a Spring Boot Starter while building your application: org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config The following is a basic configuration of maven dependency:
If you want to use Nacos to manage externalized configurations for your applications, please use the starter with the group ID as `org.springframework.cloud` and the artifact ID as `spring-cloud-starter-alibaba-nacos-config`.
[source,xml]
----
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
----
Now we can create a standard Spring Boot application.

View File

@ -11,39 +11,18 @@ Discovery Starter registers some of the metadata of the service instance, such a
==== How to Introduce Nacos Discovery Starter
To introduce Nacos Discovey Starter into your project, use the group ID of `org.springframework.cloud` and the artifact ID of `spring-cloud-starter-alibaba-nacos-discovery`.
pom.xml sample
please use the starter with the group ID as `org.springframework.cloud` and the artifact ID as `spring-cloud-starter-alibaba-nacos-discovery`.
[source,xml,indent=0]
----
<! -- dependency management-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<! -- dependencies -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
----
==== Start a Provider Application
If you use the Finchley.SR1 version of Spring Cloud , then you will need to be very cautious when selecting the Spring Boot version, because the version incompatibility might lead to many unexpected results.
The best practice for Spring Cloud Finchley.SR1 is to use the 2.0.6 release of Spring Boot. When starting a provider application, please also check if your Spring Boot version is
1.X.Y.RELEASE or 2.1.0.RELEASE. If not, please change it to 2.0.6.RELEASE.
The following sample illustrates how to register a service to Nacos.
1. Configuration of pom.xml The following is a complete example of pom.xml:
@ -62,7 +41,7 @@ The following sample illustrates how to register a service to Nacos.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<version>${spring.boot.version}</version>
<relativePath/>
</parent>
@ -77,14 +56,14 @@ The following sample illustrates how to register a service to Nacos.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

View File

@ -4,24 +4,7 @@ SchedulerXDistributed job scheduling is a component of EDAS, an Alibaba Cl
=== How to Introduce Spring Cloud Alibaba Cloud SchedulerX
Weve released Spring Cloud Alibaba version 0.2.1. You will need to add dependency management POM first.
[source,xml]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.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 AliCloud SchedulerX Starter.
If you want to use SchedulerX in your project, please use the starter with the group ID as `org.springframework.cloud` and the artifact ID as `spring-cloud-starter-alicloud-schedulerX`.
[source,xml]
----

View File

@ -265,12 +265,13 @@ The following table shows all the configurations of Spring Cloud Alibaba Sentine
^|Configuration ^|Description ^|Default Value
|`spring.cloud.sentinel.enabled`|Whether Sentinel automatic configuration takes effect|true
|`spring.cloud.sentinel.eager`|Cancel Sentinel dashboard lazy load|false
|`spring.cloud.sentinel.transport.port`|Port for the application to interact with Sentinel dashboard. An HTTP Server which uses this port will be started in the application|8721
|`spring.cloud.sentinel.transport.port`|Port for the application to interact with Sentinel dashboard. An HTTP Server which uses this port will be started in the application|8719
|`spring.cloud.sentinel.transport.dashboard`|Sentinel dashboard address|
|`spring.cloud.sentinel.transport.heartbeatIntervalMs`|Hearbeat interval between the application and Sentinel dashboard|
|`spring.cloud.sentinel.transport.client-ip`|Client IP|
|`spring.cloud.sentinel.filter.order`|Loading order of Servlet Filter. The filter will be constructed in the Starter|Integer.MIN_VALUE
|`spring.cloud.sentinel.filter.url-patterns`|Data type is array. Refers to the collection of Servlet Filter ULR patterns|/*
|`spring.cloud.sentinel.filter.enabled`|Enable to instance CommonFilter|true
|`spring.cloud.sentinel.metric.charset`|metric file character set|UTF-8
|`spring.cloud.sentinel.metric.fileSingleSize`|Sentinel metric single file size|
|`spring.cloud.sentinel.metric.fileTotalCount`|Sentinel metric total file number|

View File

@ -0,0 +1,209 @@
== 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 AliCloud SMS provide an easier-to-use API for quick access to Alibaba Cloud's SMS service based on Spring Cloud Alibaba SMS.
=== 如何引入 Spring Cloud AliCloud SMS
If you want to use SMS in your project, please use the starter with the group ID as `org.springframework.cloud` and the artifact ID as `spring-cloud-starter-alicloud-sms`.
[source,xml]
----
<dependency>
<groupId>org.springframework.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 org.springframework.cloud.alicloud.sms.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
----
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

@ -14,9 +14,7 @@
<name>Spring Cloud Alibaba Dubbo</name>
<properties>
<dubbo.version>2.6.5</dubbo.version>
<dubbo-spring-boot.version>0.2.1.RELEASE</dubbo-spring-boot.version>
<dubbo-registry-nacos.version>0.0.2</dubbo-registry-nacos.version>
<dubbo.version>2.7.0</dubbo.version>
<spring-cloud-zookeeper.version>2.1.0.RELEASE</spring-cloud-zookeeper.version>
<spring-cloud-consul.version>2.1.0.RELEASE</spring-cloud-consul.version>
<curator.version>4.0.1</curator.version>
@ -36,7 +34,7 @@
<!-- Apache Dubbo dependencies-->
<dependency>
<groupId>com.alibaba</groupId>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
@ -93,7 +91,6 @@
<optional>true</optional>
</dependency>
<!-- Eureka Service Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
@ -153,19 +150,35 @@
<!-- Spring Cloud Open Feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
<artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!-- Netty -->

View File

@ -16,13 +16,16 @@
*/
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import feign.Contract;
import org.apache.dubbo.config.ProtocolConfig;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy;
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@ -38,12 +41,17 @@ import static com.alibaba.dubbo.common.Constants.DEFAULT_PROTOCOL;
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Configuration
@Import(DubboServiceMetadataRepository.class)
@DubboComponentScan(basePackages = "org.springframework.cloud.alibaba.dubbo.service")
@Import({DubboServiceMetadataRepository.class, PublishingDubboMetadataConfigService.class})
public class DubboMetadataAutoConfiguration {
public static final String METADATA_PROTOCOL_BEAN_NAME = "metadata";
@Bean
@ConditionalOnMissingBean
public MetadataResolver metadataJsonResolver(ObjectProvider<Contract> contract) {
return new DubboServiceBeanMetadataResolver(contract);
}
/**
* Build an alias Bean for {@link ProtocolConfig}
*

View File

@ -0,0 +1,214 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.List;
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration.METADATA_PROTOCOL_BEAN_NAME;
/**
* The Auto-Configuration class for Dubbo metadata {@link EventListener event handling}.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class})
@Configuration
public class DubboMetadataEventHandlingAutoConfiguration {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private MetadataResolver metadataResolver;
@Autowired
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
@Autowired
private ApplicationConfig applicationConfig;
@Autowired
@Qualifier(METADATA_PROTOCOL_BEAN_NAME)
private ProtocolConfig metadataProtocolConfig;
@Autowired
private ConfigurableApplicationContext context;
@Value("${spring.application.name:application}")
private String currentApplicationName;
/**
* The ServiceConfig of DubboMetadataConfigService to be exported, can be nullable.
*/
private ServiceConfig<DubboMetadataConfigService> serviceConfig;
private ServiceInstance restServiceInstance;
@EventListener(ServiceBeanExportedEvent.class)
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
ServiceBean serviceBean = event.getServiceBean();
publishServiceRestMetadata(serviceBean);
setRestServiceInstance(serviceBean);
}
private void setRestServiceInstance(ServiceBean serviceBean) {
List<URL> urls = serviceBean.getExportedUrls();
urls.stream()
.filter(url -> "rest".equalsIgnoreCase(url.getProtocol()))
.forEach(url -> {
String host = url.getIp();
int port = url.getPort();
if (restServiceInstance == null) {
String instanceId = currentApplicationName + "-" + host + ":" + port;
this.restServiceInstance = new DefaultServiceInstance(instanceId, currentApplicationName,
host, port, false, new HashMap<>());
} else {
if (!host.equals(restServiceInstance.getHost())) {
if (logger.isWarnEnabled()) {
logger.warn("Current application[{}] host is not consistent, expected: {}, actual: {}",
currentApplicationName, restServiceInstance.getHost(), host);
}
}
if (port != restServiceInstance.getPort()) {
if (logger.isWarnEnabled()) {
logger.warn("Current application[{}] port is not consistent, expected: {}, actual: {}",
currentApplicationName, restServiceInstance.getPort(), port);
}
}
}
});
}
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
exportDubboMetadataConfigService();
}
@EventListener(ApplicationFailedEvent.class)
public void onApplicationFailed() {
unexportDubboMetadataConfigService();
}
@EventListener(ContextClosedEvent.class)
public void onContextClosed() {
unexportDubboMetadataConfigService();
}
@ConditionalOnNotWebApplication
@Bean
public ApplicationRunner applicationRunner() {
return args -> {
if (restServiceInstance == null) {
return;
}
// From RegistrationFactoryProvider
RegistrationFactory registrationFactory = context.getBean(RegistrationFactory.class);
ServiceRegistry<Registration> serviceRegistry = context.getBean(ServiceRegistry.class);
Registration registration = context.getBean(Registration.class);
restServiceInstance.getMetadata().putAll(registration.getMetadata());
serviceRegistry.register(registrationFactory.create(restServiceInstance, context));
};
}
private void publishServiceRestMetadata(ServiceBean serviceBean) {
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
}
private void exportDubboMetadataConfigService() {
if (serviceConfig != null && serviceConfig.isExported()) {
return;
}
if (StringUtils.isEmpty(dubboMetadataConfigService.getServiceRestMetadata())) {
// If there is no REST metadata, DubboMetadataConfigService will not be exported.
if (logger.isInfoEnabled()) {
logger.info("There is no REST metadata, the Dubbo service[{}] will not be exported.",
dubboMetadataConfigService.getClass().getName());
}
return;
}
serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(DubboMetadataConfigService.class);
// Use current Spring application name as the Dubbo Service version
serviceConfig.setVersion(currentApplicationName);
serviceConfig.setRef(dubboMetadataConfigService);
serviceConfig.setApplication(applicationConfig);
serviceConfig.setProtocol(metadataProtocolConfig);
serviceConfig.export();
if (logger.isInfoEnabled()) {
logger.info("The Dubbo service[{}] has been exported.", serviceConfig.toString());
}
}
private void unexportDubboMetadataConfigService() {
if (serviceConfig == null || serviceConfig.isUnexported()) {
return;
}
serviceConfig.unexport();
if (logger.isInfoEnabled()) {
logger.info("The Dubbo service[{}] has been unexported.", serviceConfig.toString());
}
}
}

View File

@ -16,14 +16,9 @@
*/
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import feign.Contract;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
import org.springframework.cloud.alibaba.dubbo.openfeign.TargeterBeanPostProcessor;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
@ -31,22 +26,20 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration.TARGETER_CLASS_NAME;
/**
* Dubbo Feign Auto-{@link Configuration Configuration}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConditionalOnClass(name = {"feign.Feign"})
@ConditionalOnClass(name = {"feign.Feign", TARGETER_CLASS_NAME})
@AutoConfigureAfter(name = {"org.springframework.cloud.openfeign.FeignAutoConfiguration"})
@Configuration
public class DubboOpenFeignAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MetadataResolver metadataJsonResolver(ObjectProvider<Contract> contract) {
return new DubboServiceBeanMetadataResolver(contract);
}
public static final String TARGETER_CLASS_NAME = "org.springframework.cloud.openfeign.Targeter";
@Bean
public TargeterBeanPostProcessor targeterBeanPostProcessor(Environment environment,

View File

@ -1,62 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import com.alibaba.dubbo.config.spring.ServiceBean;
import com.alibaba.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
/**
* The Auto-Configuration class for Dubbo REST metadata registration,
* REST metadata that is a part of {@link Registration#getMetadata() Spring Cloud service instances' metadata}
* will be registered Spring Cloud registry.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@ConditionalOnBean(value = {
MetadataResolver.class
})
@AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class})
@Configuration
public class DubboRestMetadataRegistrationAutoConfiguration {
@Autowired
private MetadataResolver metadataResolver;
@Autowired
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
@Value("${spring.application.name:application}")
private String currentApplicationName;
@EventListener(ServiceBeanExportedEvent.class)
public void recordRestMetadata(ServiceBeanExportedEvent event) {
ServiceBean serviceBean = event.getServiceBean();
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
}
}

View File

@ -16,16 +16,35 @@
*/
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.spring.util.PropertySourcesUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactoryProvider;
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
import org.springframework.cloud.alibaba.dubbo.registry.handler.StandardDubboRegistryServiceIdHandler;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
import org.springframework.cloud.alibaba.dubbo.service.parameter.PathVariableServiceParameterResolver;
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestBodyServiceParameterResolver;
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestHeaderServiceParameterResolver;
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestParamServiceParameterResolver;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertyResolver;
import org.springframework.lang.Nullable;
import java.util.Map;
import static org.apache.dubbo.spring.boot.util.DubboUtils.BASE_PACKAGES_PROPERTY_RESOLVER_BEAN_NAME;
import static org.apache.dubbo.spring.boot.util.DubboUtils.DUBBO_SCAN_PREFIX;
/**
* Spring Boot Auto-Configuration class for Dubbo Service
@ -51,4 +70,92 @@ public class DubboServiceAutoConfiguration {
})
static class ParameterResolversConfiguration {
}
@Bean
@ConditionalOnMissingBean
public DubboRegistryServiceIdHandler dubboRegistryServiceIdHandler(ConfigurableApplicationContext context) {
return new StandardDubboRegistryServiceIdHandler(context);
}
@Bean
public RegistrationFactoryProvider registrationFactoryProvider() {
return new RegistrationFactoryProvider();
}
/**
* Bugfix code for an issue : https://github.com/apache/incubator-dubbo-spring-boot-project/issues/459
*
* @param environment {@link ConfigurableEnvironment}
* @return a Bean of {@link PropertyResolver}
*/
@Primary
@Bean(name = BASE_PACKAGES_PROPERTY_RESOLVER_BEAN_NAME)
public PropertyResolver dubboScanBasePackagesPropertyResolver(ConfigurableEnvironment environment) {
ConfigurableEnvironment propertyResolver = new AbstractEnvironment() {
protected void customizePropertySources(MutablePropertySources propertySources) {
Map<String, Object> dubboScanProperties = PropertySourcesUtils.getSubProperties(environment, DUBBO_SCAN_PREFIX);
propertySources.addLast(new MapPropertySource("dubboScanProperties", dubboScanProperties));
}
};
ConfigurationPropertySources.attach(propertyResolver);
return new DelegatingPropertyResolver(propertyResolver);
}
private static class DelegatingPropertyResolver implements PropertyResolver {
private final PropertyResolver delegate;
DelegatingPropertyResolver(PropertyResolver delegate) {
Assert.notNull(delegate, "The delegate of PropertyResolver must not be null");
this.delegate = delegate;
}
@Override
public boolean containsProperty(String key) {
return delegate.containsProperty(key);
}
@Override
@Nullable
public String getProperty(String key) {
return delegate.getProperty(key);
}
@Override
public String getProperty(String key, String defaultValue) {
return delegate.getProperty(key, defaultValue);
}
@Override
@Nullable
public <T> T getProperty(String key, Class<T> targetType) {
return delegate.getProperty(key, targetType);
}
@Override
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
return delegate.getProperty(key, targetType, defaultValue);
}
@Override
public String getRequiredProperty(String key) throws IllegalStateException {
return delegate.getRequiredProperty(key);
}
@Override
public <T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException {
return delegate.getRequiredProperty(key, targetType);
}
@Override
public String resolvePlaceholders(String text) {
return delegate.resolvePlaceholders(text);
}
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
return delegate.resolveRequiredPlaceholders(text);
}
}
}

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.client.loadbalancer;
import com.alibaba.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.client.loadbalancer;
import com.alibaba.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericException;
import org.springframework.cloud.alibaba.dubbo.http.converter.HttpMessageConverterHolder;
import org.springframework.cloud.alibaba.dubbo.http.util.HttpMessageConverterResolver;
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;

View File

@ -16,9 +16,8 @@
*/
package org.springframework.cloud.alibaba.dubbo.client.loadbalancer;
import com.alibaba.dubbo.rpc.service.GenericException;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.cloud.alibaba.dubbo.http.MutableHttpServerRequest;
import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata;

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.http;
import com.alibaba.dubbo.common.io.UnsafeByteArrayInputStream;
import org.apache.dubbo.common.io.UnsafeByteArrayInputStream;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;

View File

@ -30,16 +30,16 @@ import java.util.Set;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ServiceRestMetadata {
private String name;
private String url;
private Set<RestMethodMetadata> meta;
public String getName() {
return name;
public String getUrl() {
return url;
}
public void setName(String name) {
this.name = name;
public void setUrl(String url) {
this.url = url;
}
public Set<RestMethodMetadata> getMeta() {
@ -55,12 +55,12 @@ public class ServiceRestMetadata {
if (this == o) return true;
if (!(o instanceof ServiceRestMetadata)) return false;
ServiceRestMetadata that = (ServiceRestMetadata) o;
return Objects.equals(name, that.name) &&
return Objects.equals(url, that.url) &&
Objects.equals(meta, that.meta);
}
@Override
public int hashCode() {
return Objects.hash(name, meta);
return Objects.hash(url, meta);
}
}

View File

@ -16,20 +16,18 @@
*/
package org.springframework.cloud.alibaba.dubbo.metadata.resolver;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.config.spring.ServiceBean;
import feign.Contract;
import feign.Feign;
import feign.MethodMetadata;
import feign.Util;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.spring.ServiceBean;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
import org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Method;
@ -116,10 +114,10 @@ public class DubboServiceBeanMetadataResolver implements BeanClassLoaderAware, S
List<URL> urls = serviceBean.getExportedUrls();
urls.stream()
.map(SpringCloudRegistry::getServiceName)
.forEach(serviceName -> {
.map(URL::toString)
.forEach(url -> {
ServiceRestMetadata metadata = new ServiceRestMetadata();
metadata.setName(serviceName);
metadata.setUrl(url);
metadata.setMeta(methodRestMetadata);
serviceRestMetadata.add(metadata);
});

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.metadata.resolver;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.openfeign;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContext;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.openfeign;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
import java.lang.reflect.Method;

View File

@ -25,6 +25,7 @@ import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactor
import org.springframework.core.env.Environment;
import static java.lang.reflect.Proxy.newProxyInstance;
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration.TARGETER_CLASS_NAME;
import static org.springframework.util.ClassUtils.getUserClass;
import static org.springframework.util.ClassUtils.isPresent;
import static org.springframework.util.ClassUtils.resolveClassName;
@ -36,8 +37,6 @@ import static org.springframework.util.ClassUtils.resolveClassName;
*/
public class TargeterBeanPostProcessor implements BeanPostProcessor, BeanClassLoaderAware {
private static final String TARGETER_CLASS_NAME = "org.springframework.cloud.openfeign.Targeter";
private final Environment environment;
private final DubboServiceMetadataRepository dubboServiceMetadataRepository;

View File

@ -17,10 +17,9 @@
package org.springframework.cloud.alibaba.dubbo.openfeign;
import com.alibaba.dubbo.rpc.service.GenericService;
import feign.Contract;
import feign.Target;
import org.apache.dubbo.rpc.service.GenericService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported;

View File

@ -16,13 +16,13 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.LinkedHashMap;
@ -30,20 +30,39 @@ import java.util.LinkedHashMap;
* Abstract {@link RegistrationFactory} implementation
* <p>
*
* @param <T> The subclass of {@link Registration}
* @param <R> The subclass of {@link Registration}
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public abstract class AbstractRegistrationFactory<T extends Registration> implements RegistrationFactory<T> {
public abstract class AbstractRegistrationFactory<R extends Registration> implements RegistrationFactory<R> {
protected ServiceInstance createServiceInstance(String serviceName, URL url) {
public final R create(URL url, ConfigurableApplicationContext applicationContext) {
ServiceInstance serviceInstance = createServiceInstance(url, applicationContext);
return create(serviceInstance, applicationContext);
}
/**
* Create an instance {@link ServiceInstance}. This method maybe override by sub-class.
*
* @param url The Dubbo's {@link URL}
* @param applicationContext {@link ConfigurableApplicationContext}
* @return an instance {@link ServiceInstance}
*/
protected ServiceInstance createServiceInstance(URL url, ConfigurableApplicationContext applicationContext) {
String serviceId = createServiceId(url, applicationContext);
// Append default category if absent
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
URL newURL = url.addParameter(Constants.CATEGORY_KEY, category);
newURL = newURL.addParameter(Constants.PROTOCOL_KEY, url.getProtocol());
String ip = NetUtils.getLocalHost();
String ip = url.getIp();
int port = newURL.getParameter(Constants.BIND_PORT_KEY, url.getPort());
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(url.toIdentityString(), serviceName, ip, port, false);
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(url.toIdentityString(), serviceId, ip, port, false);
serviceInstance.getMetadata().putAll(new LinkedHashMap<>(newURL.getParameters()));
return serviceInstance;
}
protected String createServiceId(URL url, ConfigurableApplicationContext applicationContext) {
DubboRegistryServiceIdHandler handler = applicationContext.getBean(DubboRegistryServiceIdHandler.class);
return handler.createServiceId(url);
}
}

View File

@ -16,10 +16,9 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.URL;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Default {@link RegistrationFactory}
@ -29,7 +28,7 @@ import org.springframework.context.ApplicationContext;
public class DefaultRegistrationFactory extends AbstractRegistrationFactory<Registration> {
@Override
public Registration create(String serviceName, URL url, ApplicationContext applicationContext) {
return new DelegatingRegistration(createServiceInstance(serviceName, url));
public Registration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
return new DelegatingRegistration(serviceInstance);
}
}

View File

@ -16,27 +16,35 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.URL;
import org.apache.dubbo.common.URL;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* {@link Registration} Factory to createServiceInstance a instance of {@link Registration}
*
* @param <T> The subclass of {@link Registration}
* @param <R> The subclass of {@link Registration}
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public interface RegistrationFactory<T extends Registration> {
public interface RegistrationFactory<R extends Registration> {
/**
* Create a instance of {@link T}
* Create a instance of {@link R}
*
* @param serviceName The service name of Dubbo service interface
* @param url The Dubbo's URL
* @param applicationContext {@link ApplicationContext}
* @return a instance of {@link T}
* @param url The Dubbo's {@link URL}
* @param applicationContext {@link ConfigurableApplicationContext}
* @return a instance of {@link R}, if null, it indicates the registration will not be executed.
*/
T create(String serviceName, URL url, ApplicationContext applicationContext);
R create(URL url, ConfigurableApplicationContext applicationContext);
/**
* Create a instance of {@link R}
*
* @param serviceInstance {@link ServiceInstance}
* @param applicationContext {@link ConfigurableApplicationContext}
* @return a instance of {@link R}, if null, it indicates the registration will not be executed.
*/
R create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext);
}

View File

@ -0,0 +1,144 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.ResolvableType;
import java.util.List;
import static org.springframework.beans.BeanUtils.instantiateClass;
import static org.springframework.core.ResolvableType.forInstance;
import static org.springframework.core.ResolvableType.forType;
import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames;
import static org.springframework.util.ClassUtils.isPresent;
import static org.springframework.util.ClassUtils.resolveClassName;
/**
* {@link RegistrationFactory} Provider
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class RegistrationFactoryProvider implements FactoryBean<RegistrationFactory>, ApplicationContextAware {
private final Logger logger = LoggerFactory.getLogger(getClass());
private RegistrationFactory registrationFactory;
@Override
public RegistrationFactory getObject() throws BeansException {
return registrationFactory;
}
@Override
public Class<?> getObjectType() {
return RegistrationFactory.class;
}
public boolean isSingleton() {
return true;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ServiceRegistry<Registration> serviceRegistry = applicationContext.getBean(ServiceRegistry.class);
ClassLoader classLoader = applicationContext.getClassLoader();
this.registrationFactory = buildRegistrationFactory(serviceRegistry, classLoader);
}
private RegistrationFactory buildRegistrationFactory(ServiceRegistry<Registration> serviceRegistry,
ClassLoader classLoader) {
RegistrationFactory registrationFactory = null;
List<String> factoryClassNames = loadFactoryNames(RegistrationFactory.class, classLoader);
ResolvableType serviceRegistryType = forInstance(serviceRegistry);
// Get first generic Class
Class<?> registrationClass = resolveGenericClass(serviceRegistryType, ServiceRegistry.class, 0);
for (String factoryClassName : factoryClassNames) {
if (isPresent(factoryClassName, classLoader)) { // ignore compilation issue
Class<?> factoryClass = resolveClassName(factoryClassName, classLoader);
ResolvableType registrationFactoryType = forType(factoryClass);
Class<?> actualRegistrationClass = resolveGenericClass(registrationFactoryType, RegistrationFactory.class, 0);
if (registrationClass.equals(actualRegistrationClass)) {
registrationFactory = (RegistrationFactory) instantiateClass(registrationFactoryType.getRawClass());
break;
}
}
}
if (registrationFactory == null) {
if (logger.isWarnEnabled()) {
logger.warn("{} implementation can't be resolved by ServiceRegistry[{}]",
registrationClass.getSimpleName(), serviceRegistry.getClass().getName());
}
registrationFactory = new DefaultRegistrationFactory();
} else {
if (logger.isInfoEnabled()) {
logger.info("{} has been resolved by ServiceRegistry[{}]",
registrationFactory.getClass().getName(), serviceRegistry.getClass().getName());
}
}
return registrationFactory;
}
private Class<?> resolveGenericClass(ResolvableType implementedType, Class<?> interfaceClass, int index) {
ResolvableType resolvableType = implementedType;
try {
OUTER:
while (true) {
ResolvableType[] interfaceTypes = resolvableType.getInterfaces();
for (ResolvableType interfaceType : interfaceTypes) {
if (interfaceType.resolve().equals(interfaceClass)) {
resolvableType = interfaceType;
break OUTER;
}
}
ResolvableType superType = resolvableType.getSuperType();
Class<?> superClass = superType.resolve();
if (Object.class.equals(superClass)) {
break;
}
resolvableType = superType;
}
} catch (Throwable e) {
resolvableType = ResolvableType.forType(void.class);
}
return resolvableType.resolveGeneric(index);
}
}

View File

@ -16,47 +16,37 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
import com.alibaba.dubbo.common.utils.UrlUtils;
import com.alibaba.dubbo.registry.NotifyListener;
import com.alibaba.dubbo.registry.RegistryFactory;
import com.alibaba.dubbo.registry.support.FailbackRegistry;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.registry.NotifyListener;
import org.apache.dubbo.registry.RegistryFactory;
import org.apache.dubbo.registry.support.FailbackRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.util.StringUtils;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.alibaba.dubbo.common.Constants.CONFIGURATORS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.CONSUMERS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.ROUTERS_CATEGORY;
import static java.lang.Long.getLong;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.springframework.beans.BeanUtils.instantiateClass;
import static org.springframework.core.ResolvableType.forInstance;
import static org.springframework.core.ResolvableType.forType;
import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames;
import static org.springframework.util.ClassUtils.isPresent;
import static org.springframework.util.ClassUtils.resolveClassName;
import static java.util.Collections.singletonList;
import static org.apache.dubbo.common.Constants.CONFIGURATORS_CATEGORY;
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static org.apache.dubbo.common.Constants.PROVIDER_SIDE;
import static org.apache.dubbo.common.Constants.ROUTERS_CATEGORY;
import static org.apache.dubbo.common.Constants.SIDE_KEY;
/**
* Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud"
@ -65,306 +55,131 @@ import static org.springframework.util.ClassUtils.resolveClassName;
*/
public class SpringCloudRegistry extends FailbackRegistry {
/**
* The parameter name of {@link #allServicesLookupInterval}
*/
public static final String ALL_SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.all.services.lookup.interval";
/**
* The parameter name of {@link #registeredServicesLookupInterval}
*/
public static final String REGISTERED_SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.registered.services.lookup.interval";
/**
* All supported categories
*/
private static final String[] ALL_SUPPORTED_CATEGORIES = of(
public static final String[] ALL_SUPPORTED_CATEGORIES = of(
PROVIDERS_CATEGORY,
CONSUMERS_CATEGORY,
ROUTERS_CATEGORY,
CONFIGURATORS_CATEGORY
);
private static final int CATEGORY_INDEX = 0;
private static final int SERVICE_INTERFACE_INDEX = CATEGORY_INDEX + 1;
private static final int SERVICE_VERSION_INDEX = SERVICE_INTERFACE_INDEX + 1;
private static final int SERVICE_GROUP_INDEX = SERVICE_VERSION_INDEX + 1;
private static final String WILDCARD = "*";
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* The interval in second of lookup service names(only for Dubbo-OPS)
*/
private static final long ALL_SERVICES_LOOKUP_INTERVAL = getLong("dubbo.all.services.lookup.interval", 30);
private final long allServicesLookupInterval;
/**
* The interval in second of lookup regigered service instances
*/
private static final long REGISTERED_SERVICES_LOOKUP_INTERVAL = getLong("dubbo.registered.services.lookup.interval", 300);
/**
* The {@link ScheduledExecutorService Scheduler} to lookup the registered services
*/
private static final ScheduledExecutorService registeredServicesLookupScheduler = newSingleThreadScheduledExecutor(new NamedThreadFactory("dubbo-registered-services-lookup-"));
/**
* The {@link ScheduledExecutorService Scheduler} to lookup all services (only for Dubbo-OPS)
*/
private static volatile ScheduledExecutorService allServicesLookupScheduler;
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* The separator for service name
*/
private static final String SERVICE_NAME_SEPARATOR = ":";
private final ApplicationContext applicationContext;
private final long registeredServicesLookupInterval;
private final ServiceRegistry<Registration> serviceRegistry;
private final DiscoveryClient discoveryClient;
private final RegistrationFactory registrationFactory;
public SpringCloudRegistry(URL url, ApplicationContext applicationContext) {
private final DiscoveryClient discoveryClient;
private final DubboRegistryServiceIdHandler dubboRegistryServiceIdHandler;
private final ScheduledExecutorService servicesLookupScheduler;
private final ConfigurableApplicationContext applicationContext;
public SpringCloudRegistry(URL url,
ServiceRegistry<Registration> serviceRegistry,
RegistrationFactory registrationFactory,
DiscoveryClient discoveryClient,
ScheduledExecutorService servicesLookupScheduler,
ConfigurableApplicationContext applicationContext) {
super(url);
this.allServicesLookupInterval = url.getParameter(ALL_SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 30L);
this.registeredServicesLookupInterval = url.getParameter(REGISTERED_SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 300L);
this.serviceRegistry = serviceRegistry;
this.registrationFactory = registrationFactory;
this.discoveryClient = discoveryClient;
this.dubboRegistryServiceIdHandler = applicationContext.getBean(DubboRegistryServiceIdHandler.class);
this.applicationContext = applicationContext;
this.serviceRegistry = applicationContext.getBean(ServiceRegistry.class);
this.registrationFactory = buildRegistrationFactory(serviceRegistry, applicationContext.getClassLoader());
this.discoveryClient = applicationContext.getBean(DiscoveryClient.class);
applicationContext.getClassLoader();
this.servicesLookupScheduler = servicesLookupScheduler;
}
private RegistrationFactory buildRegistrationFactory(ServiceRegistry<Registration> serviceRegistry,
ClassLoader classLoader) {
RegistrationFactory registrationFactory = null;
List<String> factoryClassNames = loadFactoryNames(RegistrationFactory.class, classLoader);
ResolvableType serviceRegistryType = forInstance(serviceRegistry);
// Get first generic Class
Class<?> registrationClass = resolveGenericClass(serviceRegistryType, ServiceRegistry.class, 0);
for (String factoryClassName : factoryClassNames) {
if (isPresent(factoryClassName, classLoader)) { // ignore compilation issue
Class<?> factoryClass = resolveClassName(factoryClassName, classLoader);
ResolvableType registrationFactoryType = forType(factoryClass);
Class<?> actualRegistrationClass = resolveGenericClass(registrationFactoryType, RegistrationFactory.class, 0);
if (registrationClass.equals(actualRegistrationClass)) {
registrationFactory = (RegistrationFactory) instantiateClass(registrationFactoryType.getRawClass());
break;
}
}
}
if (registrationFactory == null) {
if (logger.isWarnEnabled()) {
logger.warn("{} implementation can't be resolved by ServiceRegistry[{}]",
registrationClass.getSimpleName(), serviceRegistry.getClass().getName());
}
registrationFactory = new DefaultRegistrationFactory();
} else {
if (logger.isInfoEnabled()) {
logger.info("{} has been resolved by ServiceRegistry[{}]",
registrationFactory.getClass().getName(), serviceRegistry.getClass().getName());
}
}
return registrationFactory;
}
private Class<?> resolveGenericClass(ResolvableType implementedType, Class<?> interfaceClass, int index) {
ResolvableType resolvableType = implementedType;
try {
OUTER:
while (true) {
ResolvableType[] interfaceTypes = resolvableType.getInterfaces();
for (ResolvableType interfaceType : interfaceTypes) {
if (interfaceType.resolve().equals(interfaceClass)) {
resolvableType = interfaceType;
break OUTER;
}
}
ResolvableType superType = resolvableType.getSuperType();
Class<?> superClass = superType.resolve();
if (Object.class.equals(superClass)) {
break;
}
resolvableType = superType;
}
} catch (Throwable e) {
resolvableType = ResolvableType.forType(void.class);
}
return resolvableType.resolveGeneric(index);
}
@Override
protected void doRegister(URL url) {
final String serviceName = getServiceName(url);
final Registration registration = createRegistration(serviceName, url);
serviceRegistry.register(registration);
protected boolean shouldRegister(Registration registration) {
Map<String, String> metadata = registration.getMetadata();
String side = metadata.get(SIDE_KEY);
return PROVIDER_SIDE.equals(side); // Only register the Provider.
}
@Override
protected void doUnregister(URL url) {
final String serviceName = getServiceName(url);
final Registration registration = createRegistration(serviceName, url);
this.serviceRegistry.deregister(registration);
public void doRegister(URL url) {
final Registration registration = createRegistration(url);
if (shouldRegister(registration)) {
serviceRegistry.register(registration);
}
}
@Override
protected void doSubscribe(URL url, NotifyListener listener) {
public void doUnregister(URL url) {
final Registration registration = createRegistration(url);
if (shouldRegister(registration)) {
this.serviceRegistry.deregister(registration);
}
}
@Override
public void doSubscribe(URL url, NotifyListener listener) {
List<String> serviceNames = getServiceNames(url, listener);
doSubscribe(url, listener, serviceNames);
this.registeredServicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
this.servicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
doSubscribe(url, listener, serviceNames);
}
}, REGISTERED_SERVICES_LOOKUP_INTERVAL, REGISTERED_SERVICES_LOOKUP_INTERVAL, TimeUnit.SECONDS);
}, registeredServicesLookupInterval, registeredServicesLookupInterval, TimeUnit.SECONDS);
}
@Override
protected void doUnsubscribe(URL url, NotifyListener listener) {
public void doUnsubscribe(URL url, NotifyListener listener) {
if (isAdminProtocol(url)) {
shutdownServiceNamesLookup();
}
// if (registeredServicesLookupScheduler != null) {
// registeredServicesLookupScheduler.shutdown();
// }
}
@Override
public boolean isAvailable() {
return false;
return !discoveryClient.getServices().isEmpty();
}
private void shutdownServiceNamesLookup() {
if (allServicesLookupScheduler != null) {
allServicesLookupScheduler.shutdown();
if (servicesLookupScheduler != null) {
servicesLookupScheduler.shutdown();
}
}
private Registration createRegistration(String serviceName, URL url) {
return registrationFactory.create(serviceName, url, applicationContext);
private Registration createRegistration(URL url) {
return registrationFactory.create(url, applicationContext);
}
public static String getServiceName(URL url) {
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
return getServiceName(url, category);
}
private static String getServiceName(URL url, String category) {
StringBuilder serviceNameBuilder = new StringBuilder(category);
appendIfPresent(serviceNameBuilder, url, Constants.INTERFACE_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.VERSION_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.GROUP_KEY);
return serviceNameBuilder.toString();
}
private static void appendIfPresent(StringBuilder target, URL url, String parameterName) {
String parameterValue = url.getParameter(parameterName);
appendIfPresent(target, parameterValue);
}
private static void appendIfPresent(StringBuilder target, String parameterValue) {
if (StringUtils.hasText(parameterValue)) {
target.append(SERVICE_NAME_SEPARATOR).append(parameterValue);
}
}
private void filterServiceNames(List<String> serviceNames, URL url) {
final String[] categories = getCategories(url);
final String targetServiceInterface = url.getServiceInterface();
final String targetVersion = url.getParameter(Constants.VERSION_KEY);
final String targetGroup = url.getParameter(Constants.GROUP_KEY);
private void filterServiceNames(List<String> serviceNames) {
filter(serviceNames, new Filter<String>() {
@Override
public boolean accept(String serviceName) {
// split service name to segments
// (required) segments[0] = category
// (required) segments[1] = serviceInterface
// (required) segments[2] = version
// (optional) segments[3] = group
String[] segments = getServiceSegments(serviceName);
int length = segments.length;
if (length < SERVICE_GROUP_INDEX) { // must present 4 segments or more
return false;
}
String category = getCategory(segments);
if (Arrays.binarySearch(categories, category) > -1) { // no match category
return false;
}
String serviceInterface = getServiceInterface(segments);
if (!WILDCARD.equals(targetServiceInterface) &&
!Objects.equals(targetServiceInterface, serviceInterface)) { // no match service interface
return false;
}
String version = getServiceVersion(segments);
if (!WILDCARD.equals(targetVersion) &&
!Objects.equals(targetVersion, version)) { // no match service version
return false;
}
String group = getServiceGroup(segments);
if (group != null && !WILDCARD.equals(targetGroup)
&& !Objects.equals(targetGroup, group)) { // no match service group
return false;
}
return true;
return dubboRegistryServiceIdHandler.supports(serviceName);
}
});
}
public static String[] getServiceSegments(String serviceName) {
return StringUtils.delimitedListToStringArray(serviceName, SERVICE_NAME_SEPARATOR);
}
public static String getCategory(String[] segments) {
return segments[CATEGORY_INDEX];
}
public static String getServiceInterface(String[] segments) {
return segments[SERVICE_INTERFACE_INDEX];
}
public static String getServiceVersion(String[] segments) {
return segments[SERVICE_VERSION_INDEX];
}
public static String getServiceGroup(String[] segments) {
return segments.length > SERVICE_GROUP_INDEX ? segments[SERVICE_GROUP_INDEX] : null;
}
/**
* Get the categories from {@link URL}
*
* @param url {@link URL}
* @return non-null array
*/
private String[] getCategories(URL url) {
return Constants.ANY_VALUE.equals(url.getServiceInterface()) ?
ALL_SUPPORTED_CATEGORIES : of(Constants.DEFAULT_CATEGORY);
}
private List<String> getAllServiceNames() {
return discoveryClient.getServices();
return new LinkedList<>(discoveryClient.getServices());
}
/**
@ -379,7 +194,7 @@ public class SpringCloudRegistry extends FailbackRegistry {
initAllServicesLookupScheduler(url, listener);
return getServiceNamesForOps(url);
} else {
return doGetServiceNames(url);
return singletonList(dubboRegistryServiceIdHandler.createServiceId(url));
}
}
@ -389,30 +204,14 @@ public class SpringCloudRegistry extends FailbackRegistry {
}
private void initAllServicesLookupScheduler(final URL url, final NotifyListener listener) {
if (allServicesLookupScheduler == null) {
allServicesLookupScheduler = newSingleThreadScheduledExecutor(new NamedThreadFactory("dubbo-all-services-lookup-"));
allServicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
List<String> serviceNames = getAllServiceNames();
filter(serviceNames, new Filter<String>() {
@Override
public boolean accept(String serviceName) {
boolean accepted = false;
for (String category : ALL_SUPPORTED_CATEGORIES) {
String prefix = category + SERVICE_NAME_SEPARATOR;
if (StringUtils.startsWithIgnoreCase(serviceName, prefix)) {
accepted = true;
break;
}
}
return accepted;
}
});
doSubscribe(url, listener, serviceNames);
}
}, ALL_SERVICES_LOOKUP_INTERVAL, ALL_SERVICES_LOOKUP_INTERVAL, TimeUnit.SECONDS);
}
servicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
List<String> serviceNames = getAllServiceNames();
filterServiceNames(serviceNames);
doSubscribe(url, listener, serviceNames);
}
}, allServicesLookupInterval, allServicesLookupInterval, TimeUnit.SECONDS);
}
private void doSubscribe(final URL url, final NotifyListener listener, final List<String> serviceNames) {
@ -422,16 +221,6 @@ public class SpringCloudRegistry extends FailbackRegistry {
}
}
private List<String> doGetServiceNames(URL url) {
String[] categories = getCategories(url);
List<String> serviceNames = new ArrayList<String>(categories.length);
for (String category : categories) {
final String serviceName = getServiceName(url, category);
serviceNames.add(serviceName);
}
return serviceNames;
}
/**
* Notify the Healthy {@link ServiceInstance service instance} to subscriber.
*
@ -488,7 +277,7 @@ public class SpringCloudRegistry extends FailbackRegistry {
*/
private List<String> getServiceNamesForOps(URL url) {
List<String> serviceNames = getAllServiceNames();
filterServiceNames(serviceNames, url);
filterServiceNames(serviceNames);
return serviceNames;
}
@ -509,7 +298,7 @@ public class SpringCloudRegistry extends FailbackRegistry {
/**
* A filter
*/
private interface Filter<T> {
public interface Filter<T> {
/**
* Tests whether or not the specified data should be accepted.

View File

@ -16,11 +16,21 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.RegistryFactory;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.ApplicationContext;
import java.util.concurrent.ScheduledExecutorService;
import static java.lang.System.getProperty;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
/**
* Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud"
@ -31,14 +41,46 @@ import org.springframework.context.ApplicationContext;
*/
public class SpringCloudRegistryFactory implements RegistryFactory {
private static ApplicationContext applicationContext;
private static String SERVICES_LOOKUP_SCHEDULER_THREAD_NAME_PREFIX =
getProperty("dubbo.services.lookup.scheduler.thread.name.prefix ", "dubbo-services-lookup-");
private static ConfigurableApplicationContext applicationContext;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final ScheduledExecutorService servicesLookupScheduler;
private ServiceRegistry<Registration> serviceRegistry;
private RegistrationFactory registrationFactory;
private DiscoveryClient discoveryClient;
private volatile boolean initialized = false;
public SpringCloudRegistryFactory() {
servicesLookupScheduler = newSingleThreadScheduledExecutor(
new NamedThreadFactory(SERVICES_LOOKUP_SCHEDULER_THREAD_NAME_PREFIX));
}
protected void init() {
if (initialized || applicationContext == null) {
return;
}
this.serviceRegistry = applicationContext.getBean(ServiceRegistry.class);
this.registrationFactory = applicationContext.getBean(RegistrationFactory.class);
this.discoveryClient = applicationContext.getBean(DiscoveryClient.class);
}
@Override
public Registry getRegistry(URL url) {
return new SpringCloudRegistry(url, applicationContext);
init();
return new SpringCloudRegistry(url, serviceRegistry, registrationFactory, discoveryClient,
servicesLookupScheduler, applicationContext);
}
public static void setApplicationContext(ApplicationContext applicationContext) {
public static void setApplicationContext(ConfigurableApplicationContext applicationContext) {
SpringCloudRegistryFactory.applicationContext = applicationContext;
}
}

View File

@ -16,15 +16,13 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry.apache.zookeeper;
import com.alibaba.dubbo.common.URL;
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.serviceregistry.ServiceInstanceRegistration;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Zookeeper {@link RegistrationFactory}
@ -34,10 +32,7 @@ import org.springframework.context.ApplicationContext;
public class ZookeeperRegistrationFactory extends AbstractRegistrationFactory<ZookeeperRegistration> {
@Override
public ZookeeperRegistration create(String serviceName, URL url, ApplicationContext applicationContext) {
ServiceInstance serviceInstance = createServiceInstance(serviceName, url);
public ZookeeperRegistration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
ZookeeperInstance zookeeperInstance = new ZookeeperInstance(serviceInstance.getInstanceId(),
serviceInstance.getServiceId(), serviceInstance.getMetadata());

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.registry.handler;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.registry.Registry;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Dubbo {@link Registry} Spring Cloud Service Id Builder
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public interface DubboRegistryServiceIdHandler {
/**
* Supports the specified id of Spring Cloud Service or not
*
* @param serviceId the specified id of Spring Cloud Service
* @return if supports, return <code>true</code>, or <code>false</code>
*/
boolean supports(String serviceId);
/**
* Creates the id of Spring Cloud Service
*
* @param url The Dubbo's {@link URL}
* @return non-null
*/
String createServiceId(URL url);
/**
* The instance if {@link ConfigurableApplicationContext} .
*
* @return non-null
*/
ConfigurableApplicationContext getContext();
}

View File

@ -0,0 +1,96 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.registry.handler;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.StringUtils;
import java.util.Objects;
import static java.lang.System.getProperty;
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static org.springframework.util.StringUtils.startsWithIgnoreCase;
/**
* The Standard {@link DubboRegistryServiceIdHandler}
* <p>
* The service ID pattern is "${category}:${interface}:${version}:${group}"
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class StandardDubboRegistryServiceIdHandler implements DubboRegistryServiceIdHandler {
/**
* The separator for service name that could be changed by the Java Property "dubbo.service.name.separator".
*/
protected static final String SERVICE_NAME_SEPARATOR = getProperty("dubbo.service.name.separator", ":");
private final ConfigurableApplicationContext context;
public StandardDubboRegistryServiceIdHandler(ConfigurableApplicationContext context) {
this.context = context;
}
@Override
public boolean supports(String serviceId) {
return startsWithIgnoreCase(serviceId, PROVIDERS_CATEGORY) ||
startsWithIgnoreCase(serviceId, CONSUMERS_CATEGORY);
}
@Override
public String createServiceId(URL url) {
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
if (!Objects.equals(category, PROVIDERS_CATEGORY) && !Objects.equals(category, CONSUMERS_CATEGORY)) {
category = PROVIDERS_CATEGORY;
}
return createServiceId(url, category);
}
@Override
public ConfigurableApplicationContext getContext() {
return context;
}
/**
* This method maybe override by sub-class.
*
* @param url The Dubbo's {@link URL}
* @param category The category
* @return
*/
protected String createServiceId(URL url, String category) {
StringBuilder serviceNameBuilder = new StringBuilder(category);
appendIfPresent(serviceNameBuilder, url, Constants.INTERFACE_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.VERSION_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.GROUP_KEY);
return serviceNameBuilder.toString();
}
private static void appendIfPresent(StringBuilder target, URL url, String parameterName) {
String parameterValue = url.getParameter(parameterName);
appendIfPresent(target, parameterValue);
}
private static void appendIfPresent(StringBuilder target, String parameterValue) {
if (StringUtils.hasText(parameterValue)) {
target.append(SERVICE_NAME_SEPARATOR).append(parameterValue);
}
}
}

View File

@ -16,8 +16,6 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry.hashicorp.consul;
import com.alibaba.dubbo.common.URL;
import com.ecwid.consul.v1.agent.model.NewService;
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
@ -25,7 +23,7 @@ import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.discovery.ConsulServerUtils;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.LinkedHashSet;
import java.util.LinkedList;
@ -41,9 +39,7 @@ import java.util.Set;
public class ConsulRegistrationFactory extends AbstractRegistrationFactory<ConsulRegistration> {
@Override
public ConsulRegistration create(String serviceName, URL url, ApplicationContext applicationContext) {
ServiceInstance serviceInstance = createServiceInstance(serviceName, url);
public ConsulRegistration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
Map<String, String> metadata = getMetadata(serviceInstance);
List<String> tags = createTags(metadata);

View File

@ -16,8 +16,6 @@
*/
package org.springframework.cloud.alibaba.dubbo.registry.netflix.eureka;
import com.alibaba.dubbo.common.URL;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.discovery.EurekaClientConfig;
import org.springframework.beans.BeanUtils;
@ -28,7 +26,7 @@ import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.netflix.eureka.CloudEurekaInstanceConfig;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* {@link EurekaRegistration} Factory
@ -38,8 +36,7 @@ import org.springframework.context.ApplicationContext;
public class EurekaRegistrationFactory extends AbstractRegistrationFactory<EurekaRegistration> {
@Override
public EurekaRegistration create(String serviceName, URL url, ApplicationContext applicationContext) {
ServiceInstance serviceInstance = createServiceInstance(serviceName, url);
public EurekaRegistration create(ServiceInstance serviceInstance, ConfigurableApplicationContext applicationContext) {
CloudEurekaInstanceConfig cloudEurekaInstanceConfig = applicationContext.getBean(CloudEurekaInstanceConfig.class);
ObjectProvider<HealthCheckHandler> healthCheckHandler = applicationContext.getBeanProvider(HealthCheckHandler.class);
EurekaClientConfig eurekaClientConfig = applicationContext.getBean(EurekaClientConfig.class);

View File

@ -16,7 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.service;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.service.GenericService;
/**
* Dubbo {@link GenericService} execution context

View File

@ -16,9 +16,9 @@
*/
package org.springframework.cloud.alibaba.dubbo.service;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.rpc.service.GenericService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata;
@ -31,12 +31,10 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static com.alibaba.dubbo.common.Constants.DEFAULT_CLUSTER;
import static com.alibaba.dubbo.common.Constants.DEFAULT_PROTOCOL;
import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceGroup;
import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceInterface;
import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceSegments;
import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceVersion;
import static org.apache.dubbo.common.Constants.DEFAULT_CLUSTER;
import static org.apache.dubbo.common.Constants.DEFAULT_PROTOCOL;
import static org.apache.dubbo.common.Constants.GROUP_KEY;
import static org.apache.dubbo.common.Constants.VERSION_KEY;
/**
* Dubbo {@link GenericService} Factory
@ -67,11 +65,11 @@ public class DubboGenericServiceFactory {
private ReferenceBean<GenericService> build(ServiceRestMetadata serviceRestMetadata,
DubboTransportedMetadata dubboTransportedMetadata) {
String dubboServiceName = serviceRestMetadata.getName();
String[] segments = getServiceSegments(dubboServiceName);
String interfaceName = getServiceInterface(segments);
String version = getServiceVersion(segments);
String group = getServiceGroup(segments);
String urlValue = serviceRestMetadata.getUrl();
URL url = URL.valueOf(urlValue);
String interfaceName = url.getServiceInterface();
String version = url.getParameter(VERSION_KEY);
String group = url.getParameter(GROUP_KEY);
String protocol = dubboTransportedMetadata.getProtocol();
String cluster = dubboTransportedMetadata.getCluster();

View File

@ -16,7 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.service;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.service.GenericService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

View File

@ -16,8 +16,6 @@
*/
package org.springframework.cloud.alibaba.dubbo.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@ -28,15 +26,13 @@ import javax.annotation.PostConstruct;
import java.util.LinkedHashSet;
import java.util.Set;
import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration.METADATA_PROTOCOL_BEAN_NAME;
import static org.springframework.util.ObjectUtils.isEmpty;
/**
* Publishing {@link DubboMetadataConfigService} implementation
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Service(version = "${spring.application.name}", protocol = METADATA_PROTOCOL_BEAN_NAME)
// Use current Spring application name as the Dubbo Service version
public class PublishingDubboMetadataConfigService implements DubboMetadataConfigService {
/**
@ -69,7 +65,9 @@ public class PublishingDubboMetadataConfigService implements DubboMetadataConfig
public String getServiceRestMetadata() {
String serviceRestMetadataJsonConfig = null;
try {
serviceRestMetadataJsonConfig = objectMapper.writeValueAsString(serviceRestMetadata);
if (!isEmpty(serviceRestMetadata)) {
serviceRestMetadataJsonConfig = objectMapper.writeValueAsString(serviceRestMetadata);
}
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.service.parameter;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.cloud.alibaba.dubbo.http.HttpServerRequest;
import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata;
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;

View File

@ -1,7 +1,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboRestMetadataRegistrationAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataEventHandlingAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceAutoConfiguration
@ -9,7 +9,6 @@ org.springframework.context.ApplicationContextInitializer=\
org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer
org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory=\
org.springframework.cloud.alibaba.dubbo.registry.DefaultRegistrationFactory,\
org.springframework.cloud.alibaba.dubbo.registry.netflix.eureka.EurekaRegistrationFactory,\
org.springframework.cloud.alibaba.dubbo.registry.apache.zookeeper.ZookeeperRegistrationFactory,\
org.springframework.cloud.alibaba.dubbo.registry.hashicorp.consul.ConsulRegistrationFactory

View File

@ -5,5 +5,5 @@ mysql.server.ip=127.0.0.1
mysql.server.port=3306
mysql.db.name=demo
mysql.user.name=xxxxx
mysql.user.password=xxxxx
mysql.user.name=root
mysql.user.password=123456

View File

@ -16,11 +16,6 @@
package org.springframework.cloud.alibaba.cloud.examples;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Random;
import com.alibaba.fescar.core.context.RootContext;
import org.slf4j.Logger;
@ -40,92 +35,97 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Random;
/**
* @author xiaojing
*/
@RestController
public class OrderController {
private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);
private static final String SUCCESS = "SUCCESS";
private static final String FAIL = "FAIL";
private static final String USER_ID = "U100001";
private static final String COMMODITY_CODE = "C00321";
private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);
private static final String SUCCESS = "SUCCESS";
private static final String FAIL = "FAIL";
private static final String USER_ID = "U100001";
private static final String COMMODITY_CODE = "C00321";
private final JdbcTemplate jdbcTemplate;
private final RestTemplate restTemplate;
private Random random;
private final JdbcTemplate jdbcTemplate;
private final RestTemplate restTemplate;
private Random random;
public OrderController(JdbcTemplate jdbcTemplate, RestTemplate restTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.restTemplate = restTemplate;
this.random = new Random();
}
public OrderController(JdbcTemplate jdbcTemplate, RestTemplate restTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.restTemplate = restTemplate;
this.random = new Random();
}
@RequestMapping(value = "/order", method = RequestMethod.POST, produces = "application/json")
public String order(String userId, String commodityCode, int orderCount) {
LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID());
@RequestMapping(value = "/order", method = RequestMethod.POST, produces = "application/json")
public String order(String userId, String commodityCode, int orderCount) {
LOGGER.info("Order Service Begin ... xid: " + RootContext.getXID());
int orderMoney = calculate(commodityCode, orderCount);
int orderMoney = calculate(commodityCode, orderCount);
invokerAccountService(orderMoney);
invokerAccountService(orderMoney);
final Order order = new Order();
order.userId = userId;
order.commodityCode = commodityCode;
order.count = orderCount;
order.money = orderMoney;
final Order order = new Order();
order.userId = userId;
order.commodityCode = commodityCode;
order.count = orderCount;
order.money = orderMoney;
KeyHolder keyHolder = new GeneratedKeyHolder();
KeyHolder keyHolder = new GeneratedKeyHolder();
int result = jdbcTemplate.update(new PreparedStatementCreator() {
int result = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
PreparedStatement pst = con.prepareStatement(
"insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)",
PreparedStatement.RETURN_GENERATED_KEYS);
pst.setObject(1, order.userId);
pst.setObject(2, order.commodityCode);
pst.setObject(3, order.count);
pst.setObject(4, order.money);
return pst;
}
}, keyHolder);
@Override
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
PreparedStatement pst = con.prepareStatement(
"insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)",
PreparedStatement.RETURN_GENERATED_KEYS);
pst.setObject(1, order.userId);
pst.setObject(2, order.commodityCode);
pst.setObject(3, order.count);
pst.setObject(4, order.money);
return pst;
}
}, keyHolder);
order.id = (long) keyHolder.getKey();
order.id = keyHolder.getKey().longValue();
if (random.nextBoolean()) {
throw new RuntimeException("this is a mock Exception");
}
// if (random.nextBoolean()) {
// throw new RuntimeException("this is a mock Exception");
// }
LOGGER.info("Order Service End ... Created " + order);
LOGGER.info("Order Service End ... Created " + order);
if (result == 1) {
return SUCCESS;
}
return FAIL;
}
if (result == 1) {
return SUCCESS;
}
return FAIL;
}
private int calculate(String commodityId, int orderCount) {
return 2 * orderCount;
}
private int calculate(String commodityId, int orderCount) {
return 2 * orderCount;
}
private void invokerAccountService(int orderMoney) {
String url = "http://127.0.0.1:18084/account";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
private void invokerAccountService(int orderMoney) {
String url = "http://127.0.0.1:18084/account";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("userId", USER_ID);
map.add("money", orderMoney + "");
map.add("userId", USER_ID);
map.add("money", orderMoney + "");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
map, headers);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, request,
String.class);
}
ResponseEntity<String> response = restTemplate.postForEntity(url, request,
String.class);
}
}

View File

@ -5,5 +5,5 @@ mysql.server.ip=127.0.0.1
mysql.server.port=3306
mysql.db.name=demo
mysql.user.name=xxxxx
mysql.user.password=xxxxx
mysql.user.name=root
mysql.user.password=123456

View File

@ -5,5 +5,5 @@ mysql.server.ip=127.0.0.1
mysql.server.port=3306
mysql.db.name=demo
mysql.user.name=xxxxx
mysql.user.password=xxxxx
mysql.user.name=root
mysql.user.password=123456

View File

@ -1,4 +1,4 @@
spring.application.name=sca-nacos-config
spring.application.name=nacos-config-example
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.shared-data-ids=base-common.properties,common.properties
spring.cloud.nacos.config.refreshable-dataids=common.properties

View File

@ -19,7 +19,6 @@
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>

View File

@ -3,47 +3,22 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>alibaba.com</groupId>
<artifactId>sms-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>sms-example</name>
<description>Demo project for Spring Boot</description>
<description>Example demonstrating how to use alicloud sms</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<spring-cloud-alibaba-alicloud.version>0.2.2.BUILD-SNAPSHOT</spring-cloud-alibaba-alicloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba-alicloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--Spring Boot -->
@ -59,11 +34,6 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-sms</artifactId>
</dependency>
<dependency>
<groupId>alibaba.com</groupId>
<artifactId>env-extension</artifactId>
<version>0.2.2.BUILD-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
@ -72,6 +42,14 @@
<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>

View File

@ -15,7 +15,6 @@
*/
package org.springframework.cloud.alibaba.cloud.example;
import org.springframework.alicloud.env.extension.ImportExtraConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -23,7 +22,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*
*/
@SpringBootApplication
@ImportExtraConfig(name = "/Users/toava/sms.properties")
public class SmsApplication {
public static void main(String[] args) throws Exception{

View File

@ -1,4 +1,9 @@
spring.application.name=sca-sms-example
server.port=9051
# config management
# config sms
spring.cloud.alicloud.access-key=*****
spring.cloud.alicloud.secret-key=******
spring.cloud.alicloud.sms.report-queue-name=*****
spring.cloud.alicloud.sms.up-queue-name=*****
#config endpoint
management.endpoints.web.exposure.include=*

View File

@ -19,12 +19,11 @@
<module>spring-cloud-dubbo-sample-api</module>
<module>spring-cloud-dubbo-provider-sample</module>
<module>spring-cloud-dubbo-consumer-sample</module>
<module>spring-cloud-dubbo-provider-web-sample</module>
</modules>
<properties>
<dubbo.version>2.6.5</dubbo.version>
<dubbo-spring-boot.version>0.2.1.RELEASE</dubbo-spring-boot.version>
<dubbo-registry-nacos.version>0.0.2</dubbo-registry-nacos.version>
<dubbo.version>2.7.0</dubbo.version>
<spring-cloud-zookeeper.version>2.1.0.RELEASE</spring-cloud-zookeeper.version>
<spring-cloud-consul.version>2.1.0.RELEASE</spring-cloud-consul.version>
<curator.version>4.0.1</curator.version>
@ -44,7 +43,7 @@
<!-- Apache Dubbo dependencies-->
<dependency>
<groupId>com.alibaba</groupId>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>

View File

@ -16,8 +16,7 @@
*/
package org.springframework.cloud.alibaba.dubbo.bootstrap;
import com.alibaba.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
@ -95,7 +94,7 @@ public class DubboSpringCloudConsumerBootstrap {
}
@FeignClient("${provider.application.name}")
@DubboTransported
@DubboTransported()
public interface DubboFeignRestService {
@GetMapping(value = "/param")
@ -209,7 +208,7 @@ public class DubboSpringCloudConsumerBootstrap {
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudConsumerBootstrap.class)
.profiles("nacos")
.properties("spring.profiles.active=nacos")
.run(args);
}
}

View File

@ -1,5 +1,12 @@
dubbo:
registry:
address: spring-cloud://nacos
# The Spring Cloud Dubbo's registry extension
address: spring-cloud://localhost
# The traditional Dubbo's registry
# address: zookeeper://127.0.0.1:2181
server:
port: 7070
port: 0
provider:
application:
name: spring-cloud-alibaba-dubbo-web-provider

View File

@ -24,10 +24,6 @@ ribbon:
nacos:
enabled: false
provider:
application:
name: spring-cloud-alibaba-dubbo-provider
---
spring:
profiles: nacos
@ -51,7 +47,7 @@ eureka:
client:
enabled: true
service-url:
defaultZone: http://127.0.0.1:9090/eureka/
defaultZone: http://127.0.0.1:8761/eureka/
---

View File

@ -17,9 +17,10 @@
<dependencies>
<!-- Resolve the Spring Cloud registration issue -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- Sample API -->
@ -30,6 +31,11 @@
</dependency>
<!-- REST support dependencies -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
@ -60,6 +66,11 @@
<artifactId>resteasy-jaxb-provider</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -29,7 +29,7 @@ public class DubboSpringCloudProviderBootstrap {
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudProviderBootstrap.class)
.profiles("nacos")
.properties("spring.profiles.active=nacos")
.run(args);
}
}

View File

@ -16,18 +16,9 @@
*/
package org.springframework.cloud.alibaba.dubbo.service;
import com.alibaba.dubbo.rpc.RpcContext;
import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
@ -38,9 +29,11 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.HashMap;
import java.util.Map;
import static org.springframework.cloud.alibaba.dubbo.util.LoggerUtils.log;
import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
/**
@ -48,50 +41,46 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@com.alibaba.dubbo.config.annotation.Service(version = "1.0.0", protocol = {"dubbo", "rest"})
@RestController
@Service(version = "1.0.0", protocol = {"dubbo", "rest"})
@Path("/")
public class StandardRestService implements RestService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
@GetMapping(value = "/param")
@Path("/param")
@Path("param")
@GET
public String param(@RequestParam @QueryParam("param") String param) {
public String param(@QueryParam("param") String param) {
log("/param", param);
return param;
}
@Override
@PostMapping("/params")
@Path("/params")
@Path("params")
@POST
public String params(@RequestParam @QueryParam("a") int a, @RequestParam @QueryParam("b") String b) {
public String params(@QueryParam("a") int a, @QueryParam("b") String b) {
log("/params", a + b);
return a + b;
}
@Override
@GetMapping("/headers")
@Path("/headers")
@Path("headers")
@GET
public String headers(@RequestHeader("h") @HeaderParam("h") String header,
@RequestHeader("h2") @HeaderParam("h2") String header2,
@RequestParam("v") @QueryParam("v") Integer param) {
public String headers(@HeaderParam("h") String header,
@HeaderParam("h2") String header2,
@QueryParam("v")
Integer param) {
String result = header + " , " + header2 + " , " + param;
log("/headers", result);
return result;
}
@Override
@GetMapping("/path-variables/{p1}/{p2}")
@Path("/path-variables/{p1}/{p2}")
@Path("path-variables/{p1}/{p2}")
@GET
public String pathVariables(@PathVariable("p1") @PathParam("p1") String path1,
@PathVariable("p2") @PathParam("p2") String path2,
@RequestParam("v") @QueryParam("v") String param) {
public String pathVariables(@PathParam("p1") String path1,
@PathParam("p2") String path2,
@QueryParam("v") String param) {
String result = path1 + " , " + path2 + " , " + param;
log("/path-variables", result);
return result;
@ -101,19 +90,17 @@ public class StandardRestService implements RestService {
// @CookieValue also does not support
@Override
@PostMapping("/form")
@Path("/form")
@Path("form")
@POST
public String form(@RequestParam("f") @FormParam("f") String form) {
public String form(@FormParam("f") String form) {
return String.valueOf(form);
}
@Override
@PostMapping(value = "/request/body/map", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Path("/request/body/map")
@Path("request/body/map")
@POST
@Produces(APPLICATION_JSON_VALUE)
public User requestBodyMap(@RequestBody Map<String, Object> data, @RequestParam("param") @QueryParam("param") String param) {
public User requestBodyMap(Map<String, Object> data, @QueryParam("param") String param) {
User user = new User();
user.setId(((Integer) data.get("id")).longValue());
user.setName((String) data.get("name"));
@ -122,28 +109,15 @@ public class StandardRestService implements RestService {
return user;
}
@PostMapping(value = "/request/body/user", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Path("/request/body/user")
@Path("request/body/user")
@POST
@Override
@Consumes(MediaType.APPLICATION_JSON_UTF8_VALUE)
public Map<String, Object> requestBodyUser(@RequestBody User user) {
@Consumes(MediaType.APPLICATION_JSON)
public Map<String, Object> requestBodyUser(User user) {
Map<String, Object> map = new HashMap<>();
map.put("id", user.getId());
map.put("name", user.getName());
map.put("age", user.getAge());
return map;
}
private void log(String url, Object result) {
String message = String.format("The client[%s] uses '%s' protocol to call %s : %s",
RpcContext.getContext().getRemoteHostName(),
RpcContext.getContext().getUrl() == null ? "N/A" : RpcContext.getContext().getUrl().getProtocol(),
url,
result
);
if (logger.isInfoEnabled()) {
logger.info(message);
}
}
}

View File

@ -4,17 +4,16 @@ dubbo:
protocols:
dubbo:
name: dubbo
port: 12345
port: -1
rest:
name: rest
port: 8081
port: 9090
server: netty
registry:
address: spring-cloud://nacos
# 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
server:
port: 8080
enabled: true

View File

@ -4,6 +4,7 @@ spring:
main:
allow-bean-definition-overriding: true
# default disable all
cloud:
nacos:
@ -40,7 +41,7 @@ eureka:
client:
enabled: true
service-url:
defaultZone: http://127.0.0.1:9090/eureka/
defaultZone: http://127.0.0.1:8761/eureka/
---

View File

@ -0,0 +1,33 @@
<?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>
<artifactId>spring-cloud-alibaba-dubbo-examples</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.2.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dubbo-provider-web-sample</artifactId>
<name>Spring Cloud Dubbo Provider Web Sample</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Sample API -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.bootstrap;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Provider Bootstrap
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
public class DubboSpringCloudWebProviderBootstrap {
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudWebProviderBootstrap.class)
.properties("spring.profiles.active=nacos")
.run(args);
}
}

View File

@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.service;
import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import static org.springframework.cloud.alibaba.dubbo.util.LoggerUtils.log;
/**
* Spring MVC {@link RestService}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Service(version = "1.0.0")
@RestController
public class SpringRestService implements RestService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
@GetMapping(value = "/param")
public String param(@RequestParam String param) {
log("/param", param);
return param;
}
@Override
@PostMapping("/params")
public String params(@RequestParam int a, @RequestParam String b) {
log("/params", a + b);
return a + b;
}
@Override
@GetMapping("/headers")
public String headers(@RequestHeader("h") String header,
@RequestHeader("h2") String header2,
@RequestParam("v") Integer param) {
String result = header + " , " + header2 + " , " + param;
log("/headers", result);
return result;
}
@Override
@GetMapping("/path-variables/{p1}/{p2}")
public String pathVariables(@PathVariable("p1") String path1,
@PathVariable("p2") String path2,
@RequestParam("v") String param) {
String result = path1 + " , " + path2 + " , " + param;
log("/path-variables", result);
return result;
}
@Override
@PostMapping("/form")
public String form(@RequestParam("f") String form) {
return String.valueOf(form);
}
@Override
@PostMapping(value = "/request/body/map", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public User requestBodyMap(@RequestBody Map<String, Object> data, @RequestParam("param") String param) {
User user = new User();
user.setId(((Integer) data.get("id")).longValue());
user.setName((String) data.get("name"));
user.setAge((Integer) data.get("age"));
log("/request/body/map", param);
return user;
}
@PostMapping(value = "/request/body/user", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Override
public Map<String, Object> requestBodyUser(@RequestBody User user) {
Map<String, Object> map = new HashMap<>();
map.put("id", user.getId());
map.put("name", user.getName());
map.put("age", user.getAge());
return map;
}
}

View File

@ -0,0 +1,19 @@
dubbo:
scan:
base-packages: org.springframework.cloud.alibaba.dubbo.service
protocols:
dubbo:
name: dubbo
port: -1
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
server:
port: 8080

View File

@ -0,0 +1,64 @@
spring:
application:
name: spring-cloud-alibaba-dubbo-web-provider
main:
allow-bean-definition-overriding: true
# default disable all
cloud:
nacos:
discovery:
enabled: false
register-enabled: false
zookeeper:
enabled: false
consul:
enabled: false
eureka:
client:
enabled: false
---
spring:
profiles: nacos
cloud:
nacos:
discovery:
enabled: true
register-enabled: true
server-addr: 127.0.0.1:8848
---
spring:
profiles: eureka
eureka:
client:
enabled: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
---
spring:
profiles: zookeeper
cloud:
zookeeper:
enabled: true
connect-string: 127.0.0.1:2181
---
spring:
profiles: consul
cloud:
consul:
enabled: true
host: 127.0.0.1
port: 8500

View File

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.util;
import org.apache.dubbo.rpc.RpcContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Logger Utilities
*/
public abstract class LoggerUtils {
private static final Logger logger = LoggerFactory.getLogger(LoggerUtils.class);
public static void log(String url, Object result) {
String message = String.format("The client[%s] uses '%s' protocol to call %s : %s",
RpcContext.getContext().getRemoteHostName(),
RpcContext.getContext().getUrl() == null ? "N/A" : RpcContext.getContext().getUrl().getProtocol(),
url,
result
);
if (logger.isInfoEnabled()) {
logger.info(message);
}
}
}

View File

@ -31,18 +31,17 @@
package org.springframework.cloud.alibaba.fescar.rest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author xiaojing
*/

View File

@ -17,6 +17,7 @@
package org.springframework.cloud.alibaba.nacos;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher;
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshProperties;
@ -28,6 +29,7 @@ import org.springframework.context.annotation.Configuration;
* @author juven.xuxb
*/
@Configuration
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigAutoConfiguration {
@Bean

View File

@ -26,6 +26,7 @@ import org.springframework.context.annotation.Configuration;
* @author xiaojing
*/
@Configuration
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigBootstrapConfiguration {
@Bean
@ -35,7 +36,6 @@ public class NacosConfigBootstrapConfiguration {
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public NacosPropertySourceLocator nacosPropertySourceLocator(
NacosConfigProperties nacosConfigProperties) {
return new NacosPropertySourceLocator(nacosConfigProperties);

View File

@ -55,11 +55,6 @@ public class NacosConfigProperties {
private static final Logger log = LoggerFactory
.getLogger(NacosConfigProperties.class);
/**
* whether to enable nacos config.
*/
private boolean enabled = true;
/**
* nacos config server address
*/
@ -122,8 +117,6 @@ public class NacosConfigProperties {
private String name;
private String[] activeProfiles;
/**
* the dataids for configurable multiple shared configurations , multiple separated by
* commas .
@ -142,24 +135,8 @@ public class NacosConfigProperties {
private ConfigService configService;
@Autowired
private Environment environment;
@PostConstruct
public void init() {
this.activeProfiles = environment.getActiveProfiles();
}
// todo sts support
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getServerAddr() {
return serverAddr;
}
@ -260,10 +237,6 @@ public class NacosConfigProperties {
return name;
}
public String[] getActiveProfiles() {
return activeProfiles;
}
public String getSharedDataids() {
return sharedDataids;
}
@ -292,10 +265,6 @@ public class NacosConfigProperties {
this.name = name;
}
public void setActiveProfiles(String[] activeProfiles) {
this.activeProfiles = activeProfiles;
}
public static class Config {
/**
* the data id of extended configuration
@ -337,17 +306,15 @@ public class NacosConfigProperties {
@Override
public String toString() {
return "NacosConfigProperties{" + "enabled=" + enabled + ", serverAddr='"
+ serverAddr + '\'' + ", encode='" + encode + '\'' + ", group='" + group
+ '\'' + ", prefix='" + prefix + '\'' + ", fileExtension='"
+ fileExtension + '\'' + ", timeout=" + timeout + ", endpoint='"
+ endpoint + '\'' + ", namespace='" + namespace + '\'' + ", accessKey='"
+ accessKey + '\'' + ", secretKey='" + secretKey + '\''
+ ", contextPath='" + contextPath + '\'' + ", clusterName='" + clusterName
+ '\'' + ", name='" + name + '\'' + ", activeProfiles="
+ Arrays.toString(activeProfiles) + ", sharedDataids='" + sharedDataids
+ '\'' + ", refreshableDataids='" + refreshableDataids + '\''
+ ", extConfig=" + extConfig + '}';
return "NacosConfigProperties{" + "serverAddr='" + serverAddr + '\''
+ ", encode='" + encode + '\'' + ", group='" + group + '\'' + ", prefix='"
+ prefix + '\'' + ", fileExtension='" + fileExtension + '\''
+ ", timeout=" + timeout + ", endpoint='" + endpoint + '\''
+ ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\''
+ ", secretKey='" + secretKey + '\'' + ", contextPath='" + contextPath
+ '\'' + ", clusterName='" + clusterName + '\'' + ", name='" + name + '\''
+ ", sharedDataids='" + sharedDataids + '\'' + ", refreshableDataids='"
+ refreshableDataids + '\'' + ", extConfig=" + extConfig + '}';
}
public ConfigService configServiceInstance() {

View File

@ -71,7 +71,6 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
timeout);
String name = nacosConfigProperties.getName();
String nacosGroup = nacosConfigProperties.getGroup();
String dataIdPrefix = nacosConfigProperties.getPrefix();
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = name;
@ -81,17 +80,12 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
dataIdPrefix = env.getProperty("spring.application.name");
}
List<String> profiles = Arrays.asList(env.getActiveProfiles());
nacosConfigProperties.setActiveProfiles(profiles.toArray(new String[0]));
String fileExtension = nacosConfigProperties.getFileExtension();
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME);
loadSharedConfiguration(composite);
loadExtConfiguration(composite);
loadApplicationConfiguration(composite, nacosGroup, dataIdPrefix, fileExtension);
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
return composite;
}
@ -152,11 +146,15 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
}
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, String nacosGroup,
String dataIdPrefix, String fileExtension) {
CompositePropertySource compositePropertySource, String dataIdPrefix,
NacosConfigProperties properties, Environment environment) {
String fileExtension = properties.getFileExtension();
String nacosGroup = properties.getGroup();
loadNacosDataIfPresent(compositePropertySource,
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
for (String profile : nacosConfigProperties.getActiveProfiles()) {
for (String profile : environment.getActiveProfiles()) {
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
fileExtension, true);

View File

@ -21,6 +21,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.condition.Conditi
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
@ -31,6 +32,7 @@ import org.springframework.context.annotation.Bean;
*/
@ConditionalOnWebApplication
@ConditionalOnClass(value = Endpoint.class)
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigEndpointAutoConfiguration {
@Autowired

View File

@ -32,6 +32,12 @@
"name": "spring.cloud.nacos.config.ext-config",
"type": "java.util.List",
"description": "a set of extended configurations ."
},
{
"name": "spring.cloud.nacos.config.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "enable nacos config or not."
}
]
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (C) 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import org.junit.Test;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpoint;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author pbting
* @date 2019-01-17 2:25 PM
*/
public class EndpointTests extends NacosPowerMockitBaseTests {
@Test
public void nacosConfigEndpoint() {
NacosConfigEndpoint nacosConfigEndpoint = super.context
.getBean(NacosConfigEndpoint.class);
assertThat(nacosConfigEndpoint != null).isEqualTo(true);
}
@Test
public void endpointInvoke() {
NacosConfigEndpoint nacosConfigEndpoint = this.context
.getBean(NacosConfigEndpoint.class);
assertThat(nacosConfigEndpoint.invoke() != null).isEqualTo(true);
}
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import org.junit.Test;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshProperties;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.PropertySource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author xiaojing
* @author pbting
*/
public class NacosConfigAutoConfigurationTests extends NacosPowerMockitBaseTests {
@Test
public void testNacosConfigProperties() {
NacosConfigProperties nacosConfigProperties = context.getParent()
.getBean(NacosConfigProperties.class);
assertThat(nacosConfigProperties.getFileExtension()).isEqualTo("properties");
assertThat(nacosConfigProperties.getPrefix() == null).isEqualTo(true);
assertThat(nacosConfigProperties.getNamespace() == null).isEqualTo(true);
assertThat(nacosConfigProperties.getName()).isEqualTo("sca-nacos-config");
assertThat(nacosConfigProperties.getServerAddr()).isEqualTo("127.0.0.1:8848");
assertThat(nacosConfigProperties.getEncode()).isEqualTo("utf-8");
assertThat(nacosConfigProperties.getActiveProfiles())
.isEqualTo(new String[] { "develop" });
assertThat(nacosConfigProperties.getSharedDataids())
.isEqualTo("base-common.properties,common.properties");
assertThat(nacosConfigProperties.getRefreshableDataids())
.isEqualTo("common.properties");
assertThat(nacosConfigProperties.getExtConfig().size()).isEqualTo(3);
assertThat(nacosConfigProperties.getExtConfig().get(0).getDataId())
.isEqualTo("ext00.yaml");
assertThat(nacosConfigProperties.getExtConfig().get(1).getGroup())
.isEqualTo("EXT01_GROUP");
assertThat(nacosConfigProperties.getExtConfig().get(1).isRefresh())
.isEqualTo(true);
}
@Test
public void nacosPropertySourceLocator() {
NacosPropertySourceLocator nacosPropertySourceLocator = this.context
.getBean(NacosPropertySourceLocator.class);
PropertySource propertySource = nacosPropertySourceLocator
.locate(this.context.getEnvironment());
assertThat(propertySource instanceof CompositePropertySource).isEqualTo(true);
}
@Test
public void testNacosRefreshProperties() {
NacosRefreshProperties nacosRefreshProperties = this.context
.getBean(NacosRefreshProperties.class);
assertThat(nacosRefreshProperties.isEnabled()).isEqualTo(true);
}
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (C) 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import org.junit.Test;
import org.springframework.boot.actuate.health.Health;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigHealthIndicator;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author pbting
* @date 2019-01-17 2:58 PM
*/
public class NacosConfigHealthIndicatorTests extends NacosPowerMockitBaseTests {
@Test
public void nacosConfigHealthIndicatorInstance() {
NacosConfigHealthIndicator nacosConfigHealthIndicator = this.context
.getBean(NacosConfigHealthIndicator.class);
assertThat(nacosConfigHealthIndicator != null).isEqualTo(true);
}
@Test
public void testHealthCheck() {
NacosConfigHealthIndicator nacosConfigHealthIndicator = this.context
.getBean(NacosConfigHealthIndicator.class);
Health.Builder builder = Health.up();
Method method = ReflectionUtils.findMethod(NacosConfigHealthIndicator.class,
"doHealthCheck", Health.Builder.class);
ReflectionUtils.makeAccessible(method);
assertThat(method != null).isEqualTo(true);
try {
method.invoke(nacosConfigHealthIndicator, builder);
assertThat(builder != null).isEqualTo(true);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,153 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import static org.junit.Assert.assertNotNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.alibaba.nacos.client.config.NacosConfigService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.MethodProxy;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpointAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author xiaojing
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosConfigurationExtConfigTests.TestConfig.class, properties = {
"spring.application.name=myTestService1", "spring.profiles.active=dev,test",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.encode=utf-8",
"spring.cloud.nacos.config.timeout=1000",
"spring.cloud.nacos.config.file-extension=properties",
"spring.cloud.nacos.config.ext-config[0].data-id=ext-config-common01.properties",
"spring.cloud.nacos.config.ext-config[1].data-id=ext-config-common02.properties",
"spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP",
"spring.cloud.nacos.config.shared-dataids=common1.properties,common2.properties",
"spring.cloud.nacos.config.accessKey=test-accessKey",
"spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE)
public class NacosConfigurationExtConfigTests {
static {
try {
// when(any(ConfigService.class).getConfig(eq("test-name.properties"),
// eq("test-group"), any())).thenReturn("user.name=hello");
Method method = PowerMockito.method(NacosConfigService.class, "getConfig",
String.class, String.class, long.class);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("test-name.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "user.name=hello\nuser.age=12";
}
if ("test-name-dev.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "user.name=dev";
}
if ("ext-config-common01.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "test-ext-config1=config1\ntest-ext-config2=config1";
}
if ("ext-config-common02.properties".equals(args[0])
&& "GLOBAL_GROUP".equals(args[1])) {
return "test-ext-config2=config2";
}
if ("common1.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "test-common1=common1\ntest-common2=common1";
}
if ("common2.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "test-common2=common2";
}
return "";
}
});
}
catch (Exception ignore) {
ignore.printStackTrace();
}
}
@Autowired
private Environment environment;
@Autowired
private NacosPropertySourceLocator locator;
@Autowired
private NacosConfigProperties properties;
@Test
public void contextLoads() throws Exception {
assertNotNull("NacosPropertySourceLocator was not created", locator);
assertNotNull("NacosConfigProperties was not created", properties);
Assert.assertEquals(environment.getProperty("test-ext-config1"), "config1");
Assert.assertEquals(environment.getProperty("test-ext-config2"), "config2");
Assert.assertEquals(environment.getProperty("test-common1"), "common1");
Assert.assertEquals(environment.getProperty("test-common2"), "common2");
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class,
NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class })
public static class TestConfig {
}
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import com.alibaba.nacos.client.config.NacosConfigService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.MethodProxy;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpoint;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpointAutoConfiguration;
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author xiaojing
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosConfigurationTests.TestConfig.class, properties = {
"spring.application.name=myTestService1", "spring.profiles.active=dev,test",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.endpoint=test-endpoint",
"spring.cloud.nacos.config.namespace=test-namespace",
"spring.cloud.nacos.config.encode=utf-8",
"spring.cloud.nacos.config.timeout=1000",
"spring.cloud.nacos.config.group=test-group",
"spring.cloud.nacos.config.name=test-name",
"spring.cloud.nacos.config.cluster-name=test-cluster",
"spring.cloud.nacos.config.file-extension=properties",
"spring.cloud.nacos.config.contextPath=test-contextpath",
"spring.cloud.nacos.config.ext-config[0].data-id=ext-config-common01.properties",
"spring.cloud.nacos.config.ext-config[1].data-id=ext-config-common02.properties",
"spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP",
"spring.cloud.nacos.config.shared-dataids=common1.properties,common2.properties",
"spring.cloud.nacos.config.accessKey=test-accessKey",
"spring.cloud.nacos.config.secretKey=test-secretKey" }, webEnvironment = NONE)
public class NacosConfigurationTests {
static {
try {
// when(any(ConfigService.class).getConfig(eq("test-name.properties"),
// eq("test-group"), any())).thenReturn("user.name=hello");
Method method = PowerMockito.method(NacosConfigService.class, "getConfig",
String.class, String.class, long.class);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("test-name.properties".equals(args[0])
&& "test-group".equals(args[1])) {
return "user.name=hello\nuser.age=12";
}
if ("test-name-dev.properties".equals(args[0])
&& "test-group".equals(args[1])) {
return "user.name=dev";
}
if ("ext-config-common01.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "test-ext-config1=config1\ntest-ext-config2=config1";
}
if ("ext-config-common02.properties".equals(args[0])
&& "GLOBAL_GROUP".equals(args[1])) {
return "test-ext-config2=config2";
}
if ("common1.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "test-common1=common1\ntest-common2=common1";
}
if ("common2.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "test-common2=common2";
}
return "";
}
});
}
catch (Exception ignore) {
ignore.printStackTrace();
}
}
@Autowired
private Environment environment;
@Autowired
private NacosPropertySourceLocator locator;
@Autowired
private NacosConfigProperties properties;
@Autowired
private NacosRefreshHistory refreshHistory;
@Test
public void contextLoads() throws Exception {
assertNotNull("NacosPropertySourceLocator was not created", locator);
assertNotNull("NacosConfigProperties was not created", properties);
checkoutNacosConfigServerAddr();
checkoutNacosConfigEndpoint();
checkoutNacosConfigNamespace();
checkoutNacosConfigClusterName();
checkoutNacosConfigAccessKey();
checkoutNacosConfigSecrectKey();
checkoutNacosConfigName();
checkoutNacosConfigGroup();
checkoutNacosConfigContextPath();
checkoutNacosConfigFileExtension();
checkoutNacosConfigTimeout();
checkoutNacosConfigEncode();
checkoutEndpoint();
checkoutDataLoad();
}
private void checkoutNacosConfigServerAddr() {
assertEquals("NacosConfigProperties server address is wrong", "127.0.0.1:8848",
properties.getServerAddr());
}
private void checkoutNacosConfigEndpoint() {
assertEquals("NacosConfigProperties endpoint is wrong", "test-endpoint",
properties.getEndpoint());
}
private void checkoutNacosConfigNamespace() {
assertEquals("NacosConfigProperties namespace is wrong", "test-namespace",
properties.getNamespace());
}
private void checkoutNacosConfigClusterName() {
assertEquals("NacosConfigProperties' cluster is wrong", "test-cluster",
properties.getClusterName());
}
private void checkoutNacosConfigAccessKey() {
assertEquals("NacosConfigProperties' is access key is wrong", "test-accessKey",
properties.getAccessKey());
}
private void checkoutNacosConfigSecrectKey() {
assertEquals("NacosConfigProperties' is secret key is wrong", "test-secretKey",
properties.getSecretKey());
}
private void checkoutNacosConfigContextPath() {
assertEquals("NacosConfigProperties' context path is wrong", "test-contextpath",
properties.getContextPath());
}
private void checkoutNacosConfigName() {
assertEquals("NacosConfigProperties' name is wrong", "test-name",
properties.getName());
}
private void checkoutNacosConfigGroup() {
assertEquals("NacosConfigProperties' group is wrong", "test-group",
properties.getGroup());
}
private void checkoutNacosConfigFileExtension() {
assertEquals("NacosConfigProperties' file extension is wrong", "properties",
properties.getFileExtension());
}
private void checkoutNacosConfigTimeout() {
assertEquals("NacosConfigProperties' timeout is wrong", 1000,
properties.getTimeout());
}
private void checkoutNacosConfigEncode() {
assertEquals("NacosConfigProperties' encode is wrong", "utf-8",
properties.getEncode());
}
private void checkoutDataLoad() {
Assert.assertEquals(environment.getProperty("user.name"), "dev");
Assert.assertEquals(environment.getProperty("user.age"), "12");
}
private void checkoutEndpoint() throws Exception {
NacosConfigEndpoint nacosConfigEndpoint = new NacosConfigEndpoint(properties,
refreshHistory);
Map<String, Object> map = nacosConfigEndpoint.invoke();
assertEquals(map.get("NacosConfigProperties"), properties);
assertEquals(map.get("RefreshHistory"), refreshHistory.getRecords());
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class,
NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class })
public static class TestConfig {
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.alibaba.nacos.client.config.NacosConfigService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.MethodProxy;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpointAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author xiaojing
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosFileExtensionTest.TestConfig.class, properties = {
"spring.application.name=test-name",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.file-extension=yaml" }, webEnvironment = NONE)
public class NacosFileExtensionTest {
static {
try {
Method method = PowerMockito.method(NacosConfigService.class, "getConfig",
String.class, String.class, long.class);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("test-name.yaml".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "user:\n name: hello\n age: 12";
}
return "";
}
});
}
catch (Exception ignore) {
ignore.printStackTrace();
}
}
@Autowired
private Environment environment;
@Test
public void contextLoads() throws Exception {
Assert.assertEquals(environment.getProperty("user.name"), "hello");
Assert.assertEquals(environment.getProperty("user.age"), "12");
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class,
NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class })
public static class TestConfig {
}
}

View File

@ -1,177 +0,0 @@
/*
* Copyright (C) 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import com.alibaba.nacos.api.config.ConfigService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.MethodProxy;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceBuilder;
import org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpointAutoConfiguration;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ReflectionUtils;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* @author pbting
* @date 2019-01-17 8:54 PM
*/
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PowerMockIgnore({ "javax.management.*", "javax.net.ssl.*" })
@PrepareForTest({ NacosPropertySourceBuilder.class })
@SpringBootTest(classes = { NacosConfigBootstrapConfiguration.class,
NacosConfigEndpointAutoConfiguration.class, NacosConfigAutoConfiguration.class,
NacosPowerMockitBaseTests.TestConfiguration.class }, properties = {
"spring.application.name=sca-nacos-config",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.name=sca-nacos-config",
// "spring.cloud.nacos.config.refresh.enabled=false",
"spring.cloud.nacos.config.encode=utf-8",
"spring.cloud.nacos.config.shared-data-ids=base-common.properties,common.properties",
"spring.cloud.nacos.config.refreshable-dataids=common.properties",
"spring.cloud.nacos.config.ext-config[0].data-id=ext00.yaml",
"spring.cloud.nacos.config.ext-config[1].data-id=ext01.yml",
"spring.cloud.nacos.config.ext-config[1].group=EXT01_GROUP",
"spring.cloud.nacos.config.ext-config[1].refresh=true",
"spring.cloud.nacos.config.ext-config[2].data-id=ext02.yaml",
"spring.profiles.active=develop", "server.port=19090" })
public class NacosPowerMockitBaseTests {
private final static List<String> DATAIDS = Arrays.asList("common.properties",
"base-common.properties", "ext00.yaml", "ext01.yml", "ext02.yaml",
"sca-nacos-config.properties", "sca-nacos-config-develop.properties");
private final static HashMap<String, Properties> VALUES = new HashMap<>();
@Autowired
protected ApplicationContext context;
static {
initDataIds();
try {
final Constructor constructor = ReflectionUtils.accessibleConstructor(
NacosPropertySource.class, String.class, String.class, Map.class,
Date.class, boolean.class);
Method method = PowerMockito.method(NacosPropertySourceBuilder.class, "build",
String.class, String.class, String.class, boolean.class);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Properties properties = VALUES.get(args[0].toString());
if (properties == null) {
properties = new Properties();
properties.put("user.name", args[0].toString());
}
Object instance = constructor.newInstance(args[1].toString(),
args[0].toString(), properties, new Date(), args[3]);
return instance;
}
});
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private static void initDataIds() {
DATAIDS.forEach(dataId -> {
String realpath = "/" + dataId;
ClassPathResource classPathResource = new ClassPathResource(realpath);
if (realpath.endsWith("properties")) {
Properties properties = new Properties();
try {
properties.load(classPathResource.getInputStream());
VALUES.put(dataId, properties);
}
catch (IOException e) {
e.printStackTrace();
}
}
if (realpath.endsWith("yaml") || realpath.endsWith("yml")) {
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
yamlFactory.setResources(classPathResource);
try {
VALUES.put(dataId, yamlFactory.getObject());
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
public NacosPropertySourceBuilder nacosPropertySourceBuilderInstance() {
NacosConfigProperties nacosConfigProperties = this.context
.getBean(NacosConfigProperties.class);
ConfigService configService = nacosConfigProperties.configServiceInstance();
long timeout = nacosConfigProperties.getTimeout();
NacosPropertySourceBuilder nacosPropertySourceBuilder = new NacosPropertySourceBuilder(
configService, timeout);
return nacosPropertySourceBuilder;
}
@Configuration
@AutoConfigureBefore(NacosConfigAutoConfiguration.class)
static class TestConfiguration {
@Autowired
ConfigurableApplicationContext context;
@Bean
ContextRefresher contextRefresher() {
RefreshScope refreshScope = new RefreshScope();
refreshScope.setApplicationContext(context);
return new ContextRefresher(context, refreshScope);
}
}
@Test
public void testAppContext() {
System.err.println(this.context);
}
}

View File

@ -1,190 +0,0 @@
/*
* Copyright (C) 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import org.junit.Test;
import org.powermock.api.support.MethodProxy;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceBuilder;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author pbting
* @date 2019-01-17 11:49 AM
*/
public class NacosPropertySourceBuilderTests extends NacosPowerMockitBaseTests {
@Test
public void nacosPropertySourceBuilder() {
assertThat(nacosPropertySourceBuilderInstance() != null).isEqualTo(true);
}
@Test
public void getConfigByProperties() {
try {
final HashMap<String, String> value = new HashMap<>();
value.put("dev.mode", "local-mock");
final Constructor constructor = ReflectionUtils.accessibleConstructor(
NacosPropertySource.class, String.class, String.class, Map.class,
Date.class, boolean.class);
NacosPropertySourceBuilder nacosPropertySourceBuilder = nacosPropertySourceBuilderInstance();
Method method = ReflectionUtils.findMethod(NacosPropertySourceBuilder.class,
"build", String.class, String.class, String.class, boolean.class);
ReflectionUtils.makeAccessible(method);
assertThat(method != null).isEqualTo(true);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object instance = constructor.newInstance(args[1].toString(),
args[0].toString(), value, new Date(), args[3]);
return instance;
}
});
Object result = method.invoke(nacosPropertySourceBuilder,
"mock-nacos-config.properties", "DEFAULT_GROUP", "properties", true);
assertThat(result != null).isEqualTo(true);
assertThat(result instanceof NacosPropertySource).isEqualTo(true);
NacosPropertySource nacosPropertySource = (NacosPropertySource) result;
assertThat(nacosPropertySource.getProperty("dev.mode"))
.isEqualTo("local-mock");
}
catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void getConfigByYaml() {
try {
//
final HashMap<String, String> value = new HashMap<>();
value.put("mock-ext-config", "mock-ext-config-value");
final Constructor constructor = ReflectionUtils.accessibleConstructor(
NacosPropertySource.class, String.class, String.class, Map.class,
Date.class, boolean.class);
Method method = ReflectionUtils.findMethod(NacosPropertySourceBuilder.class,
"build", String.class, String.class, String.class, boolean.class);
ReflectionUtils.makeAccessible(method);
assertThat(method != null).isEqualTo(true);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object instance = constructor.newInstance(args[1].toString(),
args[0].toString(), value, new Date(), args[3]);
return instance;
}
});
NacosPropertySourceBuilder nacosPropertySourceBuilder = nacosPropertySourceBuilderInstance();
Object result = method.invoke(nacosPropertySourceBuilder, "ext-config.yaml",
"DEFAULT_GROUP", "yaml", true);
assertThat(result != null).isEqualTo(true);
assertThat(result instanceof NacosPropertySource).isEqualTo(true);
NacosPropertySource nacosPropertySource = (NacosPropertySource) result;
assertThat(nacosPropertySource.getProperty("mock-ext-config"))
.isEqualTo("mock-ext-config-value");
}
catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void getConfigByYml() {
try {
//
final HashMap<String, String> value = new HashMap<>();
value.put("mock-ext-config-yml", "mock-ext-config-yml-value");
final Constructor constructor = ReflectionUtils.accessibleConstructor(
NacosPropertySource.class, String.class, String.class, Map.class,
Date.class, boolean.class);
Method method = ReflectionUtils.findMethod(NacosPropertySourceBuilder.class,
"build", String.class, String.class, String.class, boolean.class);
ReflectionUtils.makeAccessible(method);
assertThat(method != null).isEqualTo(true);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object instance = constructor.newInstance(args[1].toString(),
args[0].toString(), value, new Date(), args[3]);
return instance;
}
});
NacosPropertySourceBuilder nacosPropertySourceBuilder = nacosPropertySourceBuilderInstance();
Object result = method.invoke(nacosPropertySourceBuilder, "ext-config.yml",
"DEFAULT_GROUP", "yml", true);
assertThat(result != null).isEqualTo(true);
assertThat(result instanceof NacosPropertySource).isEqualTo(true);
NacosPropertySource nacosPropertySource = (NacosPropertySource) result;
assertThat(nacosPropertySource.getProperty("mock-ext-config-yml"))
.isEqualTo("mock-ext-config-yml-value");
}
catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void getEmpty() {
NacosPropertySourceBuilder nacosPropertySourceBuilder = nacosPropertySourceBuilderInstance();
Method method = ReflectionUtils.findMethod(NacosPropertySourceBuilder.class,
"build", String.class, String.class, String.class, boolean.class);
ReflectionUtils.makeAccessible(method);
assertThat(method != null).isEqualTo(true);
try {
Object result = method.invoke(nacosPropertySourceBuilder, "nacos-empty.yml",
"DEFAULT_GROUP", "yml", true);
assertThat(result != null).isEqualTo(true);
assertThat(result instanceof NacosPropertySource).isEqualTo(true);
NacosPropertySource nacosPropertySource = (NacosPropertySource) result;
assertThat(nacosPropertySource.getProperty("address")).isEqualTo(null);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (C) 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author pbting
* @date 2019-01-17 11:46 AM
*/
public class NacosSharedAndExtConfigTests extends NacosPowerMockitBaseTests {
private final static Logger log = LoggerFactory
.getLogger(NacosSharedAndExtConfigTests.class);
@Test
public void testSharedConfigPriority() {
String userName = this.context.getEnvironment().getProperty("user.address");
assertThat(userName).isEqualTo("zhejiang-ningbo");
}
@Test
public void testSharedConfigRefresh() {
while (true) {
// ContextRefresher contextRefresher = this.context
// .getBean(ContextRefresher.class);
// contextRefresher.refresh();
String userName = this.context.getEnvironment().getProperty("user.address");
try {
assertThat(userName).isEqualTo("zhejiang-ningbo");
TimeUnit.SECONDS.sleep(1);
log.info("user name is {}", userName);
}
catch (InterruptedException e) {
e.printStackTrace();
}
// 真实测试时将这里 注释掉
break;
}
}
@Test
public void testExtConfigPriority() {
String extKey = this.context.getEnvironment().getProperty("ext.key");
assertThat(extKey).isEqualTo("ext.value02");
}
@Test
public void testExtOtherGroup() {
String userExt = this.context.getEnvironment().getProperty("user.ext");
assertThat(userExt).isEqualTo("EXT01_GROUP-value");
}
@Test
public void testExtRefresh() {
while (true) {
// ContextRefresher contextRefresher = this.context
// .getBean(ContextRefresher.class);
// contextRefresher.refresh();
String userExt = this.context.getEnvironment().getProperty("user.ext");
try {
assertThat(userExt).isEqualTo("EXT01_GROUP-value");
TimeUnit.SECONDS.sleep(1);
log.info("user name is {}", userExt);
}
catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
}

View File

@ -0,0 +1,141 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.nacos.endpoint;
import static org.junit.Assert.assertEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.nacos.client.config.NacosConfigService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.MethodProxy;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.alibaba.nacos.NacosConfigAutoConfiguration;
import org.springframework.cloud.alibaba.nacos.NacosConfigBootstrapConfiguration;
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author xiaojing
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosConfigEndpointTests.TestConfig.class, properties = {
"spring.application.name=test-name",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.file-extension=properties" }, webEnvironment = NONE)
public class NacosConfigEndpointTests {
static {
try {
Method method = PowerMockito.method(NacosConfigService.class, "getConfig",
String.class, String.class, long.class);
MethodProxy.proxy(method, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("test-name.properties".equals(args[0])
&& "DEFAULT_GROUP".equals(args[1])) {
return "user.name=hello\nuser.age=12";
}
return "";
}
});
}
catch (Exception ignore) {
ignore.printStackTrace();
}
}
@Autowired
private NacosConfigProperties properties;
@Autowired
private NacosRefreshHistory refreshHistory;
@Test
public void contextLoads() throws Exception {
checkoutEndpoint();
checkoutAcmHealthIndicator();
}
private void checkoutAcmHealthIndicator() {
try {
Builder builder = new Builder();
NacosConfigHealthIndicator healthIndicator = new NacosConfigHealthIndicator(
properties, properties.configServiceInstance());
healthIndicator.doHealthCheck(builder);
Builder builder1 = new Builder();
List<String> dataIds = new ArrayList<>();
dataIds.add("test-name.properties");
builder1.up().withDetail("dataIds", dataIds);
Assert.assertTrue(builder.build().equals(builder1.build()));
}
catch (Exception ignoreE) {
}
}
private void checkoutEndpoint() throws Exception {
NacosConfigEndpoint endpoint = new NacosConfigEndpoint(properties,
refreshHistory);
Map<String, Object> map = endpoint.invoke();
assertEquals(map.get("NacosConfigProperties"), properties);
assertEquals(map.get("RefreshHistory"), refreshHistory.getRecords());
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ NacosConfigEndpointAutoConfiguration.class,
NacosConfigAutoConfiguration.class, NacosConfigBootstrapConfiguration.class })
public static class TestConfig {
}
}

View File

@ -1,2 +0,0 @@
user.name=base-common-value
user.address=zhejiang-hangzhou

View File

@ -1,2 +0,0 @@
user.name=common-value
user.address=zhejiang-ningbo

View File

@ -1,4 +0,0 @@
user:
name: ext-00-value
ext:
key: ext.value00

View File

@ -1,5 +0,0 @@
user:
name: ext-01-value
ext: EXT01_GROUP-value
ext:
key: ext.value01

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