From ee2c696bdf1a3c5b36d6a69b7482d8d1053c71fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=97=E5=B0=91?= <314226532@qq.com>
Date: Wed, 9 Jan 2019 18:38:08 +0800
Subject: [PATCH] ans starter suport eureka/consule registry and add sms module
---
spring-cloud-alibaba-dependencies/pom.xml | 29 ++
.../sms-example/pom.xml | 74 +++
.../alibaba/cloud/example/SmsApplication.java | 31 ++
.../alibaba/cloud/example/SmsController.java | 128 ++++++
.../example/SmsReportMessageListener.java | 28 ++
.../cloud/example/SmsUpMessageListener.java | 19 +
.../src/main/resources/application.properties | 9 +
.../NacosConfigBootstrapConfiguration.java | 11 +-
.../alibaba/nacos/NacosConfigProperties.java | 13 +-
.../client/NacosPropertySourceBuilder.java | 20 +-
.../client/NacosPropertySourceLocator.java | 32 +-
.../nacos/refresh/NacosContextRefresher.java | 24 +-
.../alicloud/ans/AnsAutoConfiguration.java | 11 +-
.../alicloud/ans/AnsDiscoveryClient.java | 10 +-
.../AnsDiscoveryClientAutoConfiguration.java | 3 +
.../alicloud/ans/endpoint/AnsEndpoint.java | 23 +-
.../alicloud/ans/migrate/MigrateEndpoint.java | 31 ++
.../MigrateEndpointAutoConfiguration.java | 18 +
.../ans/migrate/MigrateOnCondition.java | 49 ++
.../ans/migrate/MigrateOnConditionClass.java | 22 +
.../MigrateOnConditionMissingClass.java | 23 +
.../ans/migrate/MigrateProxyManager.java | 94 ++++
.../migrate/MigrateRefreshEventListener.java | 75 +++
.../MigrateRibbonBeanPostProcessor.java | 53 +++
.../ans/migrate/MigrateServiceRegistry.java | 51 +++
.../migrate/MigrationAutoconfiguration.java | 25 +
.../migrate/ServerListInvocationHandler.java | 143 ++++++
.../alicloud/ans/migrate/ServerWrapper.java | 35 ++
.../registry/AnsAutoServiceRegistration.java | 11 +-
.../ans/registry/AnsRegistration.java | 23 +-
.../ans/registry/AnsServiceRegistry.java | 42 +-
.../ribbon/AnsRibbonClientConfiguration.java | 5 +-
.../cloud/alicloud/ans/ribbon/AnsServer.java | 50 +-
.../alicloud/ans/ribbon/AnsServerList.java | 6 +-
.../ans/ribbon/MigrateRibbonCofiguration.java | 20 +
.../ribbon/RibbonAnsAutoConfiguration.java | 3 +-
.../main/resources/META-INF/spring.factories | 6 +-
spring-cloud-alicloud-context/pom.xml | 6 +
.../context/sms/SmsConfigProperties.java | 107 +++++
.../context/sms/SmsConfigRegistration.java | 26 ++
.../sms/SmsContextAutoConfiguration.java | 30 ++
.../main/resources/META-INF/spring.factories | 3 +-
spring-cloud-alicloud-sms/pom.xml | 83 ++++
.../alicloud/sms/AbstractSmsService.java | 46 ++
.../cloud/alicloud/sms/ISmsService.java | 115 +++++
.../sms/SmsInitializerEventListener.java | 105 +++++
.../alicloud/sms/SmsMessageListener.java | 24 +
.../sms/SmsReportMessageListener.java | 22 +
.../cloud/alicloud/sms/SmsServiceImpl.java | 187 ++++++++
.../alicloud/sms/SmsUpMessageListener.java | 22 +
.../sms/base/DefaultAlicomMessagePuller.java | 429 ++++++++++++++++++
.../alicloud/sms/base/MessageListener.java | 24 +
.../base/QueryTokenForMnsQueueRequest.java | 82 ++++
.../base/QueryTokenForMnsQueueResponse.java | 117 +++++
...yTokenForMnsQueueResponseUnmarshaller.java | 48 ++
.../alicloud/sms/base/TokenForAlicom.java | 96 ++++
.../sms/base/TokenGetterForAlicom.java | 142 ++++++
.../sms/config/SmsAutoConfiguration.java | 49 ++
.../sms/endpoint/EndpointManager.java | 106 +++++
.../sms/endpoint/ReceiveMessageEntity.java | 60 +++
.../alicloud/sms/endpoint/SmsEndpoint.java | 31 ++
.../SmsEndpointAutoConfiguration.java | 31 ++
.../main/resources/META-INF/spring.factories | 3 +
spring-cloud-starter-alicloud/pom.xml | 1 +
.../spring-cloud-starter-alicloud-sms/pom.xml | 20 +
65 files changed, 3149 insertions(+), 116 deletions(-)
create mode 100644 spring-cloud-alibaba-examples/sms-example/pom.xml
create mode 100644 spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsApplication.java
create mode 100644 spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsController.java
create mode 100644 spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsReportMessageListener.java
create mode 100644 spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsUpMessageListener.java
create mode 100644 spring-cloud-alibaba-examples/sms-example/src/main/resources/application.properties
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpointAutoConfiguration.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnCondition.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrationAutoconfiguration.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerWrapper.java
create mode 100644 spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/MigrateRibbonCofiguration.java
create mode 100644 spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigProperties.java
create mode 100644 spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigRegistration.java
create mode 100644 spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsContextAutoConfiguration.java
create mode 100644 spring-cloud-alicloud-sms/pom.xml
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/AbstractSmsService.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/ISmsService.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsInitializerEventListener.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsMessageListener.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsReportMessageListener.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsServiceImpl.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsUpMessageListener.java
create mode 100755 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/DefaultAlicomMessagePuller.java
create mode 100755 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/MessageListener.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueRequest.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponse.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponseUnmarshaller.java
create mode 100755 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenForAlicom.java
create mode 100755 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenGetterForAlicom.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/config/SmsAutoConfiguration.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/EndpointManager.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/ReceiveMessageEntity.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpoint.java
create mode 100644 spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpointAutoConfiguration.java
create mode 100644 spring-cloud-alicloud-sms/src/main/resources/META-INF/spring.factories
create mode 100644 spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-sms/pom.xml
diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml
index cc49e9ee0..e34b9f726 100644
--- a/spring-cloud-alibaba-dependencies/pom.xml
+++ b/spring-cloud-alibaba-dependencies/pom.xml
@@ -28,6 +28,10 @@
2.16.0
4.3.1
2.1.6
+ 1.1.0
+ 1.1.8
+ 1.1.0
+ 1.1.1
@@ -71,6 +75,19 @@
${schedulerX.client.version}
+
+
+ com.aliyun.mns
+ aliyun-sdk-mns
+ ${aliyun.sdk.mns}
+
+
+
+ com.aliyun
+ aliyun-java-sdk-dysmsapi
+ ${aliyun.java.sdk.dysmsapi}
+
+
com.alibaba.nacos
@@ -213,6 +230,11 @@
spring-cloud-alicloud-schedulerx
${project.version}
+
+ org.springframework.cloud
+ spring-cloud-alicloud-sms
+ ${project.version}
+
org.springframework.cloud
spring-cloud-alicloud-context
@@ -283,6 +305,13 @@
${project.version}
+
+
+ org.springframework.cloud
+ spring-cloud-starter-alicloud-sms
+ ${project.version}
+
+
diff --git a/spring-cloud-alibaba-examples/sms-example/pom.xml b/spring-cloud-alibaba-examples/sms-example/pom.xml
new file mode 100644
index 000000000..77069083f
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sms-example/pom.xml
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+
+ alibaba.com
+ sms-example
+ 0.0.1-SNAPSHOT
+ jar
+
+ sms-example
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.6.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.SR2
+ 0.2.2.BUILD-SNAPSHOT
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba-dependencies
+ ${spring-cloud-alibaba-alicloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-alicloud-sms
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsApplication.java b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsApplication.java
new file mode 100644
index 000000000..a5e89a9a4
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsApplication.java
@@ -0,0 +1,31 @@
+/*
+ * 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.cloud.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ *
+ */
+@SpringBootApplication
+public class SmsApplication {
+
+ public static void main(String[] args) {
+
+ SpringApplication.run(SmsApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsController.java b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsController.java
new file mode 100644
index 000000000..496b97c0d
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsController.java
@@ -0,0 +1,128 @@
+package org.springframework.cloud.alibaba.cloud.example;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alicloud.sms.ISmsService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.aliyun.mns.model.Message;
+import com.aliyuncs.dysmsapi.model.v20170525.*;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.http.MethodType;
+
+@RestController
+public class SmsController {
+
+ @Autowired
+ private ISmsService smsService;
+
+ @Autowired
+ private SmsReportMessageListener smsReportMessageListener;
+
+ /**
+ * 短信发送 Example
+ * @param code
+ * @return
+ */
+ @RequestMapping("/batch-sms-send.do")
+ public SendBatchSmsResponse batchsendCheckCode(
+ @RequestParam(name = "code") String code) {
+ // 组装请求对象
+ SendBatchSmsRequest request = new SendBatchSmsRequest();
+ // 使用post提交
+ request.setMethod(MethodType.GET);
+ // 必填:待发送手机号。支持JSON格式的批量调用,批量上限为100个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
+ request.setPhoneNumberJson("[\"177********\",\"130********\"]");
+ // 必填:短信签名-支持不同的号码发送不同的短信签名
+ request.setSignNameJson("[\"*******\",\"*******\"]");
+ // 必填:短信模板-可在短信控制台中找到
+ request.setTemplateCode("******");
+ // 必填:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+ // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
+ request.setTemplateParamJson(
+ "[{\"code\":\"" + code + "\"},{\"code\":\"" + code + "\"}]");
+ // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
+ // request.setSmsUpExtendCodeJson("[\"90997\",\"90998\"]");
+ try {
+ SendBatchSmsResponse sendSmsResponse = smsService
+ .sendSmsBatchRequest(request);
+ return sendSmsResponse;
+ }
+ catch (ClientException e) {
+ e.printStackTrace();
+ }
+ return new SendBatchSmsResponse();
+ }
+
+ /**
+ * 短信发送 Example
+ * @param code
+ * @return
+ */
+ @RequestMapping("/sms-send.do")
+ public SendSmsResponse sendCheckCode(@RequestParam(name = "code") String code) {
+ // 组装请求对象-具体描述见控制台-文档部分内容
+ SendSmsRequest request = new SendSmsRequest();
+ // 必填:待发送手机号
+ request.setPhoneNumbers("******");
+ // 必填:短信签名-可在短信控制台中找到
+ request.setSignName("******");
+ // 必填:短信模板-可在短信控制台中找到
+ request.setTemplateCode("******");
+ // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+ request.setTemplateParam("{\"code\":\"" + code + "\"}");
+
+ // 选填-上行短信扩展码(无特殊需求用户请忽略此字段)
+ // request.setSmsUpExtendCode("90997");
+
+ // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+ request.setOutId("****TraceId");
+ try {
+ SendSmsResponse sendSmsResponse = smsService.sendSmsRequest(request);
+ return sendSmsResponse;
+ }
+ catch (ClientException e) {
+ e.printStackTrace();
+ }
+ return new SendSmsResponse();
+ }
+
+ /**
+ *
+ * 短信查询 Example
+ * @param telephone
+ * @return
+ */
+ @RequestMapping("/query.do")
+ public QuerySendDetailsResponse querySendDetailsResponse(
+ @RequestParam(name = "tel") String telephone) {
+ // 组装请求对象
+ QuerySendDetailsRequest request = new QuerySendDetailsRequest();
+ // 必填-号码
+ request.setPhoneNumber(telephone);
+ // 必填-短信发送的日期 支持30天内记录查询(可查其中一天的发送数据),格式yyyyMMdd
+ request.setSendDate("20190103");
+ // 必填-页大小
+ request.setPageSize(10L);
+ // 必填-当前页码从1开始计数
+ request.setCurrentPage(1L);
+ try {
+ QuerySendDetailsResponse response = smsService.querySendDetails(request);
+ return response;
+ }
+ catch (ClientException e) {
+ e.printStackTrace();
+ }
+
+ return new QuerySendDetailsResponse();
+ }
+
+ @RequestMapping("/sms-report.do")
+ public List smsReport() {
+
+ return smsReportMessageListener.getSmsReportMessageSet();
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsReportMessageListener.java b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsReportMessageListener.java
new file mode 100644
index 000000000..aa092789f
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsReportMessageListener.java
@@ -0,0 +1,28 @@
+package org.springframework.cloud.alibaba.cloud.example;
+
+import com.aliyun.mns.model.Message;
+import org.springframework.stereotype.Component;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author 如果需要监听短信是否被对方成功接收,只需实现这个接口并初始化一个 Spring Bean 即可。
+ */
+@Component
+public class SmsReportMessageListener
+ implements org.springframework.cloud.alicloud.sms.SmsReportMessageListener {
+ private List smsReportMessageSet = new LinkedList<>();
+
+ @Override
+ public boolean dealMessage(Message message) {
+ smsReportMessageSet.add(message);
+ System.err.println(this.getClass().getName() + "; " + message.toString());
+ return true;
+ }
+
+ public List getSmsReportMessageSet() {
+
+ return smsReportMessageSet;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsUpMessageListener.java b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsUpMessageListener.java
new file mode 100644
index 000000000..22f4efec1
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sms-example/src/main/java/org/springframework/cloud/alibaba/cloud/example/SmsUpMessageListener.java
@@ -0,0 +1,19 @@
+package org.springframework.cloud.alibaba.cloud.example;
+
+import org.springframework.stereotype.Component;
+
+import com.aliyun.mns.model.Message;
+
+/**
+ * @author 如果发送的短信需要接收对方回复的状态消息,只需实现该接口并初始化一个 Spring Bean 即可。
+ */
+@Component
+public class SmsUpMessageListener
+ implements org.springframework.cloud.alicloud.sms.SmsUpMessageListener {
+
+ @Override
+ public boolean dealMessage(Message message) {
+ System.err.println(this.getClass().getName() + "; " + message.toString());
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-examples/sms-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sms-example/src/main/resources/application.properties
new file mode 100644
index 000000000..ae65c56b9
--- /dev/null
+++ b/spring-cloud-alibaba-examples/sms-example/src/main/resources/application.properties
@@ -0,0 +1,9 @@
+spring.application.name=sca-sms-example
+server.port=9051
+# config management
+management.endpoints.web.exposure.include=*
+#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=******
\ No newline at end of file
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java
index 076d884f0..7fedcc169 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java
@@ -27,15 +27,16 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class NacosConfigBootstrapConfiguration {
- @Bean
- public NacosPropertySourceLocator nacosPropertySourceLocator() {
- return new NacosPropertySourceLocator();
- }
-
@Bean
@ConditionalOnMissingBean
public NacosConfigProperties nacosConfigProperties() {
return new NacosConfigProperties();
}
+ @Bean
+ public NacosPropertySourceLocator nacosPropertySourceLocator(
+ NacosConfigProperties nacosConfigProperties) {
+ return new NacosPropertySourceLocator(nacosConfigProperties);
+ }
+
}
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java
index 941672204..8a7be5057 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java
@@ -18,8 +18,8 @@ package org.springframework.cloud.alibaba.nacos;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
@@ -42,10 +42,9 @@ import static com.alibaba.nacos.api.PropertyKeyConst.*;
@ConfigurationProperties(NacosConfigProperties.PREFIX)
public class NacosConfigProperties {
- public static final String PREFIX = "spring.cloud.nacos.config";
+ static final String PREFIX = "spring.cloud.nacos.config";
- private static final Logger LOGGER = LoggerFactory
- .getLogger(NacosConfigProperties.class);
+ private static final Log log = LogFactory.getLog(NacosConfigProperties.class);
/**
* nacos config server address
@@ -348,7 +347,9 @@ public class NacosConfigProperties {
return configService;
}
catch (Exception e) {
- LOGGER.error("create config service error!properties={},e=,", this, e);
+ log.error(
+ "create config service error!properties=" + this.toString() + ",e=,",
+ e);
return null;
}
}
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java
index b900a674c..1b853704a 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java
@@ -18,8 +18,8 @@ package org.springframework.cloud.alibaba.nacos.client;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
import org.springframework.core.io.ByteArrayResource;
@@ -33,8 +33,7 @@ import java.util.*;
* @author pbting
*/
public class NacosPropertySourceBuilder {
- private static final Logger LOGGER = LoggerFactory
- .getLogger(NacosPropertySourceBuilder.class);
+ private static final Log log = LogFactory.getLog(NacosPropertySourceBuilder.class);
private static final Properties EMPTY_PROPERTIES = new Properties();
private ConfigService configService;
@@ -68,9 +67,6 @@ public class NacosPropertySourceBuilder {
NacosPropertySource build(String dataId, String group, String fileExtension,
boolean isRefreshable) {
Properties p = loadNacosData(dataId, group, fileExtension);
- if (p == null) {
- p = EMPTY_PROPERTIES;
- }
NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
propertiesToMap(p), new Date(), isRefreshable);
NacosPropertySourceRepository.collectNacosPropertySources(nacosPropertySource);
@@ -82,7 +78,7 @@ public class NacosPropertySourceBuilder {
try {
data = configService.getConfig(dataId, group, timeout);
if (!StringUtils.isEmpty(data)) {
- LOGGER.info(String.format("Loading nacos data, dataId: '%s', group: '%s'",
+ log.info(String.format("Loading nacos data, dataId: '%s', group: '%s'",
dataId, group));
if (fileExtension.equalsIgnoreCase("properties")) {
@@ -101,13 +97,13 @@ public class NacosPropertySourceBuilder {
}
}
catch (NacosException e) {
- LOGGER.error("get data from Nacos error,dataId:{}, ", dataId, e);
+ log.error("get data from Nacos error,dataId:" + dataId + ", ", e);
}
catch (Exception e) {
- LOGGER.error("parse data from Nacos error,dataId:{},data:{},", dataId, data,
- e);
+ log.error("parse data from Nacos error,dataId:" + dataId + ",data:" + data
+ + ",", e);
}
- return null;
+ return EMPTY_PROPERTIES;
}
@SuppressWarnings("unchecked")
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java
index e0cabb383..72cdb6088 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java
@@ -16,10 +16,11 @@
package org.springframework.cloud.alibaba.nacos.client;
-import com.alibaba.nacos.api.config.ConfigService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher;
@@ -30,8 +31,7 @@ import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
-import java.util.Arrays;
-import java.util.List;
+import com.alibaba.nacos.api.config.ConfigService;
/**
* @author xiaojing
@@ -40,8 +40,7 @@ import java.util.List;
@Order(0)
public class NacosPropertySourceLocator implements PropertySourceLocator {
- private static final Logger LOGGER = LoggerFactory
- .getLogger(NacosPropertySourceLocator.class);
+ private static final Log log = LogFactory.getLog(NacosPropertySourceLocator.class);
private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";
private static final String SEP1 = "-";
private static final String DOT = ".";
@@ -49,22 +48,21 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
private static final List SUPPORT_FILE_EXTENSION = Arrays.asList("properties",
"yaml", "yml");
- @Autowired
+ private NacosPropertySourceBuilder nacosPropertySourceBuilder;
+
private NacosConfigProperties nacosConfigProperties;
- public NacosPropertySourceLocator() {
+ public NacosPropertySourceLocator(NacosConfigProperties nacosConfigProperties) {
+ this.nacosConfigProperties = nacosConfigProperties;
}
- private NacosPropertySourceBuilder nacosPropertySourceBuilder;
-
@Override
public PropertySource> locate(Environment env) {
ConfigService configService = nacosConfigProperties.configServiceInstance();
if (null == configService) {
- LOGGER.warn(
- "no instance of config service found, can't load config from nacos");
+ log.warn("no instance of config service found, can't load config from nacos");
return null;
}
long timeout = nacosConfigProperties.getTimeout();
@@ -167,7 +165,7 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
private void loadNacosDataIfPresent(final CompositePropertySource composite,
final String dataId, final String group, String fileExtension,
boolean isRefreshable) {
- if (NacosContextRefresher.loadCount.get() != 0) {
+ if (NacosContextRefresher.getRefreshCount() != 0) {
NacosPropertySource ps;
if (!isRefreshable) {
ps = NacosPropertySourceRepository.getNacosPropertySource(dataId);
@@ -187,10 +185,10 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
private static void checkDataIdFileExtension(String[] sharedDataIdArry) {
StringBuilder stringBuilder = new StringBuilder();
- outline: for (int i = 0; i < sharedDataIdArry.length; i++) {
+ for (int i = 0; i < sharedDataIdArry.length; i++) {
for (String fileExtension : SUPPORT_FILE_EXTENSION) {
if (sharedDataIdArry[i].indexOf(fileExtension) > 0) {
- continue outline;
+ break;
}
}
stringBuilder.append(sharedDataIdArry[i] + ",");
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java
index c726f9489..fcc6d9df1 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosContextRefresher.java
@@ -19,8 +19,8 @@ package org.springframework.cloud.alibaba.nacos.refresh;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
@@ -51,10 +51,9 @@ import java.util.concurrent.atomic.AtomicLong;
public class NacosContextRefresher
implements ApplicationListener, ApplicationContextAware {
- private final static Logger LOGGER = LoggerFactory
- .getLogger(NacosContextRefresher.class);
+ private final static Log log = LogFactory.getLog(NacosContextRefresher.class);
- public static final AtomicLong loadCount = new AtomicLong(0);
+ private static final AtomicLong REFRESH_COUNT = new AtomicLong(0);
private final NacosRefreshProperties refreshProperties;
@@ -108,7 +107,7 @@ public class NacosContextRefresher
Listener listener = listenerMap.computeIfAbsent(dataId, i -> new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
- loadCount.incrementAndGet();
+ refreshCountIncrement();
String md5 = "";
if (!StringUtils.isEmpty(configInfo)) {
try {
@@ -117,14 +116,14 @@ public class NacosContextRefresher
.toString(16);
}
catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
- LOGGER.warn("[Nacos] unable to get md5 for dataId: " + dataId, e);
+ log.warn("[Nacos] unable to get md5 for dataId: " + dataId, e);
}
}
refreshHistory.add(dataId, md5);
applicationContext.publishEvent(
new RefreshEvent(this, null, "Refresh Nacos config"));
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Refresh Nacos config group{},dataId{}", group, dataId);
+ if (log.isDebugEnabled()) {
+ log.debug("Refresh Nacos config group " + group + ",dataId" + dataId);
}
}
@@ -142,4 +141,11 @@ public class NacosContextRefresher
}
}
+ public static long getRefreshCount() {
+ return REFRESH_COUNT.get();
+ }
+
+ public static void refreshCountIncrement() {
+ REFRESH_COUNT.incrementAndGet();
+ }
}
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java
index a14c6e12a..d563632ea 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java
@@ -21,12 +21,16 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alicloud.ans.migrate.MigrateOnConditionMissingClass;
import org.springframework.cloud.alicloud.ans.registry.AnsAutoServiceRegistration;
import org.springframework.cloud.alicloud.ans.registry.AnsRegistration;
import org.springframework.cloud.alicloud.ans.registry.AnsServiceRegistry;
+import org.springframework.cloud.alicloud.context.ans.AnsProperties;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
@@ -34,6 +38,7 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration
@EnableConfigurationProperties
+@Conditional(MigrateOnConditionMissingClass.class)
@ConditionalOnClass(name = "org.springframework.boot.web.context.WebServerInitializedEvent")
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@ConditionalOnAnsEnabled
@@ -49,8 +54,9 @@ public class AnsAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
- public AnsRegistration ansRegistration() {
- return new AnsRegistration();
+ public AnsRegistration ansRegistration(AnsProperties ansProperties,
+ ApplicationContext applicationContext) {
+ return new AnsRegistration(ansProperties, applicationContext);
}
@Bean
@@ -63,4 +69,5 @@ public class AnsAutoConfiguration {
return new AnsAutoServiceRegistration(registry, autoServiceRegistrationProperties,
registration);
}
+
}
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java
index c95757b22..46e1a1bbf 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java
@@ -16,13 +16,12 @@
package org.springframework.cloud.alicloud.ans;
-import java.util.*;
-
+import com.alibaba.ans.core.NamingService;
+import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
-import com.alibaba.ans.core.NamingService;
-import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
+import java.util.*;
/**
* @author xiaolongzuo
@@ -75,8 +74,9 @@ public class AnsDiscoveryClient implements DiscoveryClient {
@Override
public List getServices() {
-
+ Set publishers = NamingService.getPublishes();
Set doms = NamingService.getDomsSubscribed();
+ doms.addAll(publishers);
List result = new LinkedList<>();
for (String service : doms) {
result.add(service);
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java
index 7d2869763..c19296f4d 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java
@@ -19,15 +19,18 @@ package org.springframework.cloud.alicloud.ans;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alicloud.ans.migrate.MigrateOnConditionMissingClass;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaolongzuo
*/
@Configuration
+@Conditional(MigrateOnConditionMissingClass.class)
@ConditionalOnMissingBean(DiscoveryClient.class)
@EnableConfigurationProperties
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java
index a8bc64c7c..87cdcd591 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java
@@ -16,19 +16,18 @@
package org.springframework.cloud.alicloud.ans.endpoint;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.alibaba.ans.core.NamingService;
+import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.cloud.alicloud.context.ans.AnsProperties;
-import com.alibaba.ans.core.NamingService;
-import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* @author xiaolongzuo
@@ -36,7 +35,7 @@ import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
@Endpoint(id = "ans")
public class AnsEndpoint {
- private static final Logger LOGGER = LoggerFactory.getLogger(AnsEndpoint.class);
+ private static final Log log = LogFactory.getLog(AnsEndpoint.class);
private AnsProperties ansProperties;
@@ -50,7 +49,7 @@ public class AnsEndpoint {
@ReadOperation
public Map invoke() {
Map ansEndpoint = new HashMap<>();
- LOGGER.info("ANS endpoint invoke, ansProperties is {}", ansProperties);
+ log.info("ANS endpoint invoke, ansProperties is " + ansProperties);
ansEndpoint.put("ansProperties", ansProperties);
Map subscribes = new HashMap<>();
@@ -65,7 +64,7 @@ public class AnsEndpoint {
}
}
ansEndpoint.put("subscribes", subscribes);
- LOGGER.info("ANS endpoint invoke, subscribes is {}", subscribes);
+ log.info("ANS endpoint invoke, subscribes is " + subscribes);
return ansEndpoint;
}
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java
new file mode 100644
index 000000000..16b99d7b8
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpoint.java
@@ -0,0 +1,31 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+@Endpoint(id = "migrate")
+public class MigrateEndpoint {
+
+ private static final Log log = LogFactory.getLog(MigrateEndpoint.class);
+
+ public MigrateEndpoint() {
+ }
+
+ /**
+ * @return ans endpoint
+ */
+ @ReadOperation
+ public Map> invoke() {
+
+ Map> result = ServerListInvocationHandler
+ .getServerRegistry();
+
+ log.info("migrate server list :" + result);
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpointAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpointAutoConfiguration.java
new file mode 100644
index 000000000..bc80cfc23
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateEndpointAutoConfiguration.java
@@ -0,0 +1,18 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+
+@ConditionalOnWebApplication
+
+@ConditionalOnClass(name = "org.springframework.boot.actuate.endpoint.annotation.Endpoint")
+@Conditional(MigrateOnConditionClass.class)
+public class MigrateEndpointAutoConfiguration {
+
+ @Bean
+ public MigrateEndpoint ansEndpoint() {
+ return new MigrateEndpoint();
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnCondition.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnCondition.java
new file mode 100644
index 000000000..96050181e
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnCondition.java
@@ -0,0 +1,49 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.springframework.beans.factory.BeanClassLoaderAware;
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author pbting
+ */
+public abstract class MigrateOnCondition implements Condition, BeanClassLoaderAware {
+
+ final String[] conditionOnClass = new String[] {
+ "org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration",
+ "org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration" };
+
+ ClassLoader classLoader;
+
+ @Override
+ public void setBeanClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public abstract boolean matches(ConditionContext context,
+ AnnotatedTypeMetadata metadata);
+
+ boolean isPresent(String className, ClassLoader classLoader) {
+ if (classLoader == null) {
+ classLoader = ClassUtils.getDefaultClassLoader();
+ }
+
+ try {
+ forName(className, classLoader);
+ return true;
+ }
+ catch (Throwable var3) {
+ return false;
+ }
+ }
+
+ Class> forName(String className, ClassLoader classLoader)
+ throws ClassNotFoundException {
+ return classLoader != null ? classLoader.loadClass(className)
+ : Class.forName(className);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java
new file mode 100644
index 000000000..cf5ee82ad
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionClass.java
@@ -0,0 +1,22 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * @author pbting
+ */
+public class MigrateOnConditionClass extends MigrateOnCondition {
+
+ protected static final Log log = LogFactory.getLog(MigrateOnConditionClass.class);
+
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ boolean result = isPresent(conditionOnClass[0], classLoader)
+ || isPresent(conditionOnClass[1], classLoader);
+ log.info("the result of MigrateOnConditionClass is :" + result);
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java
new file mode 100644
index 000000000..e5651c6f9
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateOnConditionMissingClass.java
@@ -0,0 +1,23 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * @author pbting
+ */
+public class MigrateOnConditionMissingClass extends MigrateOnConditionClass {
+
+ protected static final Log log = LogFactory
+ .getLog(MigrateOnConditionMissingClass.class);
+
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ boolean result = !super.matches(context, metadata);
+ log.info("the result of MigrateOnConditionMissingClass is :" + result);
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java
new file mode 100644
index 000000000..df2800829
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateProxyManager.java
@@ -0,0 +1,94 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.aopalliance.aop.Advice;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.aop.AfterReturningAdvice;
+import org.springframework.aop.framework.ProxyFactory;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.Server;
+import com.netflix.loadbalancer.ServerList;
+
+/**
+ * @author pbting
+ */
+final class MigrateProxyManager {
+
+ private final static Log log = LogFactory.getLog(MigrateProxyManager.class);
+ private final static AtomicBoolean IS_PROXY = new AtomicBoolean(true);
+
+ private final static Set SERVICES_ID = new ConcurrentSkipListSet<>();
+
+ private static Object springProxyFactory(Object target, ClassLoader classLoader,
+ List adviceList, Class... interfaces) {
+ final ProxyFactory proxyFactory = new ProxyFactory(interfaces);
+ proxyFactory.setTarget(target);
+ adviceList.forEach(advice -> proxyFactory.addAdvice(advice));
+ return proxyFactory.getProxy(classLoader);
+ }
+
+ static Object newServerListProxy(Object bean, ClassLoader classLoader,
+ IClientConfig clientConfig) {
+ bean = springProxyFactory(bean, classLoader,
+ Arrays.asList(new ServerListInvocationHandler(clientConfig)),
+ new Class[] { ServerList.class });
+ log.info("[service id]" + clientConfig.getClientName()
+ + " new a ServerList proxy instance for spring cloud netflix to spring cloud alibaba ");
+ collectServiceId(clientConfig.getClientName());
+ return bean;
+ }
+
+ static Object newLoadBalancerProxy(Object bean, ClassLoader classLoader,
+ IClientConfig clientConfig) {
+
+ bean = springProxyFactory(bean, classLoader,
+ Arrays.asList(new AfterReturningAdvice() {
+ @Override
+ public void afterReturning(Object returnValue, Method method,
+ Object[] args, Object target) {
+ String methodName = method.getName();
+ if ("chooseServer".equals(methodName)) {
+ String serviceId = clientConfig.getClientName();
+ Server server = (Server) returnValue;
+ ServerListInvocationHandler.incrementCallService(serviceId,
+ server);
+ }
+ }
+ }), new Class[] { ILoadBalancer.class });
+ log.info("[service id]" + clientConfig.getClientName()
+ + " new a ILoadBalancer proxy instance for spring cloud netflix to spring cloud alibaba ");
+ return bean;
+ }
+
+ static void migrateProxyClose() {
+ IS_PROXY.set(false);
+ }
+
+ static void migrateProxyUp() {
+ IS_PROXY.set(true);
+ }
+
+ static boolean isMigrateProxy() {
+
+ return IS_PROXY.get();
+ }
+
+ static void collectServiceId(String serviceId) {
+ SERVICES_ID.add(serviceId);
+ }
+
+ static Set getServicesId() {
+
+ return Collections.unmodifiableSet(SERVICES_ID);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java
new file mode 100644
index 000000000..620776d9a
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRefreshEventListener.java
@@ -0,0 +1,75 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import com.netflix.loadbalancer.ILoadBalancer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.context.named.NamedContextFactory;
+import org.springframework.cloud.endpoint.event.RefreshEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author pbting
+ */
+@Component
+public class MigrateRefreshEventListener implements ApplicationListener {
+
+ private final static String MIGRATE_SWITCH = "sca.migrate.ans.switch";
+
+ private volatile String lastScaMigrateAnsSwitchValue = "true";
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private NamedContextFactory namedContextFactory;
+
+ public MigrateRefreshEventListener() {
+ }
+
+ @PostConstruct
+ public void initTimerCheck() {
+ Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(
+ () -> onApplicationEvent(null), 1, 1, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void onApplicationEvent(RefreshEvent event) {
+ String value = environment.getProperty(MIGRATE_SWITCH, "true");
+ // check 1: check the value
+ if (value.equals(lastScaMigrateAnsSwitchValue)) {
+ return;
+ }
+
+ updateLastScaMigrateAnsResetValue(value);
+
+ // step 1: migrate up
+ if ("true".equals(value)) {
+ MigrateProxyManager.migrateProxyUp();
+ serviceIdContextInit();
+ return;
+ }
+
+ // step 2: migrate close
+ if ("false".equals(value)) {
+ MigrateProxyManager.migrateProxyClose();
+ serviceIdContextInit();
+ return;
+ }
+ }
+
+ private void serviceIdContextInit() {
+ namedContextFactory.destroy();
+ // initializer each spring context for service id
+ MigrateProxyManager.getServicesId().forEach(serviceId -> namedContextFactory
+ .getInstance(serviceId, ILoadBalancer.class));
+ }
+
+ private synchronized void updateLastScaMigrateAnsResetValue(String value) {
+ this.lastScaMigrateAnsSwitchValue = value;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java
new file mode 100644
index 000000000..c863399b0
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateRibbonBeanPostProcessor.java
@@ -0,0 +1,53 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanClassLoaderAware;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.ServerList;
+
+public class MigrateRibbonBeanPostProcessor
+ implements BeanPostProcessor, BeanClassLoaderAware {
+
+ protected static final Log log = LogFactory.getLog(MigrateOnCondition.class);
+
+ private ClassLoader classLoader;
+ private IClientConfig clientConfig;
+
+ public MigrateRibbonBeanPostProcessor(IClientConfig clientConfig) {
+ this.clientConfig = clientConfig;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+
+ // step 1 : check the bean whether proxy or not
+ if (!MigrateProxyManager.isMigrateProxy()) {
+ log.info("Migrate proxy is Close.");
+ return bean;
+ }
+
+ // step 2 : proxy the designated bean
+ if (bean instanceof ServerList) {
+ bean = MigrateProxyManager.newServerListProxy(bean, classLoader,
+ clientConfig);
+ }
+
+ if (bean instanceof ILoadBalancer) {
+ bean = MigrateProxyManager.newLoadBalancerProxy(bean, classLoader,
+ clientConfig);
+ }
+ return bean;
+ }
+
+ @Override
+ public void setBeanClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java
new file mode 100644
index 000000000..5491e98df
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrateServiceRegistry.java
@@ -0,0 +1,51 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.cloud.alicloud.ans.registry.AnsRegistration;
+import org.springframework.cloud.alicloud.ans.registry.AnsServiceRegistry;
+import org.springframework.cloud.alicloud.context.ans.AnsProperties;
+import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author pbting
+ */
+@Component
+public class MigrateServiceRegistry {
+
+ private static final Log log = LogFactory.getLog(MigrateServiceRegistry.class);
+
+ private AtomicBoolean running = new AtomicBoolean(false);
+
+ private ServiceRegistry serviceRegistry;
+ private AnsRegistration ansRegistration;
+
+ public MigrateServiceRegistry(AnsProperties ansProperties,
+ ApplicationContext context) {
+ this.ansRegistration = new AnsRegistration(ansProperties, context);
+ this.ansRegistration.init();
+ this.serviceRegistry = new AnsServiceRegistry();
+ }
+
+ @EventListener(WebServerInitializedEvent.class)
+ public void onApplicationEvent(WebServerInitializedEvent event) {
+ int serverPort = event.getWebServer().getPort();
+ this.ansRegistration.setPort(serverPort);
+ log.info("[ Migrate ] change the port to " + serverPort);
+ if (!this.running.get()) {
+ long s = System.currentTimeMillis();
+ log.info("[Migrate] start to registry server to ANS");
+ this.serviceRegistry.register(this.ansRegistration);
+ log.info("[migrate] end to registry server to ANS cost time with "
+ + (System.currentTimeMillis() - s) + " ms.");
+ this.running.set(true);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrationAutoconfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrationAutoconfiguration.java
new file mode 100644
index 000000000..45ae571f4
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/MigrationAutoconfiguration.java
@@ -0,0 +1,25 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alicloud.ans.ConditionalOnAnsEnabled;
+import org.springframework.cloud.alicloud.context.ans.AnsProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties
+@Conditional(MigrateOnConditionClass.class)
+@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
+@ConditionalOnAnsEnabled
+public class MigrationAutoconfiguration {
+
+ @Bean
+ public MigrateServiceRegistry migrationManger(AnsProperties ansProperties,
+ ApplicationContext applicationContext) {
+
+ return new MigrateServiceRegistry(ansProperties, applicationContext);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java
new file mode 100644
index 000000000..2a8f1b4f2
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerListInvocationHandler.java
@@ -0,0 +1,143 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.Server;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.alicloud.ans.ribbon.AnsServer;
+import org.springframework.cloud.alicloud.ans.ribbon.AnsServerList;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ *
+ */
+class ServerListInvocationHandler implements MethodInterceptor {
+
+ private final static Log log = LogFactory.getLog(ServerListInvocationHandler.class);
+
+ private final static ConcurrentMap> CALL_SERVICE_COUNT = new ConcurrentHashMap<>();
+ private final static Set INTERCEPTOR_METHOD_NAME = new ConcurrentSkipListSet();
+
+ private IClientConfig clientConfig;
+ private AnsServerList ansServerList;
+ private AtomicBoolean isFirst = new AtomicBoolean(false);
+
+ static {
+ INTERCEPTOR_METHOD_NAME.add("getInitialListOfServers");
+ INTERCEPTOR_METHOD_NAME.add("getUpdatedListOfServers");
+ }
+
+ ServerListInvocationHandler(IClientConfig clientConfig) {
+ this.clientConfig = clientConfig;
+ this.ansServerList = new AnsServerList(clientConfig.getClientName());
+ }
+
+ @Override
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ String methodName = invocation.getMethod().getName();
+ // step 1: check the method is not interceptor
+ if (!INTERCEPTOR_METHOD_NAME.contains(methodName)) {
+ return invocation.proceed();
+ }
+
+ // step 2: interceptor the method
+ List serverList = (List) invocation.proceed();
+ long s = System.currentTimeMillis();
+ log.info("[ START ] merage server list for " + clientConfig.getClientName());
+ serverList = mergeAnsServerList(serverList);
+ log.info("[ END ] merage server list for " + clientConfig.getClientName()
+ + ", cost time " + (System.currentTimeMillis() - s) + " ms .");
+ return serverList;
+ }
+
+ /**
+ * 后台线程 和 Eureka 两个注册中心进行 Merage 的时候,List 表中始终保持是有效的 Server. 即不考虑 ANS 客户端本地容灾的情况
+ */
+ private List mergeAnsServerList(final List source) {
+ if (isFirst.compareAndSet(false, true)) {
+ return source;
+ }
+
+ // step 1: get all of server list and filter the alive
+ List ansServerList = filterAliveAnsServer(
+ this.ansServerList.getInitialListOfServers());
+
+ if (ansServerList.isEmpty()) {
+ return source;
+ }
+
+ log.info("[" + this.clientConfig.getClientName() + "] Get Server List from ANS:"
+ + ansServerList + "; loadbalancer server list override before:" + source);
+
+ // step 2:remove servers of that have in load balancer list
+ final Iterator serverIterator = source.iterator();
+ while (serverIterator.hasNext()) {
+ final Server server = serverIterator.next();
+ ansServerList.forEach(ansServer -> {
+ if (server.getHostPort()
+ .equals(ansServer.getHealthService().toInetAddr())) {
+ // fix bug: mast be set the zone, update server list,will filter
+ // by: ZoneAffinityPredicate
+ ansServer.setZone(server.getZone());
+ ansServer.setSchemea(server.getScheme());
+ ansServer.setId(server.getId());
+ ansServer.setReadyToServe(true);
+ serverIterator.remove();
+ log.info("Source Server is remove " + server.getHostPort()
+ + ", and from ANS Server is override:"
+ + ansServer.toString());
+ }
+ });
+ }
+
+ ansServerList.forEach(ansServer -> source.add(ansServer));
+ log.info("[" + this.clientConfig.getClientName() + "] "
+ + "; loadbalancer server list override after:" + source);
+ // override
+ return source;
+ }
+
+ private List filterAliveAnsServer(List sourceServerList) {
+ final List resultServerList = new LinkedList<>();
+ sourceServerList.forEach(ansServer -> {
+ boolean isAlive = ansServer.isAlive(3);
+ if (isAlive) {
+ resultServerList.add(ansServer);
+ }
+ log.warn(ansServer.toString() + " isAlive :" + isAlive);
+ });
+ return resultServerList;
+ }
+
+ static Map> getServerRegistry() {
+
+ return Collections.unmodifiableMap(CALL_SERVICE_COUNT);
+ }
+
+ static void incrementCallService(String serviceId, Server server) {
+ ConcurrentMap concurrentHashMap = CALL_SERVICE_COUNT
+ .putIfAbsent(serviceId, new ConcurrentHashMap<>());
+
+ if (concurrentHashMap == null) {
+ concurrentHashMap = CALL_SERVICE_COUNT.get(serviceId);
+ }
+
+ String ipPort = server.getHostPort();
+ ServerWrapper serverWraper = concurrentHashMap.putIfAbsent(ipPort,
+ new ServerWrapper(server, new AtomicLong()));
+
+ if (serverWraper == null) {
+ serverWraper = concurrentHashMap.get(ipPort);
+ }
+ serverWraper.setServer(server);
+ serverWraper.getCallCount().incrementAndGet();
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerWrapper.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerWrapper.java
new file mode 100644
index 000000000..aeaa5a60e
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/migrate/ServerWrapper.java
@@ -0,0 +1,35 @@
+package org.springframework.cloud.alicloud.ans.migrate;
+
+import com.netflix.loadbalancer.Server;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class ServerWrapper {
+
+ private Server server;
+ private AtomicLong callCount;
+
+ public ServerWrapper() {
+ }
+
+ public ServerWrapper(Server server, AtomicLong callCount) {
+ this.server = server;
+ this.callCount = callCount;
+ }
+
+ public Server getServer() {
+ return server;
+ }
+
+ public void setServer(Server server) {
+ this.server = server;
+ }
+
+ public AtomicLong getCallCount() {
+ return callCount;
+ }
+
+ public void setCallCount(AtomicLong callCount) {
+ this.callCount = callCount;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java
index 0774f1856..b48c94b2d 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java
@@ -16,8 +16,8 @@
package org.springframework.cloud.alicloud.ans.registry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
@@ -30,8 +30,7 @@ import org.springframework.util.StringUtils;
*/
public class AnsAutoServiceRegistration
extends AbstractAutoServiceRegistration {
- private static final Logger LOGGER = LoggerFactory
- .getLogger(AnsAutoServiceRegistration.class);
+ private static final Log log = LogFactory.getLog(AnsAutoServiceRegistration.class);
@Autowired
private AnsRegistration registration;
@@ -59,13 +58,13 @@ public class AnsAutoServiceRegistration
@Override
protected AnsRegistration getManagementRegistration() {
- return null;
+ return registration;
}
@Override
protected void register() {
if (!this.registration.getAnsProperties().isRegisterEnabled()) {
- LOGGER.debug("Registration disabled.");
+ log.debug("Registration disabled.");
return;
}
if (this.registration.getPort() < 0) {
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java
index 1fcb292f3..e28bf4779 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java
@@ -16,12 +16,6 @@
package org.springframework.cloud.alicloud.ans.registry;
-import java.net.URI;
-import java.util.Map;
-
-import javax.annotation.PostConstruct;
-
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alicloud.context.ans.AnsProperties;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
@@ -31,6 +25,10 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
+import javax.annotation.PostConstruct;
+import java.net.URI;
+import java.util.Map;
+
/**
* @author xiaolongzuo
*/
@@ -40,12 +38,14 @@ public class AnsRegistration implements Registration, ServiceInstance {
private static final String MANAGEMENT_CONTEXT_PATH = "management.context-path";
private static final String MANAGEMENT_ADDRESS = "management.address";
- @Autowired
private AnsProperties ansProperties;
-
- @Autowired
private ApplicationContext context;
+ public AnsRegistration(AnsProperties ansProperties, ApplicationContext context) {
+ this.ansProperties = ansProperties;
+ this.context = context;
+ }
+
@PostConstruct
public void init() {
@@ -64,6 +64,11 @@ public class AnsRegistration implements Registration, ServiceInstance {
metadata.put(MANAGEMENT_ADDRESS, address);
}
}
+
+ String serverPort = env.getProperty("server.port");
+ if (null != serverPort) {
+ this.setPort(Integer.valueOf(serverPort));
+ }
}
@Override
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java
index ebe65ee39..1ff187a35 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java
@@ -16,24 +16,23 @@
package org.springframework.cloud.alicloud.ans.registry;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
+import com.alibaba.ans.core.NamingService;
+import com.alibaba.ans.shaded.com.taobao.vipserver.client.ipms.NodeReactor;
import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
-import com.alibaba.ans.core.NamingService;
-import com.alibaba.ans.shaded.com.taobao.vipserver.client.ipms.NodeReactor;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
/**
* @author xiaolongzuo
*/
public class AnsServiceRegistry implements ServiceRegistry {
- private static Logger logger = LoggerFactory.getLogger(AnsServiceRegistry.class);
+ private static Log log = LogFactory.getLog(AnsServiceRegistry.class);
private static final String SEPARATOR = ",";
@@ -41,11 +40,11 @@ public class AnsServiceRegistry implements ServiceRegistry {
public void register(AnsRegistration registration) {
if (!registration.isRegisterEnabled()) {
- logger.info("Registration is disabled...");
+ log.info("Registration is disabled...");
return;
}
if (StringUtils.isEmpty(registration.getServiceId())) {
- logger.info("No service to register for client...");
+ log.info("No service to register for client...");
return;
}
@@ -63,13 +62,14 @@ public class AnsServiceRegistry implements ServiceRegistry {
NamingService.regDom(dom, registration.getHost(), registration.getPort(),
registration.getRegisterWeight(dom), registration.getCluster(),
tags);
- logger.info("INFO_ANS_REGISTER, {} {}:{} register finished", dom,
- registration.getAnsProperties().getClientIp(),
- registration.getAnsProperties().getClientPort());
+ log.info("INFO_ANS_REGISTER, " + dom + " "
+ + registration.getAnsProperties().getClientIp() + ":"
+ + registration.getAnsProperties().getClientPort()
+ + " register finished");
}
catch (Exception e) {
- logger.error("ERR_ANS_REGISTER, {} register failed...{},", dom,
- registration.toString(), e);
+ log.error("ERR_ANS_REGISTER, " + dom + " register failed..."
+ + registration.toString() + ",", e);
}
}
}
@@ -77,10 +77,10 @@ public class AnsServiceRegistry implements ServiceRegistry {
@Override
public void deregister(AnsRegistration registration) {
- logger.info("De-registering from ANSServer now...");
+ log.info("De-registering from ANSServer now...");
if (StringUtils.isEmpty(registration.getServiceId())) {
- logger.info("No dom to de-register for client...");
+ log.info("No dom to de-register for client...");
return;
}
@@ -89,11 +89,11 @@ public class AnsServiceRegistry implements ServiceRegistry {
registration.getPort(), registration.getCluster());
}
catch (Exception e) {
- logger.error("ERR_ANS_DEREGISTER, de-register failed...{},",
- registration.toString(), e);
+ log.error("ERR_ANS_DEREGISTER, de-register failed..."
+ + registration.toString() + ",", e);
}
- logger.info("De-registration finished.");
+ log.info("De-registration finished.");
}
@Override
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java
index 7734e0371..93393ed9e 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java
@@ -17,7 +17,9 @@
package org.springframework.cloud.alicloud.ans.ribbon;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.cloud.alicloud.ans.migrate.MigrateOnConditionMissingClass;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import com.netflix.client.config.IClientConfig;
@@ -27,11 +29,12 @@ import com.netflix.loadbalancer.ServerList;
* @author xiaolongzuo
*/
@Configuration
+@Conditional(MigrateOnConditionMissingClass.class)
public class AnsRibbonClientConfiguration {
@Bean
@ConditionalOnMissingBean
- public ServerList> ribbonServerList(IClientConfig config) {
+ public ServerList> ansRibbonServerList(IClientConfig config) {
AnsServerList serverList = new AnsServerList(config.getClientName());
return serverList;
}
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java
index 8438a7f35..d19f62870 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java
@@ -16,12 +16,16 @@
package org.springframework.cloud.alicloud.ans.ribbon;
-import java.util.Collections;
-import java.util.Map;
-
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
import com.netflix.loadbalancer.Server;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
/**
* @author xiaolongzuo
*/
@@ -34,7 +38,8 @@ public class AnsServer extends Server {
public AnsServer(final Host host, final String dom) {
super(host.getIp(), host.getPort());
this.host = host;
- this.metadata = Collections.emptyMap();
+ this.metadata = new HashMap();
+ this.metadata.put("source", "ANS");
metaInfo = new MetaInfo() {
@Override
public String getAppName() {
@@ -48,16 +53,44 @@ public class AnsServer extends Server {
@Override
public String getServiceIdForDiscovery() {
- return null;
+ return dom;
}
@Override
public String getInstanceId() {
- return null;
+ return AnsServer.this.host.getIp() + ":" + dom + ":"
+ + AnsServer.this.host.getPort();
}
};
}
+ @Override
+ public boolean isAlive() {
+
+ return true;
+ }
+
+ /**
+ *
+ * @param timeOut Unit: Seconds
+ * @return
+ */
+ public boolean isAlive(long timeOut) {
+ try {
+ String hostName = this.host.getHostname();
+ hostName = hostName != null && hostName.trim().length() > 0 ? hostName
+ : this.host.getIp();
+ Socket socket = new Socket();
+ socket.connect(new InetSocketAddress(hostName, this.host.getPort()),
+ (int) TimeUnit.SECONDS.toMillis(timeOut));
+ socket.close();
+ return true;
+ }
+ catch (IOException e) {
+ return false;
+ }
+ }
+
@Override
public MetaInfo getMetaInfo() {
return metaInfo;
@@ -71,4 +104,9 @@ public class AnsServer extends Server {
return metadata;
}
+ @Override
+ public String toString() {
+ return "AnsServer{" + "metaInfo=" + metaInfo + ", host=" + host + ", metadata="
+ + metadata + '}';
+ }
}
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java
index f34f19ffd..d6a3d9df5 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java
@@ -60,10 +60,12 @@ public class AnsServerList extends AbstractServerList {
List result = new ArrayList(hosts.size());
for (Host host : hosts) {
if (host.isValid()) {
- result.add(hostToServer(host));
+ AnsServer ansServer = hostToServer(host);
+ if (ansServer.isAlive(3)) {
+ result.add(ansServer);
+ }
}
}
-
return result;
}
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/MigrateRibbonCofiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/MigrateRibbonCofiguration.java
new file mode 100644
index 000000000..5bda207c3
--- /dev/null
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/MigrateRibbonCofiguration.java
@@ -0,0 +1,20 @@
+package org.springframework.cloud.alicloud.ans.ribbon;
+
+import org.springframework.cloud.alicloud.ans.migrate.MigrateRibbonBeanPostProcessor;
+import org.springframework.cloud.alicloud.ans.migrate.MigrateOnConditionClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+
+import com.netflix.client.config.IClientConfig;
+
+@Configuration
+@Conditional(MigrateOnConditionClass.class)
+public class MigrateRibbonCofiguration {
+
+ @Bean
+ public MigrateRibbonBeanPostProcessor migrateBeanPostProcessor(IClientConfig clientConfig) {
+
+ return new MigrateRibbonBeanPostProcessor(clientConfig);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java
index 4333cb534..cf7d52ff1 100644
--- a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java
+++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java
@@ -34,6 +34,7 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnBean(SpringClientFactory.class)
@ConditionalOnRibbonAns
@AutoConfigureAfter(RibbonAutoConfiguration.class)
-@RibbonClients(defaultConfiguration = AnsRibbonClientConfiguration.class)
+@RibbonClients(defaultConfiguration = { AnsRibbonClientConfiguration.class,
+ MigrateRibbonCofiguration.class })
public class RibbonAnsAutoConfiguration {
}
diff --git a/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories
index 63d6cd5c8..050c64ec2 100644
--- a/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories
@@ -1,6 +1,10 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alicloud.ans.endpoint.AnsEndpointAutoConfiguration,\
org.springframework.cloud.alicloud.ans.ribbon.RibbonAnsAutoConfiguration,\
- org.springframework.cloud.alicloud.ans.AnsAutoConfiguration
+ org.springframework.cloud.alicloud.ans.AnsAutoConfiguration,\
+ org.springframework.cloud.alicloud.ans.migrate.MigrateEndpointAutoConfiguration,\
+ org.springframework.cloud.alicloud.ans.migrate.MigrationAutoconfiguration
org.springframework.cloud.client.discovery.EnableDiscoveryClient=\
org.springframework.cloud.alicloud.ans.AnsDiscoveryClientAutoConfiguration
+org.springframework.context.ApplicationListener=\
+ org.springframework.cloud.alicloud.ans.migrate.MigrateRefreshEventListener
\ No newline at end of file
diff --git a/spring-cloud-alicloud-context/pom.xml b/spring-cloud-alicloud-context/pom.xml
index 39e73ab50..496aea377 100644
--- a/spring-cloud-alicloud-context/pom.xml
+++ b/spring-cloud-alicloud-context/pom.xml
@@ -50,6 +50,12 @@
provided
+
+ com.alibaba.ans
+ ans-sdk
+ provided
+
+
com.aliyun.oss
aliyun-sdk-oss
diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigProperties.java
new file mode 100644
index 000000000..022c5e19d
--- /dev/null
+++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigProperties.java
@@ -0,0 +1,107 @@
+package org.springframework.cloud.alicloud.context.sms;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.alicloud.context.AliCloudProperties;
+import org.springframework.core.env.Environment;
+import org.springframework.util.StringUtils;
+
+import java.io.Serializable;
+
+/**
+ * @author pbting
+ */
+@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
+public class SmsConfigProperties implements Serializable {
+
+ // 产品名称:云通信短信API产品,开发者无需替换
+ public static final String smsProduct = "Dysmsapi";
+ // 产品域名,开发者无需替换
+ public static final String smsDomain = "dysmsapi.aliyuncs.com";
+
+ private AliCloudProperties aliCloudProperties;
+
+ /**
+ *
+ */
+ private String reportQueueName;
+ /**
+ *
+ */
+ private String upQueueName;
+
+ /**
+ *
+ */
+ protected String connnectTimeout = "10000";
+
+ /**
+ *
+ */
+ protected String readTimeout = "10000";
+
+ public SmsConfigProperties(AliCloudProperties aliCloudProperties) {
+ this.aliCloudProperties = aliCloudProperties;
+ }
+
+ public String getConnnectTimeout() {
+ return connnectTimeout;
+ }
+
+ public void setConnnectTimeout(String connnectTimeout) {
+ this.connnectTimeout = connnectTimeout;
+ }
+
+ public String getReadTimeout() {
+ return readTimeout;
+ }
+
+ public void setReadTimeout(String readTimeout) {
+ this.readTimeout = readTimeout;
+ }
+
+ public void overiideFromEnv(Environment environment) {
+ overiideCustomFromEnv(environment);
+ if (StringUtils.isEmpty(connnectTimeout)) {
+ String resolveResult = environment.resolveRequiredPlaceholders(
+ "${spring.cloud.alibaba.sms.connect-timeout:}");
+ this.setConnnectTimeout(
+ StringUtils.isEmpty(resolveResult) ? "10000" : resolveResult);
+ }
+
+ if (StringUtils.isEmpty(readTimeout)) {
+ String resolveResult = environment.resolveRequiredPlaceholders(
+ "${spring.cloud.alibaba.sms.read-timeout:}");
+ this.setReadTimeout(
+ StringUtils.isEmpty(resolveResult) ? "10000" : resolveResult);
+ }
+ }
+
+ public void overiideCustomFromEnv(Environment environment) {
+ // nothing to do
+ }
+
+ public String getReportQueueName() {
+ return reportQueueName;
+ }
+
+ public void setReportQueueName(String reportQueueName) {
+ this.reportQueueName = reportQueueName;
+ }
+
+ public String getUpQueueName() {
+ return upQueueName;
+ }
+
+ public String getAccessKeyId() {
+ return aliCloudProperties.getAccessKey();
+ }
+
+ public String getAccessKeySecret() {
+ return aliCloudProperties.getSecretKey();
+ }
+
+ public void setUpQueueName(String upQueueName) {
+ this.upQueueName = upQueueName;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigRegistration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigRegistration.java
new file mode 100644
index 000000000..555642627
--- /dev/null
+++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsConfigRegistration.java
@@ -0,0 +1,26 @@
+package org.springframework.cloud.alicloud.context.sms;
+
+import org.springframework.core.env.Environment;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @author pbting
+ */
+public class SmsConfigRegistration {
+
+ private Environment environment;
+
+ private SmsConfigProperties smsConfigProperties;
+
+ public SmsConfigRegistration(Environment environment,
+ SmsConfigProperties smsConfigProperties) {
+ this.environment = environment;
+ this.smsConfigProperties = smsConfigProperties;
+ }
+
+ @PostConstruct
+ public void initSmsConfigRegistration() {
+ smsConfigProperties.overiideFromEnv(environment);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsContextAutoConfiguration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsContextAutoConfiguration.java
new file mode 100644
index 000000000..6f1e44160
--- /dev/null
+++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/sms/SmsContextAutoConfiguration.java
@@ -0,0 +1,30 @@
+package org.springframework.cloud.alicloud.context.sms;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alicloud.context.AliCloudProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+@Configuration
+@EnableConfigurationProperties
+@ConditionalOnClass(name = "com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest")
+@ConditionalOnProperty(value = "spring.cloud.alibaba.deshao.enable.sms", matchIfMissing = true)
+public class SmsContextAutoConfiguration {
+
+ @Bean
+ public SmsConfigProperties smsConfigProperties(
+ AliCloudProperties aliCloudProperties) {
+
+ return new SmsConfigProperties(aliCloudProperties);
+ }
+
+ @Bean
+ public SmsConfigRegistration smsConfigRegistration(Environment environment,
+ SmsConfigProperties smsConfigProperties) {
+
+ return new SmsConfigRegistration(environment, smsConfigProperties);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories
index a14c70778..f99f05028 100644
--- a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories
@@ -6,7 +6,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alicloud.context.ans.AnsContextAutoConfiguration,\
org.springframework.cloud.alicloud.context.oss.OssContextAutoConfiguration,\
org.springframework.cloud.alicloud.context.scx.ScxContextAutoConfiguration,\
- org.springframework.cloud.alicloud.context.statistics.StatisticsTaskStarter
+ org.springframework.cloud.alicloud.context.statistics.StatisticsTaskStarter,\
+ org.springframework.cloud.alicloud.context.sms.SmsContextAutoConfiguration
org.springframework.context.ApplicationListener=\
org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener,\
org.springframework.cloud.alicloud.context.nacos.NacosParameterInitListener,\
diff --git a/spring-cloud-alicloud-sms/pom.xml b/spring-cloud-alicloud-sms/pom.xml
new file mode 100644
index 000000000..001a46adc
--- /dev/null
+++ b/spring-cloud-alicloud-sms/pom.xml
@@ -0,0 +1,83 @@
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba
+ 0.2.2.BUILD-SNAPSHOT
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-alicloud-sms
+ Spring Cloud Alibaba Cloud SMS
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-alicloud-context
+
+
+ com.aliyun
+ aliyun-java-sdk-core
+
+
+
+
+
+
+ com.aliyun
+ aliyun-java-sdk-core
+
+
+ com.aliyun
+ aliyun-java-sdk-dysmsapi
+
+
+ com.aliyun.mns
+ aliyun-sdk-mns
+
+
+ com.aliyun
+ aliyun-java-sdk-dysmsapi
+
+
+
+ org.springframework.boot
+ spring-boot-actuator
+ provided
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-actuator-autoconfigure
+ provided
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ provided
+ true
+
+
+
+ org.slf4j
+ slf4j-api
+ provided
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/AbstractSmsService.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/AbstractSmsService.java
new file mode 100644
index 000000000..02273a696
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/AbstractSmsService.java
@@ -0,0 +1,46 @@
+/*
+ * 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.alicloud.sms;
+
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.profile.DefaultProfile;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ *
+ * @author pbting
+ */
+public abstract class AbstractSmsService implements ISmsService {
+
+ private ConcurrentHashMap acsClientConcurrentHashMap = new ConcurrentHashMap<>();
+
+ public IAcsClient getHangZhouRegionClientProfile(String accessKeyId,
+ String accessKeySecret) {
+
+ return acsClientConcurrentHashMap.computeIfAbsent(
+ getKey("cn-hangzhou", accessKeyId, accessKeySecret),
+ (iacsClient) -> new DefaultAcsClient(DefaultProfile
+ .getProfile("cn-hangzhou", accessKeyId, accessKeySecret)));
+ }
+
+ private String getKey(String regionId, String accessKeyId, String accessKeySecret) {
+
+ return regionId + ":" + accessKeyId + ":" + accessKeySecret;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/ISmsService.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/ISmsService.java
new file mode 100644
index 000000000..54a8201cf
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/ISmsService.java
@@ -0,0 +1,115 @@
+/*
+ * 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.alicloud.sms;
+
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.*;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.exceptions.ServerException;
+
+/**
+ * @author pbting
+ */
+public interface ISmsService {
+
+ /**
+ *
+ * @param accessKeyId
+ * @param secret
+ * @return IAcsClient
+ */
+ IAcsClient getHangZhouRegionClientProfile(String accessKeyId, String secret);
+
+ /**
+ *
+ * @param sendSmsRequest
+ * @throws ServerException
+ * @throws ClientException
+ * @return SendSmsResponse
+ */
+ SendSmsResponse sendSmsRequest(SendSmsRequest sendSmsRequest)
+ throws ServerException, ClientException;
+
+ /**
+ *
+ * @param sendBatchSmsRequest
+ * @throws ServerException
+ * @throws ClientException
+ * @return SendBatchSmsResponse
+ */
+ SendBatchSmsResponse sendSmsBatchRequest(SendBatchSmsRequest sendBatchSmsRequest)
+ throws ServerException, ClientException;
+
+ /**
+ * 因为阿里云支持多个
+ * accessKeyId/accessKeySecret,当不想使用默认的配置accessKeyId/accessKeySecret时,可以使用这个方法来支持额外
+ * 的accessKeyId/accessKeySecret 发送
+ * @param sendSmsRequest
+ * @param accessKeyId
+ * @param accessKeySecret
+ * @return
+ * @throws ServerException
+ * @throws ClientException
+ */
+ SendSmsResponse sendSmsRequest(SendSmsRequest sendSmsRequest, String accessKeyId,
+ String accessKeySecret) throws ServerException, ClientException;
+
+ /**
+ *
+ * @param sendSmsRequest
+ * @param accessKeyId
+ * @param accessKeySecret
+ * @throws ServerException
+ * @throws ClientException
+ * @return SendBatchSmsResponse
+ */
+ SendBatchSmsResponse sendSmsBatchRequest(SendBatchSmsRequest sendSmsRequest,
+ String accessKeyId, String accessKeySecret)
+ throws ServerException, ClientException;
+
+ /**
+ *
+ * @param smsReportMessageListener
+ * @return boolean
+ */
+ boolean startSmsReportMessageListener(
+ SmsReportMessageListener smsReportMessageListener);
+
+ /**
+ *
+ * @param smsUpMessageListener
+ * @return boolean
+ */
+ boolean startSmsUpMessageListener(SmsUpMessageListener smsUpMessageListener);
+
+ /**
+ *
+ * @param request
+ * @param accessKeyId
+ * @param accessKeySecret
+ * @return QuerySendDetailsResponse
+ */
+ QuerySendDetailsResponse querySendDetails(QuerySendDetailsRequest request,
+ String accessKeyId, String accessKeySecret) throws ClientException;
+
+ /**
+ *
+ * @param request
+ * @return QuerySendDetailsResponse
+ */
+ QuerySendDetailsResponse querySendDetails(QuerySendDetailsRequest request)
+ throws ClientException;
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsInitializerEventListener.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsInitializerEventListener.java
new file mode 100644
index 000000000..0556ea068
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsInitializerEventListener.java
@@ -0,0 +1,105 @@
+/*
+ * 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.alicloud.sms;
+
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.profile.DefaultProfile;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.cloud.alicloud.context.sms.SmsConfigProperties;
+import org.springframework.cloud.alicloud.sms.base.MessageListener;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author pbting
+ */
+@Component
+public class SmsInitializerEventListener
+ implements ApplicationListener {
+
+ private final AtomicBoolean isCalled = new AtomicBoolean(false);
+
+ private SmsConfigProperties msConfigProperties;
+
+ private ISmsService smsService;
+
+ public SmsInitializerEventListener(SmsConfigProperties msConfigProperties,
+ ISmsService smsService) {
+ this.msConfigProperties = msConfigProperties;
+ this.smsService = smsService;
+ }
+
+ @Override
+ public void onApplicationEvent(ApplicationStartedEvent event) {
+ if (!isCalled.compareAndSet(false, true)) {
+ return;
+ }
+
+ // 整个application context refreshed then do
+ // 可自助调整超时时间
+ System.setProperty("sun.net.client.defaultConnectTimeout",
+ msConfigProperties.getConnnectTimeout());
+ System.setProperty("sun.net.client.defaultReadTimeout",
+ msConfigProperties.getReadTimeout());
+ // 初始化acsClient,暂不支持region化
+ try {
+ DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou",
+ SmsConfigProperties.smsProduct, SmsConfigProperties.smsDomain);
+ Collection messageListeners = event.getApplicationContext()
+ .getBeansOfType(MessageListener.class).values();
+ if (messageListeners.isEmpty()) {
+ return;
+ }
+
+ for (MessageListener messageListener : messageListeners) {
+ if (SmsReportMessageListener.class.isInstance(messageListener)) {
+ if (msConfigProperties.getReportQueueName() != null
+ && msConfigProperties.getReportQueueName().trim()
+ .length() > 0) {
+ smsService.startSmsReportMessageListener(
+ (SmsReportMessageListener) messageListener);
+ continue;
+ }
+
+ throw new IllegalArgumentException("the SmsReport queue name for "
+ + messageListener.getClass().getCanonicalName()
+ + " must be set.");
+ }
+
+ if (SmsUpMessageListener.class.isInstance(messageListener)) {
+
+ if (msConfigProperties.getUpQueueName() != null
+ && msConfigProperties.getUpQueueName().trim().length() > 0) {
+ smsService.startSmsUpMessageListener(
+ (SmsUpMessageListener) messageListener);
+ continue;
+ }
+
+ throw new IllegalArgumentException("the SmsUp queue name for "
+ + messageListener.getClass().getCanonicalName()
+ + " must be set.");
+ }
+ }
+ }
+ catch (ClientException e) {
+ throw new RuntimeException(
+ "initialize sms profile end point cause an exception");
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsMessageListener.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsMessageListener.java
new file mode 100644
index 000000000..5fc34dd52
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsMessageListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.alicloud.sms;
+
+import org.springframework.cloud.alicloud.sms.base.MessageListener;
+
+/**
+ * @author pbting
+ */
+public interface SmsMessageListener extends MessageListener {
+}
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsReportMessageListener.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsReportMessageListener.java
new file mode 100644
index 000000000..c214a628e
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsReportMessageListener.java
@@ -0,0 +1,22 @@
+/*
+ * 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.alicloud.sms;
+
+/**
+ * @author pbting
+ */
+public interface SmsReportMessageListener extends SmsMessageListener {
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsServiceImpl.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsServiceImpl.java
new file mode 100644
index 000000000..d32c8c64a
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsServiceImpl.java
@@ -0,0 +1,187 @@
+/*
+ * 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.alicloud.sms;
+
+import com.aliyuncs.dysmsapi.model.v20170525.*;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.exceptions.ServerException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.alicloud.context.sms.SmsConfigProperties;
+import org.springframework.cloud.alicloud.sms.base.DefaultAlicomMessagePuller;
+import org.springframework.cloud.alicloud.sms.endpoint.EndpointManager;
+import org.springframework.cloud.alicloud.sms.endpoint.ReceiveMessageEntity;
+
+import java.text.ParseException;
+
+/**
+ * @author pbting
+ */
+public final class SmsServiceImpl extends AbstractSmsService {
+
+ private static final Log log = LogFactory.getLog(SmsServiceImpl.class);
+ /**
+ * will expose user to call this method send sms message
+ * @param sendSmsRequest
+ * @return
+ */
+ private SmsConfigProperties smsConfigProperties;
+
+ public SmsServiceImpl(SmsConfigProperties smsConfigProperties) {
+ this.smsConfigProperties = smsConfigProperties;
+ }
+
+ public SendSmsResponse sendSmsRequest(SendSmsRequest sendSmsRequest)
+ throws ClientException {
+
+ return sendSmsRequest(sendSmsRequest, smsConfigProperties.getAccessKeyId(),
+ smsConfigProperties.getAccessKeySecret());
+ }
+
+ /**
+ * 因为阿里云支持多个
+ * accessKeyId/accessKeySecret,当不想使用默认的配置accessKeyId/accessKeySecret时,可以使用这个方法来支持额外
+ * 的accessKeyId/accessKeySecret 发送
+ * @param sendSmsRequest
+ * @param accessKeyId
+ * @param accessKeySecret
+ * @throws ServerException
+ * @throws ClientException
+ * @return SendSmsResponse
+ */
+ public SendSmsResponse sendSmsRequest(SendSmsRequest sendSmsRequest,
+ String accessKeyId, String accessKeySecret)
+ throws ServerException, ClientException {
+ EndpointManager.addSendSmsRequest(sendSmsRequest);
+ // hint 此处可能会抛出异常,注意catch
+ return getHangZhouRegionClientProfile(accessKeyId, accessKeySecret)
+ .getAcsResponse(sendSmsRequest);
+ }
+
+ /**
+ *
+ * @param smsReportMessageListener
+ * @return boolean
+ */
+ public boolean startSmsReportMessageListener(
+ SmsReportMessageListener smsReportMessageListener) {
+ String messageType = "SmsReport";// 短信回执:SmsReport,短信上行:SmsUp
+ String queueName = smsConfigProperties.getReportQueueName();
+ return startReceiveMsg(messageType, queueName, smsReportMessageListener);
+ }
+
+ /**
+ *
+ * @param smsUpMessageListener
+ * @return boolean
+ */
+ public boolean startSmsUpMessageListener(SmsUpMessageListener smsUpMessageListener) {
+ String messageType = "SmsUp";// 短信回执:SmsReport,短信上行:SmsUp
+ String queueName = smsConfigProperties.getUpQueueName();
+ return startReceiveMsg(messageType, queueName, smsUpMessageListener);
+ }
+
+ /**
+ *
+ * @param messageType
+ * @param queueName
+ * @param messageListener
+ * @return boolean
+ */
+ private boolean startReceiveMsg(String messageType, String queueName,
+ SmsMessageListener messageListener) {
+ String accessKeyId = smsConfigProperties.getAccessKeyId();
+ String accessKeySecret = smsConfigProperties.getAccessKeySecret();
+ boolean result = true;
+ try {
+ new DefaultAlicomMessagePuller().startReceiveMsg(accessKeyId, accessKeySecret,
+ messageType, queueName, messageListener);
+ EndpointManager.addReceiveMessageEntity(
+ new ReceiveMessageEntity(messageType, queueName, messageListener));
+ }
+ catch (ClientException e) {
+ log.error("start sms report message listener cause an exception", e);
+ result = false;
+ }
+ catch (ParseException e) {
+ log.error("start sms report message listener cause an exception", e);
+ result = false;
+ }
+ return result;
+ }
+
+ /**
+ *
+ * @param sendBatchSmsRequest
+ * @throws ServerException
+ * @throws ClientException
+ * @return SendBatchSmsResponse
+ */
+ @Override
+ public SendBatchSmsResponse sendSmsBatchRequest(
+ SendBatchSmsRequest sendBatchSmsRequest)
+ throws ServerException, ClientException {
+
+ return sendSmsBatchRequest(sendBatchSmsRequest,
+ smsConfigProperties.getAccessKeyId(),
+ smsConfigProperties.getAccessKeySecret());
+ }
+
+ /**
+ *
+ * @param sendBatchSmsRequest
+ * @param accessKeyId
+ * @param accessKeySecret
+ * @throws ClientException
+ * @return SendBatchSmsResponse
+ */
+ @Override
+ public SendBatchSmsResponse sendSmsBatchRequest(
+ SendBatchSmsRequest sendBatchSmsRequest, String accessKeyId,
+ String accessKeySecret) throws ClientException {
+ EndpointManager.addSendBatchSmsRequest(sendBatchSmsRequest);
+ return getHangZhouRegionClientProfile(accessKeyId, accessKeySecret)
+ .getAcsResponse(sendBatchSmsRequest);
+ }
+
+ /**
+ *
+ * @param request
+ * @param accessKeyId
+ * @param accessKeySecret
+ * @throws ClientException
+ * @return QuerySendDetailsResponse
+ */
+ @Override
+ public QuerySendDetailsResponse querySendDetails(QuerySendDetailsRequest request,
+ String accessKeyId, String accessKeySecret) throws ClientException {
+ return getHangZhouRegionClientProfile(accessKeyId, accessKeySecret)
+ .getAcsResponse(request);
+ }
+
+ /**
+ *
+ * @param request
+ * @throws ClientException
+ * @return QuerySendDetailsResponse
+ */
+ @Override
+ public QuerySendDetailsResponse querySendDetails(QuerySendDetailsRequest request)
+ throws ClientException {
+ return querySendDetails(request, smsConfigProperties.getAccessKeyId(),
+ smsConfigProperties.getAccessKeySecret());
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsUpMessageListener.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsUpMessageListener.java
new file mode 100644
index 000000000..4da614382
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/SmsUpMessageListener.java
@@ -0,0 +1,22 @@
+/*
+ * 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.alicloud.sms;
+
+/**
+ * @author pbting
+ */
+public interface SmsUpMessageListener extends SmsMessageListener {
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/DefaultAlicomMessagePuller.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/DefaultAlicomMessagePuller.java
new file mode 100755
index 000000000..50fe2ed6e
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/DefaultAlicomMessagePuller.java
@@ -0,0 +1,429 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyun.mns.client.CloudQueue;
+import com.aliyun.mns.common.ClientException;
+import com.aliyun.mns.common.ServiceException;
+import com.aliyun.mns.model.Message;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+/**
+ * 阿里通信官方消息默认拉取工具类
+ */
+public class DefaultAlicomMessagePuller {
+
+ private Log logger = LogFactory.getLog(DefaultAlicomMessagePuller.class);
+
+ private String mnsAccountEndpoint = "https://1943695596114318.mns.cn-hangzhou.aliyuncs.com/";// 阿里通信消息的endpoint,固定。
+ private String endpointNameForPop = "cn-hangzhou";
+ private String regionIdForPop = "cn-hangzhou";
+ private String domainForPop = "dybaseapi.aliyuncs.com";
+ private TokenGetterForAlicom tokenGetter;
+ private MessageListener messageListener;
+ private boolean isRunning = false;
+ private Integer pullMsgThreadSize = 1;
+ private boolean debugLogOpen = false;
+ private Integer sleepSecondWhenNoData = 30;
+
+ public void openDebugLog(boolean debugLogOpen) {
+ this.debugLogOpen = debugLogOpen;
+ }
+
+ public Integer getSleepSecondWhenNoData() {
+ return sleepSecondWhenNoData;
+ }
+
+ public void setSleepSecondWhenNoData(Integer sleepSecondWhenNoData) {
+ this.sleepSecondWhenNoData = sleepSecondWhenNoData;
+ }
+
+ public Integer getPullMsgThreadSize() {
+ return pullMsgThreadSize;
+ }
+
+ public void setPullMsgThreadSize(Integer pullMsgThreadSize) {
+ if (pullMsgThreadSize != null && pullMsgThreadSize > 1) {
+ this.pullMsgThreadSize = pullMsgThreadSize;
+ }
+ }
+
+ private ExecutorService executorService;
+
+ public ExecutorService getExecutorService() {
+ return executorService;
+ }
+
+ public void setExecutorService(ExecutorService executorService) {
+ this.executorService = executorService;
+ }
+
+ protected static final Map sLockObjMap = new HashMap();
+ protected static Map sPollingMap = new ConcurrentHashMap();
+ protected Object lockObj;
+
+ public boolean setPolling(String queueName) {
+ synchronized (lockObj) {
+ Boolean ret = sPollingMap.get(queueName);
+ if (ret == null || !ret) {
+ sPollingMap.put(queueName, true);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public void clearPolling(String queueName) {
+ synchronized (lockObj) {
+ sPollingMap.put(queueName, false);
+ lockObj.notifyAll();
+ if (debugLogOpen) {
+ logger.info("PullMessageTask_WakeUp:Everyone WakeUp and Work!");
+ }
+ }
+ }
+
+ public boolean isRunning() {
+ return isRunning;
+ }
+
+ public void setRunning(boolean running) {
+ isRunning = running;
+ }
+
+ private class PullMessageTask implements Runnable {
+ private String messageType;
+ private String queueName;
+
+ @Override
+ public void run() {
+
+ boolean polling = false;
+ while (isRunning) {
+ try {
+ synchronized (lockObj) {
+ Boolean p = sPollingMap.get(queueName);
+ if (p != null && p) {
+ try {
+ if (debugLogOpen) {
+ logger.info("PullMessageTask_sleep:"
+ + Thread.currentThread().getName()
+ + " Have a nice sleep!");
+ }
+ polling = false;
+ lockObj.wait();
+ }
+ catch (InterruptedException e) {
+ if (debugLogOpen) {
+ logger.info("PullMessageTask_Interrupted!"
+ + Thread.currentThread().getName()
+ + " QueueName is " + queueName);
+ }
+ continue;
+ }
+ }
+ }
+
+ TokenForAlicom tokenObject = tokenGetter.getTokenByMessageType(
+ messageType, queueName, mnsAccountEndpoint);
+ CloudQueue queue = tokenObject.getQueue();
+ Message popMsg = null;
+ if (!polling) {
+ popMsg = queue.popMessage();
+ if (debugLogOpen) {
+ SimpleDateFormat format = new SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss");
+ logger.info("PullMessageTask_popMessage:"
+ + Thread.currentThread().getName() + "-popDone at "
+ + "," + format.format(new Date()) + " msgSize="
+ + (popMsg == null ? 0 : popMsg.getMessageId()));
+ }
+ if (popMsg == null) {
+ polling = true;
+ continue;
+ }
+ }
+ else {
+ if (setPolling(queueName)) {
+ if (debugLogOpen) {
+ logger.info("PullMessageTask_setPolling:"
+ + Thread.currentThread().getName() + " Polling!");
+ }
+ }
+ else {
+ continue;
+ }
+ do {
+ if (debugLogOpen) {
+ logger.info("PullMessageTask_Keep_Polling"
+ + Thread.currentThread().getName()
+ + "KEEP Polling!");
+ }
+ try {
+ popMsg = queue.popMessage(sleepSecondWhenNoData);
+ }
+ catch (ClientException e) {
+ if (debugLogOpen) {
+ logger.info(
+ "PullMessageTask_Pop_Message:ClientException Refresh accessKey"
+ + e);
+ }
+ tokenObject = tokenGetter.getTokenByMessageType(
+ messageType, queueName, mnsAccountEndpoint);
+ queue = tokenObject.getQueue();
+
+ }
+ catch (ServiceException e) {
+ if (debugLogOpen) {
+ logger.info(
+ "PullMessageTask_Pop_Message:ServiceException Refresh accessKey"
+ + e);
+ }
+ tokenObject = tokenGetter.getTokenByMessageType(
+ messageType, queueName, mnsAccountEndpoint);
+ queue = tokenObject.getQueue();
+
+ }
+ catch (Exception e) {
+ if (debugLogOpen) {
+ logger.info(
+ "PullMessageTask_Pop_Message:Exception Happened when polling popMessage: "
+ + e);
+ }
+ }
+ }
+ while (popMsg == null && isRunning);
+ clearPolling(queueName);
+ }
+ boolean dealResult = messageListener.dealMessage(popMsg);
+ if (dealResult) {
+ // remember to delete message when consume message successfully.
+ if (debugLogOpen) {
+ logger.info("PullMessageTask_Deal_Message:"
+ + Thread.currentThread().getName() + "deleteMessage "
+ + popMsg.getMessageId());
+ }
+ queue.deleteMessage(popMsg.getReceiptHandle());
+ }
+ }
+ catch (ClientException e) {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName, e);
+ break;
+
+ }
+ catch (ServiceException e) {
+ if (e.getErrorCode().equals("AccessDenied")) {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName
+ + ",please check messageType and queueName", e);
+ }
+ else {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName, e);
+ }
+ break;
+
+ }
+ catch (com.aliyuncs.exceptions.ClientException e) {
+ if (e.getErrCode().equals("InvalidAccessKeyId.NotFound")) {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName
+ + ",please check AccessKeyId", e);
+ }
+ if (e.getErrCode().equals("SignatureDoesNotMatch")) {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName
+ + ",please check AccessKeySecret", e);
+ }
+ else {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName, e);
+ }
+ break;
+
+ }
+ catch (Exception e) {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName, e);
+ try {
+ Thread.sleep(sleepSecondWhenNoData);
+ }
+ catch (InterruptedException e1) {
+ logger.error("PullMessageTask_execute_error,messageType:"
+ + messageType + ",queueName:" + queueName, e);
+ }
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * @param accessKeyId accessKeyId
+ * @param accessKeySecret accessKeySecret
+ * @param messageType 消息类型
+ * @param queueName 队列名称
+ * @param messageListener 回调的listener,用户自己实现
+ * @throws com.aliyuncs.exceptions.ClientException
+ * @throws ParseException
+ */
+ public void startReceiveMsg(String accessKeyId, String accessKeySecret,
+ String messageType, String queueName, MessageListener messageListener)
+ throws com.aliyuncs.exceptions.ClientException, ParseException {
+
+ tokenGetter = new TokenGetterForAlicom(accessKeyId, accessKeySecret,
+ endpointNameForPop, regionIdForPop, domainForPop, null);
+
+ this.messageListener = messageListener;
+ isRunning = true;
+ PullMessageTask task = new PullMessageTask();
+ task.messageType = messageType;
+ task.queueName = queueName;
+
+ synchronized (sLockObjMap) {
+ lockObj = sLockObjMap.get(queueName);
+ if (lockObj == null) {
+ lockObj = new Object();
+ sLockObjMap.put(queueName, lockObj);
+ }
+ }
+
+ if (executorService == null) {
+ ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(
+ pullMsgThreadSize,
+ new BasicThreadFactory.Builder()
+ .namingPattern(
+ "PullMessageTask-" + messageType + "-thread-pool-%d")
+ .daemon(true).build());
+ executorService = scheduledExecutorService;
+ }
+ for (int i = 0; i < pullMsgThreadSize; i++) {
+ executorService.execute(task);
+ }
+ }
+
+ /**
+ * @param accessKeyId accessKeyId
+ * @param accessKeySecret accessKeySecret
+ * @param messageType 消息类型
+ * @param queueName 队列名称
+ * @param messageListener 回调的listener,用户自己实现
+ * @throws com.aliyuncs.exceptions.ClientException
+ * @throws ParseException
+ */
+ public void startReceiveMsgForVPC(String accessKeyId, String accessKeySecret,
+ String messageType, String queueName, String regionIdForPop,
+ String endpointNameForPop, String domainForPop, String mnsAccountEndpoint,
+ MessageListener messageListener)
+ throws com.aliyuncs.exceptions.ClientException, ParseException {
+ this.mnsAccountEndpoint = mnsAccountEndpoint;
+ tokenGetter = new TokenGetterForAlicom(accessKeyId, accessKeySecret,
+ endpointNameForPop, regionIdForPop, domainForPop, null);
+
+ this.messageListener = messageListener;
+ isRunning = true;
+ PullMessageTask task = new PullMessageTask();
+ task.messageType = messageType;
+ task.queueName = queueName;
+
+ synchronized (sLockObjMap) {
+ lockObj = sLockObjMap.get(queueName);
+ if (lockObj == null) {
+ lockObj = new Object();
+ sLockObjMap.put(queueName, lockObj);
+ }
+ }
+
+ if (executorService == null) {
+ ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(
+ pullMsgThreadSize,
+ new BasicThreadFactory.Builder()
+ .namingPattern(
+ "PullMessageTask-" + messageType + "-thread-pool-%d")
+ .daemon(true).build());
+ executorService = scheduledExecutorService;
+ }
+ for (int i = 0; i < pullMsgThreadSize; i++) {
+ executorService.execute(task);
+ }
+ }
+
+ /**
+ * 虚商用户定制接收消息方法
+ * @param accessKeyId accessKeyId
+ * @param accessKeySecret accessKeySecret
+ * @param ownerId 实际的ownerId
+ * @param messageType 消息类型
+ * @param queueName 队列名称
+ * @param messageListener 回调listener
+ * @throws com.aliyuncs.exceptions.ClientException
+ * @throws ParseException
+ */
+ public void startReceiveMsgForPartnerUser(String accessKeyId, String accessKeySecret,
+ Long ownerId, String messageType, String queueName,
+ MessageListener messageListener)
+ throws com.aliyuncs.exceptions.ClientException, ParseException {
+
+ tokenGetter = new TokenGetterForAlicom(accessKeyId, accessKeySecret,
+ endpointNameForPop, regionIdForPop, domainForPop, ownerId);
+
+ this.messageListener = messageListener;
+ isRunning = true;
+ PullMessageTask task = new PullMessageTask();
+ task.messageType = messageType;
+ task.queueName = queueName;
+
+ synchronized (sLockObjMap) {
+ lockObj = sLockObjMap.get(queueName);
+ if (lockObj == null) {
+ lockObj = new Object();
+ sLockObjMap.put(queueName, lockObj);
+ }
+ }
+
+ if (executorService == null) {
+ ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(
+ pullMsgThreadSize,
+ new BasicThreadFactory.Builder()
+ .namingPattern(
+ "PullMessageTask-" + messageType + "-thread-pool-%d")
+ .daemon(true).build());
+ executorService = scheduledExecutorService;
+ }
+ for (int i = 0; i < pullMsgThreadSize; i++) {
+ executorService.execute(task);
+ }
+ }
+
+ public void stop() {
+ isRunning = false;
+ }
+
+}
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/MessageListener.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/MessageListener.java
new file mode 100755
index 000000000..9921232a6
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/MessageListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyun.mns.model.Message;
+
+public interface MessageListener {
+
+ boolean dealMessage(Message message);
+
+}
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueRequest.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueRequest.java
new file mode 100644
index 000000000..956ecadbf
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueRequest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyuncs.RpcAcsRequest;
+
+public class QueryTokenForMnsQueueRequest
+ extends RpcAcsRequest {
+ private String resourceOwnerAccount;
+ private String messageType;
+ private Long resourceOwnerId;
+ private Long ownerId;
+
+ public QueryTokenForMnsQueueRequest() {
+ super("Dybaseapi", "2017-05-25", "QueryTokenForMnsQueue");
+ }
+
+ public String getResourceOwnerAccount() {
+ return this.resourceOwnerAccount;
+ }
+
+ public void setResourceOwnerAccount(String resourceOwnerAccount) {
+ this.resourceOwnerAccount = resourceOwnerAccount;
+ if (resourceOwnerAccount != null) {
+ this.putQueryParameter("ResourceOwnerAccount", resourceOwnerAccount);
+ }
+
+ }
+
+ public String getMessageType() {
+ return this.messageType;
+ }
+
+ public void setMessageType(String messageType) {
+ this.messageType = messageType;
+ if (messageType != null) {
+ this.putQueryParameter("MessageType", messageType);
+ }
+
+ }
+
+ public Long getResourceOwnerId() {
+ return this.resourceOwnerId;
+ }
+
+ public void setResourceOwnerId(Long resourceOwnerId) {
+ this.resourceOwnerId = resourceOwnerId;
+ if (resourceOwnerId != null) {
+ this.putQueryParameter("ResourceOwnerId", resourceOwnerId.toString());
+ }
+
+ }
+
+ public Long getOwnerId() {
+ return this.ownerId;
+ }
+
+ public void setOwnerId(Long ownerId) {
+ this.ownerId = ownerId;
+ if (ownerId != null) {
+ this.putQueryParameter("OwnerId", ownerId.toString());
+ }
+
+ }
+
+ public Class getResponseClass() {
+ return QueryTokenForMnsQueueResponse.class;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponse.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponse.java
new file mode 100644
index 000000000..56c401714
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponse.java
@@ -0,0 +1,117 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyuncs.AcsResponse;
+import com.aliyuncs.transform.UnmarshallerContext;
+
+public class QueryTokenForMnsQueueResponse extends AcsResponse {
+ private String requestId;
+ private String code;
+ private String message;
+ private QueryTokenForMnsQueueResponse.MessageTokenDTO messageTokenDTO;
+
+ public QueryTokenForMnsQueueResponse() {
+ }
+
+ public String getRequestId() {
+ return this.requestId;
+ }
+
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
+ }
+
+ public String getCode() {
+ return this.code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return this.message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public QueryTokenForMnsQueueResponse.MessageTokenDTO getMessageTokenDTO() {
+ return this.messageTokenDTO;
+ }
+
+ public void setMessageTokenDTO(
+ QueryTokenForMnsQueueResponse.MessageTokenDTO messageTokenDTO) {
+ this.messageTokenDTO = messageTokenDTO;
+ }
+
+ public QueryTokenForMnsQueueResponse getInstance(UnmarshallerContext context) {
+ return QueryTokenForMnsQueueResponseUnmarshaller.unmarshall(this, context);
+ }
+
+ public static class MessageTokenDTO {
+ private String accessKeyId;
+ private String accessKeySecret;
+ private String securityToken;
+ private String createTime;
+ private String expireTime;
+
+ public MessageTokenDTO() {
+ }
+
+ public String getAccessKeyId() {
+ return this.accessKeyId;
+ }
+
+ public void setAccessKeyId(String accessKeyId) {
+ this.accessKeyId = accessKeyId;
+ }
+
+ public String getAccessKeySecret() {
+ return this.accessKeySecret;
+ }
+
+ public void setAccessKeySecret(String accessKeySecret) {
+ this.accessKeySecret = accessKeySecret;
+ }
+
+ public String getSecurityToken() {
+ return this.securityToken;
+ }
+
+ public void setSecurityToken(String securityToken) {
+ this.securityToken = securityToken;
+ }
+
+ public String getCreateTime() {
+ return this.createTime;
+ }
+
+ public void setCreateTime(String createTime) {
+ this.createTime = createTime;
+ }
+
+ public String getExpireTime() {
+ return this.expireTime;
+ }
+
+ public void setExpireTime(String expireTime) {
+ this.expireTime = expireTime;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponseUnmarshaller.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponseUnmarshaller.java
new file mode 100644
index 000000000..627e8bb5f
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/QueryTokenForMnsQueueResponseUnmarshaller.java
@@ -0,0 +1,48 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyuncs.transform.UnmarshallerContext;
+
+public class QueryTokenForMnsQueueResponseUnmarshaller {
+
+ public QueryTokenForMnsQueueResponseUnmarshaller() {
+ }
+
+ public static QueryTokenForMnsQueueResponse unmarshall(
+ QueryTokenForMnsQueueResponse queryTokenForMnsQueueResponse,
+ UnmarshallerContext context) {
+ queryTokenForMnsQueueResponse.setRequestId(
+ context.stringValue("QueryTokenForMnsQueueResponse.RequestId"));
+ queryTokenForMnsQueueResponse
+ .setCode(context.stringValue("QueryTokenForMnsQueueResponse.Code"));
+ queryTokenForMnsQueueResponse
+ .setMessage(context.stringValue("QueryTokenForMnsQueueResponse.Message"));
+ QueryTokenForMnsQueueResponse.MessageTokenDTO messageTokenDTO = new QueryTokenForMnsQueueResponse.MessageTokenDTO();
+ messageTokenDTO.setAccessKeyId(context.stringValue(
+ "QueryTokenForMnsQueueResponse.MessageTokenDTO.AccessKeyId"));
+ messageTokenDTO.setAccessKeySecret(context.stringValue(
+ "QueryTokenForMnsQueueResponse.MessageTokenDTO.AccessKeySecret"));
+ messageTokenDTO.setSecurityToken(context.stringValue(
+ "QueryTokenForMnsQueueResponse.MessageTokenDTO.SecurityToken"));
+ messageTokenDTO.setCreateTime(context
+ .stringValue("QueryTokenForMnsQueueResponse.MessageTokenDTO.CreateTime"));
+ messageTokenDTO.setExpireTime(context
+ .stringValue("QueryTokenForMnsQueueResponse.MessageTokenDTO.ExpireTime"));
+ queryTokenForMnsQueueResponse.setMessageTokenDTO(messageTokenDTO);
+ return queryTokenForMnsQueueResponse;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenForAlicom.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenForAlicom.java
new file mode 100755
index 000000000..8af1a63c2
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenForAlicom.java
@@ -0,0 +1,96 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyun.mns.client.CloudQueue;
+import com.aliyun.mns.client.MNSClient;
+
+/**
+ * 用于接收云通信消息的临时token
+ *
+ */
+public class TokenForAlicom {
+ private String messageType;
+ private String token;
+ private Long expireTime;
+ private String tempAccessKeyId;
+ private String tempAccessKeySecret;
+ private MNSClient client;
+ private CloudQueue queue;
+
+ public String getMessageType() {
+ return messageType;
+ }
+
+ public void setMessageType(String messageType) {
+ this.messageType = messageType;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public Long getExpireTime() {
+ return expireTime;
+ }
+
+ public void setExpireTime(Long expireTime) {
+ this.expireTime = expireTime;
+ }
+
+ public String getTempAccessKeyId() {
+ return tempAccessKeyId;
+ }
+
+ public void setTempAccessKeyId(String tempAccessKeyId) {
+ this.tempAccessKeyId = tempAccessKeyId;
+ }
+
+ public String getTempAccessKeySecret() {
+ return tempAccessKeySecret;
+ }
+
+ public void setTempAccessKeySecret(String tempAccessKeySecret) {
+ this.tempAccessKeySecret = tempAccessKeySecret;
+ }
+
+ public MNSClient getClient() {
+ return client;
+ }
+
+ public void setClient(MNSClient client) {
+ this.client = client;
+ }
+
+ public CloudQueue getQueue() {
+ return queue;
+ }
+
+ public void setQueue(CloudQueue queue) {
+ this.queue = queue;
+ }
+
+ public void closeClient() {
+ if (client != null) {
+ this.client.close();
+ }
+ }
+
+}
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenGetterForAlicom.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenGetterForAlicom.java
new file mode 100755
index 000000000..270f9a56b
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/base/TokenGetterForAlicom.java
@@ -0,0 +1,142 @@
+/*
+ * 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.alicloud.sms.base;
+
+import com.aliyun.mns.client.CloudAccount;
+import com.aliyun.mns.client.CloudQueue;
+import com.aliyun.mns.client.MNSClient;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.exceptions.ServerException;
+import com.aliyuncs.http.FormatType;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.http.ProtocolType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * 获取接收云通信消息的临时token
+ *
+ */
+public class TokenGetterForAlicom {
+ private Log logger = LogFactory.getLog(TokenGetterForAlicom.class);
+ private String accessKeyId;
+ private String accessKeySecret;
+ private String endpointNameForPop;
+ private String regionIdForPop;
+ private String domainForPop;
+ private IAcsClient iAcsClient;
+ private Long ownerId;
+ private final static String productName = "Dybaseapi";
+ private long bufferTime = 1000 * 60 * 2;// 过期时间小于2分钟则重新获取,防止服务器时间误差
+ private final Object lock = new Object();
+ private ConcurrentMap tokenMap = new ConcurrentHashMap();
+
+ public TokenGetterForAlicom(String accessKeyId, String accessKeySecret,
+ String endpointNameForPop, String regionIdForPop, String domainForPop,
+ Long ownerId) throws ClientException {
+ this.accessKeyId = accessKeyId;
+ this.accessKeySecret = accessKeySecret;
+ this.endpointNameForPop = endpointNameForPop;
+ this.regionIdForPop = regionIdForPop;
+ this.domainForPop = domainForPop;
+ this.ownerId = ownerId;
+ init();
+ }
+
+ private void init() throws ClientException {
+ DefaultProfile.addEndpoint(endpointNameForPop, regionIdForPop, productName,
+ domainForPop);
+ IClientProfile profile = DefaultProfile.getProfile(regionIdForPop, accessKeyId,
+ accessKeySecret);
+ profile.getHttpClientConfig().setCompatibleMode(true);
+ iAcsClient = new DefaultAcsClient(profile);
+ }
+
+ private TokenForAlicom getTokenFromRemote(String messageType)
+ throws ServerException, ClientException, ParseException {
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+ QueryTokenForMnsQueueRequest request = new QueryTokenForMnsQueueRequest();
+ request.setAcceptFormat(FormatType.JSON);
+ request.setMessageType(messageType);
+ request.setOwnerId(ownerId);
+ request.setProtocol(ProtocolType.HTTPS);
+ request.setMethod(MethodType.POST);
+ QueryTokenForMnsQueueResponse response = iAcsClient.getAcsResponse(request);
+ String resultCode = response.getCode();
+ if (resultCode != null && "OK".equals(resultCode)) {
+ QueryTokenForMnsQueueResponse.MessageTokenDTO dto = response
+ .getMessageTokenDTO();
+ TokenForAlicom token = new TokenForAlicom();
+ String timeStr = dto.getExpireTime();
+ token.setMessageType(messageType);
+ token.setExpireTime(df.parse(timeStr).getTime());
+ token.setToken(dto.getSecurityToken());
+ token.setTempAccessKeyId(dto.getAccessKeyId());
+ token.setTempAccessKeySecret(dto.getAccessKeySecret());
+ return token;
+ }
+ else {
+ logger.error("getTokenFromRemote_error,messageType:" + messageType + ",code:"
+ + response.getCode() + ",message:" + response.getMessage());
+ throw new ServerException(response.getCode(), response.getMessage());
+ }
+ }
+
+ public TokenForAlicom getTokenByMessageType(String messageType, String queueName,
+ String mnsAccountEndpoint)
+ throws ServerException, ClientException, ParseException {
+ TokenForAlicom token = tokenMap.get(messageType);
+ Long now = System.currentTimeMillis();
+ if (token == null || (token.getExpireTime() - now) < bufferTime) {// 过期时间小于2分钟则重新获取,防止服务器时间误差
+ synchronized (lock) {
+ token = tokenMap.get(messageType);
+ if (token == null || (token.getExpireTime() - now) < bufferTime) {
+ TokenForAlicom oldToken = null;
+ if (token != null) {
+ oldToken = token;
+ }
+ token = getTokenFromRemote(messageType);
+ // 因为换token时需要重建client和关闭老的client,所以创建client的代码和创建token放在一起
+ CloudAccount account = new CloudAccount(token.getTempAccessKeyId(),
+ token.getTempAccessKeySecret(), mnsAccountEndpoint,
+ token.getToken());
+ // logger.warn("ak:"+token.getTempAccessKey());
+ // logger.warn("token:"+token.getToken());
+ MNSClient client = account.getMNSClient();
+ CloudQueue queue = client.getQueueRef(queueName);
+ token.setClient(client);
+ token.setQueue(queue);
+ tokenMap.put(messageType, token);
+ if (oldToken != null) {
+ oldToken.closeClient();
+ }
+ }
+ }
+ }
+ return token;
+ }
+}
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/config/SmsAutoConfiguration.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/config/SmsAutoConfiguration.java
new file mode 100644
index 000000000..12e1760ba
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/config/SmsAutoConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * 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.alicloud.sms.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alicloud.context.sms.SmsConfigProperties;
+import org.springframework.cloud.alicloud.sms.ISmsService;
+import org.springframework.cloud.alicloud.sms.SmsInitializerEventListener;
+import org.springframework.cloud.alicloud.sms.SmsServiceImpl;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+
+/**
+ * @author pbting
+ */
+@Configuration
+@EnableConfigurationProperties
+@ConditionalOnClass(value = SendSmsRequest.class)
+@ConditionalOnProperty(value = "spring.cloud.alicloud.sms.enable", matchIfMissing = true)
+public class SmsAutoConfiguration {
+
+ @Bean
+ public SmsServiceImpl smsService(SmsConfigProperties smsConfigProperties) {
+ return new SmsServiceImpl(smsConfigProperties);
+ }
+
+ @Bean
+ public SmsInitializerEventListener smsInitializePostListener(
+ SmsConfigProperties msConfigProperties, ISmsService smsService) {
+ return new SmsInitializerEventListener(msConfigProperties, smsService);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/EndpointManager.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/EndpointManager.java
new file mode 100644
index 000000000..3b807d08e
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/EndpointManager.java
@@ -0,0 +1,106 @@
+/*
+ * 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.alicloud.sms.endpoint;
+
+import com.aliyuncs.dysmsapi.model.v20170525.SendBatchSmsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ *
+ */
+public final class EndpointManager {
+
+ private final static int BACKLOG_SIZE = 20;
+
+ private final static ReentrantLock SEND_REENTRANT_LOCK = new ReentrantLock(true);
+ private final static ReentrantLock SEND_BATCH_REENTRANT_LOCK = new ReentrantLock(
+ true);
+
+ private final static LinkedBlockingQueue SEND_SMS_REQUESTS = new LinkedBlockingQueue(
+ BACKLOG_SIZE);
+ private final static LinkedBlockingQueue SEND_BATCH_SMS_REQUESTS = new LinkedBlockingQueue(
+ BACKLOG_SIZE);
+ private final static LinkedBlockingQueue RECEIVE_MESSAGE_ENTITIES = new LinkedBlockingQueue(
+ BACKLOG_SIZE);
+
+ public static void addSendSmsRequest(SendSmsRequest sendSmsRequest) {
+ if (SEND_SMS_REQUESTS.offer(sendSmsRequest)) {
+ return;
+ }
+ try {
+ SEND_REENTRANT_LOCK.lock();
+ SEND_SMS_REQUESTS.poll();
+ SEND_SMS_REQUESTS.offer(sendSmsRequest);
+ }
+ finally {
+ SEND_REENTRANT_LOCK.unlock();
+ }
+ }
+
+ public static void addSendBatchSmsRequest(SendBatchSmsRequest sendBatchSmsRequest) {
+ if (SEND_BATCH_SMS_REQUESTS.offer(sendBatchSmsRequest)) {
+ return;
+ }
+ try {
+ SEND_BATCH_REENTRANT_LOCK.lock();
+ SEND_BATCH_SMS_REQUESTS.poll();
+ SEND_BATCH_SMS_REQUESTS.offer(sendBatchSmsRequest);
+ }
+ finally {
+ SEND_BATCH_REENTRANT_LOCK.unlock();
+ }
+ }
+
+ public static void addReceiveMessageEntity(
+ ReceiveMessageEntity receiveMessageEntity) {
+ if (RECEIVE_MESSAGE_ENTITIES.offer(receiveMessageEntity)) {
+ return;
+ }
+ RECEIVE_MESSAGE_ENTITIES.poll();
+ RECEIVE_MESSAGE_ENTITIES.offer(receiveMessageEntity);
+ }
+
+ public static Map getSmsEndpointMessage() {
+ List sendSmsRequests = new LinkedList<>();
+ List sendBatchSmsRequests = new LinkedList<>();
+ List receiveMessageEntities = new LinkedList<>();
+ try {
+ SEND_REENTRANT_LOCK.lock();
+ SEND_BATCH_REENTRANT_LOCK.lock();
+ sendSmsRequests.addAll(SEND_SMS_REQUESTS);
+ sendBatchSmsRequests.addAll(SEND_BATCH_SMS_REQUESTS);
+ }
+ finally {
+ SEND_REENTRANT_LOCK.unlock();
+ SEND_BATCH_REENTRANT_LOCK.unlock();
+ }
+ receiveMessageEntities.addAll(RECEIVE_MESSAGE_ENTITIES);
+
+ Map endpointMessages = new HashMap<>();
+ endpointMessages.put("send-sms-request", sendSmsRequests);
+ endpointMessages.put("send-batch-sms-request", sendBatchSmsRequests);
+ endpointMessages.put("message-listener", receiveMessageEntities);
+
+ return endpointMessages;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/ReceiveMessageEntity.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/ReceiveMessageEntity.java
new file mode 100644
index 000000000..3e941c3c5
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/ReceiveMessageEntity.java
@@ -0,0 +1,60 @@
+/*
+ * 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.alicloud.sms.endpoint;
+
+import org.springframework.cloud.alicloud.sms.base.MessageListener;
+
+import java.io.Serializable;
+
+/**
+ * @author pbting
+ */
+public class ReceiveMessageEntity implements Serializable {
+ private String messageType;
+ private String queueName;
+ private MessageListener messageListener;
+
+ public ReceiveMessageEntity(String messageType, String queueName,
+ MessageListener messageListener) {
+ this.messageType = messageType;
+ this.queueName = queueName;
+ this.messageListener = messageListener;
+ }
+
+ public String getMessageType() {
+ return messageType;
+ }
+
+ public void setMessageType(String messageType) {
+ this.messageType = messageType;
+ }
+
+ public String getQueueName() {
+ return queueName;
+ }
+
+ public void setQueueName(String queueName) {
+ this.queueName = queueName;
+ }
+
+ public MessageListener getMessageListener() {
+ return messageListener;
+ }
+
+ public void setMessageListener(MessageListener messageListener) {
+ this.messageListener = messageListener;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpoint.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpoint.java
new file mode 100644
index 000000000..d254e0ebe
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpoint.java
@@ -0,0 +1,31 @@
+/*
+ * 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.alicloud.sms.endpoint;
+
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+
+import java.util.Map;
+
+@Endpoint(id = "sms-info")
+public class SmsEndpoint {
+
+ @ReadOperation
+ public Map invoke() {
+
+ return EndpointManager.getSmsEndpointMessage();
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpointAutoConfiguration.java b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpointAutoConfiguration.java
new file mode 100644
index 000000000..1db0ec254
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/java/org/springframework/cloud/alicloud/sms/endpoint/SmsEndpointAutoConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ * 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.alicloud.sms.endpoint;
+
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.context.annotation.Bean;
+
+@ConditionalOnWebApplication
+@ConditionalOnClass(Endpoint.class)
+public class SmsEndpointAutoConfiguration {
+
+ @Bean
+ public SmsEndpoint smsEndpoint() {
+ return new SmsEndpoint();
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alicloud-sms/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-sms/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..875d39db0
--- /dev/null
+++ b/spring-cloud-alicloud-sms/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ org.springframework.cloud.alicloud.sms.config.SmsAutoConfiguration,\
+ org.springframework.cloud.alicloud.sms.endpoint.SmsEndpointAutoConfiguration
\ No newline at end of file
diff --git a/spring-cloud-starter-alicloud/pom.xml b/spring-cloud-starter-alicloud/pom.xml
index 5427b6eca..df47cfbbd 100644
--- a/spring-cloud-starter-alicloud/pom.xml
+++ b/spring-cloud-starter-alicloud/pom.xml
@@ -15,5 +15,6 @@
spring-cloud-starter-alicloud-acm
spring-cloud-starter-alicloud-ans
spring-cloud-starter-alicloud-schedulerx
+ spring-cloud-starter-alicloud-sms
\ No newline at end of file
diff --git a/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-sms/pom.xml b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-sms/pom.xml
new file mode 100644
index 000000000..57a398f76
--- /dev/null
+++ b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-sms/pom.xml
@@ -0,0 +1,20 @@
+
+ 4.0.0
+
+
+ org.springframework.cloud
+ spring-cloud-starter-alicloud
+ 0.2.2.BUILD-SNAPSHOT
+
+ spring-cloud-starter-alicloud-sms
+ Spring Cloud Starter Alibaba Cloud SMS
+
+
+
+ org.springframework.cloud
+ spring-cloud-alicloud-sms
+
+
+
+