mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge pull request #254 from pbting/master
ans starter suport eureka/consule registry and add sms module
This commit is contained in:
commit
937093da80
2
pom.xml
2
pom.xml
@ -101,6 +101,7 @@
|
||||
<module>spring-cloud-alicloud-acm</module>
|
||||
<module>spring-cloud-alicloud-ans</module>
|
||||
<module>spring-cloud-alicloud-schedulerx</module>
|
||||
<module>spring-cloud-alicloud-sms</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
@ -188,6 +189,7 @@
|
||||
<format>html</format>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
<check/>
|
||||
<check />
|
||||
<instrumentation>
|
||||
<excludes>
|
||||
|
@ -28,6 +28,10 @@
|
||||
<aliyun.sdk.edas.version>2.16.0</aliyun.sdk.edas.version>
|
||||
<rocketmq.version>4.3.1</rocketmq.version>
|
||||
<schedulerX.client.version>2.1.6</schedulerX.client.version>
|
||||
<aliyun.java.sdk.dysmsapi>1.1.0</aliyun.java.sdk.dysmsapi>
|
||||
<aliyun.sdk.mns>1.1.8</aliyun.sdk.mns>
|
||||
<aliyun.java.sdk.dysmsapi>1.1.0</aliyun.java.sdk.dysmsapi>
|
||||
<aliyun.java.sdk.dyvmsapi>1.1.1</aliyun.java.sdk.dyvmsapi>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@ -71,6 +75,19 @@
|
||||
<version>${schedulerX.client.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SMS -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.mns</groupId>
|
||||
<artifactId>aliyun-sdk-mns</artifactId>
|
||||
<version>${aliyun.sdk.mns}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
<version>${aliyun.java.sdk.dysmsapi}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Nacos-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
@ -213,6 +230,11 @@
|
||||
<artifactId>spring-cloud-alicloud-schedulerx</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alicloud-sms</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alicloud-context</artifactId>
|
||||
@ -283,6 +305,13 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SMS -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alicloud-sms</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing Dependencies -->
|
||||
|
||||
</dependencies>
|
||||
|
37
spring-cloud-alibaba-examples/env-extension/pom.xml
Normal file
37
spring-cloud-alibaba-examples/env-extension/pom.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.6.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>alibaba.com</groupId>
|
||||
<artifactId>env-extension</artifactId>
|
||||
<version>0.2.2.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>env-extension</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--Spring Boot -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,12 @@
|
||||
package org.springframework.alicloud.env.extension;
|
||||
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ImportExtraConfig {
|
||||
|
||||
String[] name() default "";
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.alicloud.env.extension;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author pbting
|
||||
* @date 2019-01-09 9:00 PM
|
||||
*/
|
||||
public class LoadExtraConfigApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
|
||||
SpringApplication springApplication = event.getSpringApplication();
|
||||
Class clazz = springApplication.getMainApplicationClass();
|
||||
if (!clazz.isAnnotationPresent(ImportExtraConfig.class)) {
|
||||
return;
|
||||
}
|
||||
ImportExtraConfig annotation = (ImportExtraConfig) clazz
|
||||
.getAnnotation(ImportExtraConfig.class);
|
||||
|
||||
String[] extraConfig = annotation.name();
|
||||
|
||||
if (extraConfig == null || extraConfig.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String config : extraConfig) {
|
||||
try {
|
||||
Properties properties = new Properties();
|
||||
properties.load(new FileInputStream(config));
|
||||
event.getEnvironment().getPropertySources()
|
||||
.addFirst(new PropertiesPropertySource(config, properties));
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
org.springframework.context.ApplicationListener=\
|
||||
org.springframework.alicloud.env.extension.LoadExtraConfigApplicationListener
|
@ -23,6 +23,7 @@
|
||||
<module>sentinel-example/sentinel-dubbo-example/sentinel-dubbo-api</module>
|
||||
<module>nacos-example/nacos-discovery-example</module>
|
||||
<module>nacos-example/nacos-config-example</module>
|
||||
<module>env-extension</module>
|
||||
<module>oss-example</module>
|
||||
<module>ans-example/ans-consumer-feign-example</module>
|
||||
<module>ans-example/ans-consumer-ribbon-example</module>
|
||||
|
79
spring-cloud-alibaba-examples/sms-example/pom.xml
Normal file
79
spring-cloud-alibaba-examples/sms-example/pom.xml
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>alibaba.com</groupId>
|
||||
<artifactId>sms-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>sms-example</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.6.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
|
||||
<spring-cloud-alibaba-alicloud.version>0.2.2.BUILD-SNAPSHOT</spring-cloud-alibaba-alicloud.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||
<version>${spring-cloud-alibaba-alicloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!--Spring Boot -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alicloud-sms</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>alibaba.com</groupId>
|
||||
<artifactId>env-extension</artifactId>
|
||||
<version>0.2.2.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.alicloud.env.extension.ImportExtraConfig;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ImportExtraConfig(name = "/Users/toava/sms.properties")
|
||||
public class SmsApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
SpringApplication.run(SmsApplication.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
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.core.env.Environment;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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 Environment environment;
|
||||
|
||||
@Autowired
|
||||
private ISmsService smsService;
|
||||
|
||||
@Autowired
|
||||
private SmsReportMessageListener smsReportMessageListener;
|
||||
|
||||
@GetMapping("/report-queue.do")
|
||||
public String getSmsReportQueuename(){
|
||||
|
||||
return environment.getProperty("spring.cloud.alicloud.sms.up-queue-name");
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信发送 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<Message> smsReport() {
|
||||
|
||||
return smsReportMessageListener.getSmsReportMessageSet();
|
||||
}
|
||||
}
|
@ -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<Message> smsReportMessageSet = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public boolean dealMessage(Message message) {
|
||||
smsReportMessageSet.add(message);
|
||||
System.err.println(this.getClass().getName() + "; " + message.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Message> getSmsReportMessageSet() {
|
||||
|
||||
return smsReportMessageSet;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
spring.application.name=sca-sms-example
|
||||
server.port=9051
|
||||
# config management
|
||||
management.endpoints.web.exposure.include=*
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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<String> 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] + ",");
|
||||
|
@ -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<ApplicationReadyEvent>, 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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<String> getServices() {
|
||||
|
||||
Set<String> publishers = NamingService.getPublishes();
|
||||
Set<String> doms = NamingService.getDomsSubscribed();
|
||||
doms.addAll(publishers);
|
||||
List<String> result = new LinkedList<>();
|
||||
for (String service : doms) {
|
||||
result.add(service);
|
||||
|
@ -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)
|
||||
|
@ -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<String, Object> invoke() {
|
||||
Map<String, Object> ansEndpoint = new HashMap<>();
|
||||
LOGGER.info("ANS endpoint invoke, ansProperties is {}", ansProperties);
|
||||
log.info("ANS endpoint invoke, ansProperties is " + ansProperties);
|
||||
ansEndpoint.put("ansProperties", ansProperties);
|
||||
|
||||
Map<String, Object> 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;
|
||||
}
|
||||
|
||||
|
@ -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<String, ConcurrentMap<String, ServerWrapper>> invoke() {
|
||||
|
||||
Map<String, ConcurrentMap<String, ServerWrapper>> result = ServerListInvocationHandler
|
||||
.getServerRegistry();
|
||||
|
||||
log.info("migrate server list :" + result);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.springframework.cloud.alicloud.ans.migrate;
|
||||
|
||||
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;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnClass(value = Endpoint.class)
|
||||
@Conditional(MigrateOnConditionClass.class)
|
||||
public class MigrateEndpointAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public MigrateEndpoint ansEndpoint() {
|
||||
return new MigrateEndpoint();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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 match is :" + result);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -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 match is :" + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package org.springframework.cloud.alicloud.ans.migrate;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* @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<String> SERVICES_ID = new ConcurrentSkipListSet<>();
|
||||
|
||||
private static Object springProxyFactory(Object target, ClassLoader classLoader,
|
||||
List<Advice> 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,
|
||||
final IClientConfig clientConfig) {
|
||||
|
||||
bean = springProxyFactory(bean, classLoader,
|
||||
Arrays.asList(new AfterReturningAdvice() {
|
||||
private final IClientConfig iclientConfig = clientConfig;
|
||||
|
||||
@Override
|
||||
public void afterReturning(Object returnValue, Method method,
|
||||
Object[] args, Object target) {
|
||||
String methodName = method.getName();
|
||||
if ("chooseServer".equals(methodName)) {
|
||||
String serviceId = iclientConfig.getClientName();
|
||||
Server server = (Server) returnValue;
|
||||
server = ServerListInvocationHandler
|
||||
.checkAndGetServiceServer(serviceId, server);
|
||||
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<String> getServicesId() {
|
||||
|
||||
return Collections.unmodifiableSet(SERVICES_ID);
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package org.springframework.cloud.alicloud.ans.migrate;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
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 com.netflix.loadbalancer.ILoadBalancer;
|
||||
|
||||
/**
|
||||
* @author pbting
|
||||
*/
|
||||
@Component
|
||||
public class MigrateRefreshEventListener implements ApplicationListener<RefreshEvent> {
|
||||
|
||||
private final static int CHECK_INTERVAL = 1;
|
||||
|
||||
private final static String MIGRATE_SWITCH = "spring.cloud.alicloud.migrate.ans.switch";
|
||||
|
||||
private volatile String lastScaMigrateAnsSwitchValue = "true";
|
||||
|
||||
private Environment environment;
|
||||
|
||||
private NamedContextFactory namedContextFactory;
|
||||
|
||||
public MigrateRefreshEventListener(Environment environment,
|
||||
NamedContextFactory namedContextFactory) {
|
||||
this.environment = environment;
|
||||
this.namedContextFactory = namedContextFactory;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void initTimerCheck() {
|
||||
Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(
|
||||
() -> onApplicationEvent(null), CHECK_INTERVAL, CHECK_INTERVAL,
|
||||
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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.springframework.cloud.alicloud.ans.migrate;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
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.cloud.context.named.NamedContextFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MigrateRefreshEventListener migrateRefreshEventListener(
|
||||
Environment environment,
|
||||
@Qualifier(value = "springClientFactory") NamedContextFactory namedContextFactory) {
|
||||
|
||||
return new MigrateRefreshEventListener(environment, namedContextFactory);
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
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<String, AnsServerList> SERVER_LIST_CONCURRENT_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private final static ConcurrentMap<String, ConcurrentMap<String, ServerWrapper>> CALL_SERVICE_COUNT = new ConcurrentHashMap<>();
|
||||
|
||||
private final static Set<String> 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());
|
||||
SERVER_LIST_CONCURRENT_MAP.put(ansServerList.getDom(), ansServerList);
|
||||
}
|
||||
|
||||
@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<Server> serverList = (List<Server>) 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<Server> mergeAnsServerList(final List<Server> source) {
|
||||
if (isFirst.compareAndSet(false, true)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// step 1: get all of server list and filter the alive
|
||||
List<AnsServer> 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<Server> serverIterator = source.iterator();
|
||||
while (serverIterator.hasNext()) {
|
||||
final Server server = serverIterator.next();
|
||||
ansServerList.forEach(ansServer -> {
|
||||
if (server.getHostPort()
|
||||
.equals(ansServer.getHealthService().toInetAddr())) {
|
||||
// by: ZoneAffinityPredicate
|
||||
serverIterator.remove();
|
||||
log.info("Source Server is remove " + server.getHostPort()
|
||||
+ ", and from ANS Server is override:"
|
||||
+ ansServer.toString());
|
||||
}
|
||||
// fix bug: mast be set the zone, update server list,will filter
|
||||
ansServer.setZone(server.getZone());
|
||||
ansServer.setSchemea(server.getScheme());
|
||||
ansServer.setId(ansServer.getHealthService().toInetAddr());
|
||||
ansServer.setReadyToServe(true);
|
||||
});
|
||||
}
|
||||
|
||||
ansServerList.forEach(ansServer -> source.add(ansServer));
|
||||
log.info("[" + this.clientConfig.getClientName() + "] "
|
||||
+ "; loadbalancer server list override after:" + source);
|
||||
// override
|
||||
return source;
|
||||
}
|
||||
|
||||
private List<AnsServer> filterAliveAnsServer(List<AnsServer> sourceServerList) {
|
||||
final List<AnsServer> 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<String, ConcurrentMap<String, ServerWrapper>> getServerRegistry() {
|
||||
|
||||
return Collections.unmodifiableMap(CALL_SERVICE_COUNT);
|
||||
}
|
||||
|
||||
static Server checkAndGetServiceServer(String serviceId, Server server) {
|
||||
if (server != null) {
|
||||
return server;
|
||||
}
|
||||
|
||||
log.warn(String.format("[%s] refers the server is null", server));
|
||||
|
||||
List<AnsServer> ansServerList = SERVER_LIST_CONCURRENT_MAP.get(serviceId)
|
||||
.getInitialListOfServers();
|
||||
|
||||
if (!ansServerList.isEmpty()) {
|
||||
return ansServerList.get(0);
|
||||
}
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
static void incrementCallService(String serviceId, Server server) {
|
||||
ConcurrentMap<String, ServerWrapper> 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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<AnsRegistration> {
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(AnsAutoServiceRegistration.class);
|
||||
private static final Log log = LogFactory.getLog(AnsAutoServiceRegistration.class);
|
||||
|
||||
@Autowired
|
||||
private AnsRegistration registration;
|
||||
@ -65,7 +64,7 @@ public class AnsAutoServiceRegistration
|
||||
@Override
|
||||
protected void register() {
|
||||
if (!this.registration.getAnsProperties().isRegisterEnabled()) {
|
||||
LOGGER.debug("Registration disabled.");
|
||||
log.debug("Registration disabled.");
|
||||
return;
|
||||
}
|
||||
if (this.registration.getPort() < 0) {
|
||||
|
@ -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
|
||||
|
@ -16,24 +16,23 @@
|
||||
|
||||
package org.springframework.cloud.alicloud.ans.registry;
|
||||
|
||||
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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||
|
||||
import com.alibaba.ans.core.NamingService;
|
||||
import com.alibaba.ans.shaded.com.taobao.vipserver.client.ipms.NodeReactor;
|
||||
|
||||
/**
|
||||
* @author xiaolongzuo
|
||||
*/
|
||||
public class AnsServiceRegistry implements ServiceRegistry<AnsRegistration> {
|
||||
|
||||
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<AnsRegistration> {
|
||||
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<AnsRegistration> {
|
||||
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<AnsRegistration> {
|
||||
@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<AnsRegistration> {
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
@ -16,19 +16,21 @@
|
||||
|
||||
package org.springframework.cloud.alicloud.ans.ribbon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.ans.core.NamingService;
|
||||
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.AbstractServerList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xiaolongzuo
|
||||
*/
|
||||
public class AnsServerList extends AbstractServerList<AnsServer> {
|
||||
|
||||
private final static int CONNECT_TIME_OUT = 3;
|
||||
|
||||
private String dom;
|
||||
|
||||
public AnsServerList(String dom) {
|
||||
@ -60,10 +62,12 @@ public class AnsServerList extends AbstractServerList<AnsServer> {
|
||||
List<AnsServer> result = new ArrayList<AnsServer>(hosts.size());
|
||||
for (Host host : hosts) {
|
||||
if (host.isValid()) {
|
||||
result.add(hostToServer(host));
|
||||
AnsServer ansServer = hostToServer(host);
|
||||
if (ansServer.isAlive(CONNECT_TIME_OUT)) {
|
||||
result.add(ansServer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
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.cloud.alicloud.ans.AnsDiscoveryClientAutoConfiguration
|
@ -50,6 +50,12 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.ans</groupId>
|
||||
<artifactId>ans-sdk</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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,\
|
||||
|
83
spring-cloud-alicloud-sms/pom.xml
Normal file
83
spring-cloud-alicloud-sms/pom.xml
Normal file
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba</artifactId>
|
||||
<version>0.2.2.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alicloud-sms</artifactId>
|
||||
<name>Spring Cloud Alibaba Cloud SMS</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alicloud-context</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- sms -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun.mns</groupId>
|
||||
<artifactId>aliyun-sdk-mns</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-actuator</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -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<String, IAcsClient> 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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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<ApplicationStartedEvent> {
|
||||
|
||||
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<MessageListener> 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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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<String, Object> sLockObjMap = new HashMap<String, Object>();
|
||||
protected static Map<String, Boolean> sPollingMap = new ConcurrentHashMap<String, Boolean>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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<QueryTokenForMnsQueueResponse> {
|
||||
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<QueryTokenForMnsQueueResponse> getResponseClass() {
|
||||
return QueryTokenForMnsQueueResponse.class;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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<String, TokenForAlicom> tokenMap = new ConcurrentHashMap<String, TokenForAlicom>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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<SendSmsRequest> SEND_SMS_REQUESTS = new LinkedBlockingQueue(
|
||||
BACKLOG_SIZE);
|
||||
private final static LinkedBlockingQueue<SendBatchSmsRequest> SEND_BATCH_SMS_REQUESTS = new LinkedBlockingQueue(
|
||||
BACKLOG_SIZE);
|
||||
private final static LinkedBlockingQueue<ReceiveMessageEntity> 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<String, Object> getSmsEndpointMessage() {
|
||||
List<SendSmsRequest> sendSmsRequests = new LinkedList<>();
|
||||
List<SendBatchSmsRequest> sendBatchSmsRequests = new LinkedList<>();
|
||||
List<ReceiveMessageEntity> 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<String, Object> endpointMessages = new HashMap<>();
|
||||
endpointMessages.put("send-sms-request", sendSmsRequests);
|
||||
endpointMessages.put("send-batch-sms-request", sendBatchSmsRequests);
|
||||
endpointMessages.put("message-listener", receiveMessageEntities);
|
||||
|
||||
return endpointMessages;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<String, Object> invoke() {
|
||||
|
||||
return EndpointManager.getSmsEndpointMessage();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.alicloud.sms.config.SmsAutoConfiguration,\
|
||||
org.springframework.cloud.alicloud.sms.endpoint.SmsEndpointAutoConfiguration
|
@ -15,5 +15,6 @@
|
||||
<module>spring-cloud-starter-alicloud-acm</module>
|
||||
<module>spring-cloud-starter-alicloud-ans</module>
|
||||
<module>spring-cloud-starter-alicloud-schedulerx</module>
|
||||
<module>spring-cloud-starter-alicloud-sms</module>
|
||||
</modules>
|
||||
</project>
|
@ -0,0 +1,20 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alicloud</artifactId>
|
||||
<version>0.2.2.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-starter-alicloud-sms</artifactId>
|
||||
<name>Spring Cloud Starter Alibaba Cloud SMS</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-alicloud-sms</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
Loading…
x
Reference in New Issue
Block a user