closes #63, closes #64, closes #65, closes #66.

pull/67/head
chenzhu.zxl 6 years ago
parent 591350d7e0
commit 7126a8ce33

@ -47,6 +47,10 @@
<name>fangjian</name>
<email>fangjian0423@gmail.com</email>
</developer>
<developer>
<name>xiaolongzuo</name>
<email>150349407@qq.com</email>
</developer>
<developer>
<name>hengyunabc</name>
<email>hengyunabc@gmail.com</email>
@ -82,6 +86,9 @@
<module>spring-cloud-starter-alibaba</module>
<module>spring-cloud-starter-alicloud</module>
<module>spring-cloud-alicloud-oss</module>
<module>spring-cloud-alicloud-context</module>
<module>spring-cloud-alicloud-acm</module>
<module>spring-cloud-alicloud-ans</module>
</modules>
<dependencyManagement>

@ -19,11 +19,47 @@
<sentinel.version>0.2.0</sentinel.version>
<oss.version>3.1.0</oss.version>
<nacos.version>0.3.0-RC1</nacos.version>
<acm.version>1.0.8</acm.version>
<ans.version>0.1.1</ans.version>
<aliyun.sdk.version>4.0.1</aliyun.sdk.version>
<alicloud.context.version>1.0.0</alicloud.context.version>
<aliyun.sdk.edas.version>2.16.0</aliyun.sdk.edas.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>alicloud-context</artifactId>
<version>${alicloud.context.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-edas</artifactId>
<version>${aliyun.sdk.edas.version}</version>
<exclusions>
<exclusion>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${aliyun.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.ans</groupId>
<artifactId>ans-sdk</artifactId>
<version>${ans.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.edas.acm</groupId>
<artifactId>acm-sdk</artifactId>
<version>${acm.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
@ -115,6 +151,21 @@
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-acm</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-ans</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-context</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Own dependencies - Starters -->
<dependency>
@ -140,9 +191,17 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Testing Dependencies -->

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>acm-local-example</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author xiaolongzuo
*/
@SpringBootApplication
@EnableDiscoveryClient
public class AcmApplication {
public static void main(String[] args) {
SpringApplication.run(AcmApplication.class, args);
}
}

@ -0,0 +1,41 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xiaolongzuo
*/
@RestController
public class EchoController {
private static final Logger LOGGER = LoggerFactory.getLogger(EchoController.class);
@Value("${user.id}")
private String userId;
@RequestMapping(value = "/")
public String echo() {
LOGGER.info("User id is " + userId);
return userId;
}
}

@ -0,0 +1,6 @@
spring.application.group=com.alibaba.acm
spring.application.name=acm-local
server.port=18089
spring.cloud.alicloud.acm.server-list=127.0.0.1
spring.cloud.alicloud.acm.server-port=8080

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ans-consumer-feign-example</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @author xiaolongzuo
*/
@SpringBootApplication
@EnableFeignClients(basePackages = {"org.springframework.cloud.alibaba.cloud.examples"})
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}

@ -0,0 +1,32 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author xiaolongzuo
*/
@FeignClient(value = "ans-provider")
public interface EchoService {
@RequestMapping(path = "echo/{str}")
String echo(@RequestParam("str") String param);
}

@ -0,0 +1,46 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xiaolongzuo
*/
@RestController
public class HomeController {
private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);
@Autowired
private EchoService echoService;
@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/json")
public String home() {
LOGGER.info("-----------------consumer调用开始-----------------");
String param = "Nice to meet you.";
LOGGER.info("消费者传递参数:" + param);
String result = echoService.echo(param);
LOGGER.info("收到提供者响应:" + result);
return param + "<br>" + result;
}
}

@ -0,0 +1,4 @@
server.port=18083
# The following configuration can be omitted.
spring.cloud.ans.server.list=127.0.0.1
spring.cloud.ans.server.port=8080

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ans-consumer-ribbon-example</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,43 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @author xiaolongzuo
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}

@ -0,0 +1,47 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author xiaolongzuo
*/
@RestController
public class HomeController {
private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/json")
public String home() {
LOGGER.info("-----------------consumer调用开始-----------------");
String param = "Nice to meet you.";
LOGGER.info("消费者传递参数:" + param);
String result = restTemplate.getForObject("http://ans-provider/echo/" + param, String.class);
LOGGER.info("收到提供者响应:" + result);
return param + "<br>" + result;
}
}

@ -0,0 +1,4 @@
server.port=18082
# The following configuration can be omitted.
spring.cloud.ans.server.list=127.0.0.1
spring.cloud.ans.server.port=8080

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ans-provider-example</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,42 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xiaolongzuo
*/
@RestController
public class EchoController {
private static final Logger LOGGER = LoggerFactory.getLogger(EchoController.class);
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET, produces = "application/json")
public String echo(@PathVariable String str) {
LOGGER.info("-----------收到消费者请求-----------");
LOGGER.info("收到消费者传递的参数:" + str);
String result = "Nice to meet you, too.";
LOGGER.info("提供者返回结果:" + result);
return result;
}
}

@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author xiaolongzuo
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}

@ -1,7 +1,6 @@
package org.springframework.cloud.alibaba.cloud.examples;
import java.net.URISyntaxException;
import com.aliyun.oss.OSS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
@ -9,7 +8,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.aliyun.oss.OSS;
import java.net.URISyntaxException;
/**
* OSS Application
@ -17,35 +16,34 @@ import com.aliyun.oss.OSS;
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@SpringBootApplication
public class OSSApplication {
public static final String BUCKET_NAME = "spring-cloud-alibaba";
public static void main(String[] args) throws URISyntaxException {
SpringApplication.run(OSSApplication.class, args);
}
@Bean
public AppRunner appRunner() {
return new AppRunner();
}
class AppRunner implements ApplicationRunner {
@Autowired
private OSS ossClient;
@Override
public void run(ApplicationArguments args) throws Exception {
try {
if (!ossClient.doesBucketExist(BUCKET_NAME)) {
ossClient.createBucket(BUCKET_NAME);
}
}
catch (Exception e) {
System.err.println("oss handle bucket error: " + e.getMessage());
System.exit(-1);
}
}
}
public class OssApplication {
public static final String BUCKET_NAME = "spring-cloud-alibaba-test";
public static void main(String[] args) throws URISyntaxException {
SpringApplication.run(OssApplication.class, args);
}
@Bean
public AppRunner appRunner() {
return new AppRunner();
}
class AppRunner implements ApplicationRunner {
@Autowired
private OSS ossClient;
@Override
public void run(ApplicationArguments args) throws Exception {
try {
if (!ossClient.doesBucketExist(BUCKET_NAME)) {
ossClient.createBucket(BUCKET_NAME);
}
} catch (Exception e) {
System.err.println("oss handle bucket error: " + e.getMessage());
System.exit(-1);
}
}
}
}

@ -1,7 +1,8 @@
package org.springframework.cloud.alibaba.cloud.examples;
import java.nio.charset.Charset;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.model.OSSObject;
import org.apache.commons.codec.CharEncoding;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -10,9 +11,7 @@ import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.model.OSSObject;
import java.nio.charset.Charset;
/**
* OSS Controller
@ -20,53 +19,47 @@ import com.aliyun.oss.model.OSSObject;
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@RestController
public class OSSController {
@Autowired
private OSS ossClient;
public class OssController {
@Value("oss://" + OSSApplication.BUCKET_NAME + "/oss-test")
private Resource file;
@Autowired
private OSS ossClient;
private String dir = "custom-dir/";
@Value("oss://" + OssApplication.BUCKET_NAME + "/oss-test.json")
private Resource file;
@GetMapping("/upload")
public String upload() {
try {
ossClient.putObject(OSSApplication.BUCKET_NAME, dir + "oss-test", this
.getClass().getClassLoader().getResourceAsStream("oss-test.json"));
}
catch (Exception e) {
e.printStackTrace();
return "upload fail: " + e.getMessage();
}
return "upload success";
}
@GetMapping("/upload")
public String upload() {
try {
ossClient.putObject(OssApplication.BUCKET_NAME, "oss-test.json", this
.getClass().getClassLoader().getResourceAsStream("oss-test.json"));
} catch (Exception e) {
e.printStackTrace();
return "upload fail: " + e.getMessage();
}
return "upload success";
}
@GetMapping("/file-resource")
public String fileResource() {
try {
return "get file resource success. content: " + StreamUtils.copyToString(
file.getInputStream(), Charset.forName(CharEncoding.UTF_8));
}
catch (Exception e) {
e.printStackTrace();
return "get resource fail: " + e.getMessage();
}
}
@GetMapping("/file-resource")
public String fileResource() {
try {
return "get file resource success. content: " + StreamUtils.copyToString(
file.getInputStream(), Charset.forName(CharEncoding.UTF_8));
} catch (Exception e) {
e.printStackTrace();
return "get resource fail: " + e.getMessage();
}
}
@GetMapping("/download")
public String download() {
try {
OSSObject ossObject = ossClient.getObject(OSSApplication.BUCKET_NAME,
dir + "oss-test");
return "download success, content: " + IOUtils
.readStreamAsString(ossObject.getObjectContent(), CharEncoding.UTF_8);
}
catch (Exception e) {
e.printStackTrace();
return "download fail: " + e.getMessage();
}
}
@GetMapping("/download")
public String download() {
try {
OSSObject ossObject = ossClient.getObject(OssApplication.BUCKET_NAME, "oss-test.json");
return "download success, content: " + IOUtils
.readStreamAsString(ossObject.getObjectContent(), CharEncoding.UTF_8);
} catch (Exception e) {
e.printStackTrace();
return "download fail: " + e.getMessage();
}
}
}

@ -1,8 +1,6 @@
spring.application.name=oss-example
server.port=18084
spring.cloud.alibaba.oss.accessKeyId=[your-ak]
spring.cloud.alibaba.oss.secretAccessKey=[your-sk]
spring.cloud.alibaba.oss.region=[your-region]
management.endpoints.web.exposure.include=*
spring.cloud.alicloud.access-key=AK
spring.cloud.alicloud.secret-key=SK
spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com
management.endpoints.web.exposure.include=*

@ -1,6 +1,3 @@
{
"name": "spring-cloud-alibaba",
"github": "https://github.com/spring-cloud-incubator/spring-cloud-alibaba",
"authors": ["Jim", "flystar32"],
"emails": ["fangjian0423@gmail.com", "flystar32@163.com"]
"name": "chenzhu-test"
}

@ -23,6 +23,10 @@
<module>nacos-example/nacos-discovery-example</module>
<module>nacos-example/nacos-config-example</module>
<module>oss-example</module>
<module>ans-example/ans-consumer-feign-example</module>
<module>ans-example/ans-consumer-ribbon-example</module>
<module>ans-example/ans-provider-example</module>
<module>acm-example/acm-local-example</module>
</modules>
<build>

@ -0,0 +1,71 @@
<?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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-alicloud-acm</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-context</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-edas</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.edas.acm</groupId>
<artifactId>acm-sdk</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,73 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm;
import com.taobao.diamond.client.Diamond;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alicloud.acm.endpoint.AcmHealthIndicator;
import org.springframework.cloud.alicloud.acm.refresh.AcmContextRefresher;
import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created on 01/10/2017.
*
* @author juven.xuxb
*/
@Configuration
@ConditionalOnClass({Diamond.class})
@EnableConfigurationProperties(AcmProperties.class)
public class AcmAutoConfiguration implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Bean
public AcmPropertySourceRepository acmPropertySourceRepository() {
return new AcmPropertySourceRepository(applicationContext);
}
@Bean
public AcmHealthIndicator acmHealthIndicator(AcmProperties acmProperties,
AcmPropertySourceRepository acmPropertySourceRepository) {
return new AcmHealthIndicator(acmProperties, acmPropertySourceRepository);
}
@Bean
public AcmRefreshHistory acmRefreshHistory() {
return new AcmRefreshHistory();
}
@Bean
public AcmContextRefresher acmContextRefresher(AcmProperties acmProperties, ContextRefresher contextRefresher,
AcmRefreshHistory refreshHistory,
AcmPropertySourceRepository propertySourceRepository) {
return new AcmContextRefresher(contextRefresher, acmProperties, refreshHistory, propertySourceRepository);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}

@ -0,0 +1,68 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm;
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.PropertySource;
import java.util.ArrayList;
import java.util.List;
/**
* @author juven.xuxb, 5/17/16.
*/
public class AcmPropertySourceRepository {
private final ApplicationContext applicationContext;
public AcmPropertySourceRepository(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/**
* get all acm properties from application context
* @return
*/
public List<AcmPropertySource> getAll() {
List<AcmPropertySource> result = new ArrayList<>();
ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) applicationContext;
for (PropertySource p : ctx.getEnvironment().getPropertySources()) {
if (p instanceof AcmPropertySource) {
result.add((AcmPropertySource) p);
}
else if (p instanceof CompositePropertySource) {
collectAcmPropertySources((CompositePropertySource) p, result);
}
}
return result;
}
private void collectAcmPropertySources(CompositePropertySource composite,
List<AcmPropertySource> result) {
for (PropertySource p : composite.getPropertySources()) {
if (p instanceof AcmPropertySource) {
result.add((AcmPropertySource) p);
}
else if (p instanceof CompositePropertySource) {
collectAcmPropertySources((CompositePropertySource) p, result);
}
}
}
}

@ -0,0 +1,55 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.bootstrap;
import org.springframework.core.env.MapPropertySource;
import java.util.Date;
import java.util.Map;
/**
* @author juven.xuxb
* @author xiaolongzuo
*/
public class AcmPropertySource extends MapPropertySource {
private final String dataId;
private final Date timestamp;
private final boolean groupLevel;
AcmPropertySource(String dataId, Map<String, Object> source, Date timestamp,
boolean groupLevel) {
super(dataId, source);
this.dataId = dataId;
this.timestamp = timestamp;
this.groupLevel = groupLevel;
}
public String getDataId() {
return dataId;
}
public Date getTimestamp() {
return timestamp;
}
public boolean isGroupLevel() {
return groupLevel;
}
}

@ -0,0 +1,96 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.bootstrap;
import com.alibaba.edas.acm.ConfigService;
import com.alibaba.edas.acm.exception.ConfigException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.util.StringUtils;
import java.io.StringReader;
import java.util.*;
/**
* @author juven.xuxb
* @author xiaolongzuo
*/
class AcmPropertySourceBuilder {
private Logger logger = LoggerFactory.getLogger(AcmPropertySourceBuilder.class);
/**
* ACM DataId groupID AcmProperty
*
* @param dataId
* @param diamondGroup
* @param groupLevel
* @return
*/
AcmPropertySource build(String dataId, String diamondGroup, boolean groupLevel) {
Properties properties = loadDiamondData(dataId, diamondGroup);
if (properties == null) {
return null;
}
return new AcmPropertySource(dataId, toMap(properties), new Date(), groupLevel);
}
private Properties loadDiamondData(String dataId, String diamondGroup) {
try {
String data = ConfigService.getConfig(dataId, diamondGroup, 3000L);
if (StringUtils.isEmpty(data)) {
return null;
}
if (dataId.endsWith(".properties")) {
Properties properties = new Properties();
logger.info(String.format("Loading acm data, dataId: '%s', group: '%s'",
dataId, diamondGroup));
properties.load(new StringReader(data));
return properties;
} else if (dataId.endsWith(".yaml") || dataId.endsWith(".yml")) {
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
yamlFactory.setResources(new ByteArrayResource(data.getBytes()));
return yamlFactory.getObject();
}
} catch (Exception e) {
if (e instanceof ConfigException) {
logger.error("DIAMOND-100500:" + dataId + ", " + e.toString(), e);
} else {
logger.error("DIAMOND-100500:" + dataId, e);
}
}
return null;
}
@SuppressWarnings("unchecked")
private Map<String, Object> toMap(Properties properties) {
Map<String, Object> result = new HashMap<>();
Enumeration<String> keys = (Enumeration<String>)properties.propertyNames();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
Object value = properties.getProperty(key);
if (value != null) {
result.put(key, ((String)value).trim());
} else {
result.put(key, null);
}
}
return result;
}
}

@ -0,0 +1,142 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.bootstrap;
import com.taobao.diamond.maintenance.DiamondHealth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alicloud.acm.diagnostics.analyzer.DiamondConnectionFailureException;
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
import static com.taobao.diamond.client.impl.ServerHttpAgent.addressPort;
import static com.taobao.diamond.client.impl.ServerHttpAgent.domainName;
/**
* @author juven.xuxb
* @author xiaolongzuo
*/
public class AcmPropertySourceLocator implements PropertySourceLocator {
private final Logger logger = LoggerFactory.getLogger(AcmPropertySourceLocator.class);
private static final String DIAMOND_PROPERTY_SOURCE_NAME = "diamond";
private static String defaultDiamondGroup = "DEFAULT_GROUP";
private AcmPropertySourceBuilder acmPropertySourceBuilder = new AcmPropertySourceBuilder();
@Autowired
private AcmProperties acmProperties;
@Override
public PropertySource<?> locate(Environment environment) {
checkDiamondHealth();
String applicationName = environment.getProperty("spring.application.name");
logger.info("Initialize spring.application.name '" + applicationName + "'.");
String applicationGroup = environment.getProperty("spring.application.group");
if (StringUtils.isEmpty(applicationName)) {
throw new IllegalStateException(
"'spring.application.name' must be configured.");
}
CompositePropertySource compositePropertySource = new CompositePropertySource(
DIAMOND_PROPERTY_SOURCE_NAME);
loadGroupConfigurationRecursively(compositePropertySource, applicationGroup);
loadApplicationConfiguration(compositePropertySource, environment,
applicationGroup, applicationName);
return compositePropertySource;
}
private void checkDiamondHealth() {
logger.info("Checking ACM health");
try {
if (!"UP".equals(DiamondHealth.getHealth())) {
throw new DiamondConnectionFailureException(domainName, addressPort,
DiamondHealth.getHealth());
}
}
catch (Throwable t) {
throw new DiamondConnectionFailureException(domainName, addressPort,
"ACM Health error", t);
}
}
private void loadGroupConfigurationRecursively(
CompositePropertySource compositePropertySource, String applicationGroup) {
if (StringUtils.isEmpty(applicationGroup)) {
return;
}
String[] parts = applicationGroup.split("\\.");
for (int i = 1; i < parts.length; i++) {
String subGroup = parts[0];
for (int j = 1; j <= i; j++) {
subGroup = subGroup + "." + parts[j];
}
String dataId = subGroup + ":application." + acmProperties.getFileExtension();
loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup,
true);
}
}
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, Environment environment,
String applicationGroup, String applicationName) {
if (!StringUtils.isEmpty(applicationGroup)) {
String dataId = applicationGroup + ":" + applicationName + "."
+ acmProperties.getFileExtension();
loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup,
false);
for (String profile : environment.getActiveProfiles()) {
dataId = applicationGroup + ":" + applicationName + "-" + profile + "."
+ acmProperties.getFileExtension();
loadDiamondDataIfPresent(compositePropertySource, dataId,
defaultDiamondGroup, false);
}
}
String dataId = applicationName + "." + acmProperties.getFileExtension();
loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup,
false);
for (String profile : environment.getActiveProfiles()) {
dataId = applicationName + "-" + profile + "."
+ acmProperties.getFileExtension();
loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup,
false);
}
}
private void loadDiamondDataIfPresent(final CompositePropertySource composite,
final String dataId, final String diamondGroup, final boolean groupLevel) {
AcmPropertySource ps = acmPropertySourceBuilder.build(dataId, diamondGroup,
groupLevel);
if (ps != null) {
composite.addFirstPropertySource(ps);
}
}
}

@ -0,0 +1,40 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.diagnostics.analyzer;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
/**
* A {@code FailureAnalyzer} that performs analysis of failures caused by a
* {@code DiamondConnectionFailureException}.
*
* @author juven.xuxb, 07/11/2016.
*/
public class DiamondConnectionFailureAnalyzer
extends AbstractFailureAnalyzer<DiamondConnectionFailureException> {
@Override
protected FailureAnalysis analyze(Throwable rootFailure,
DiamondConnectionFailureException cause) {
return new FailureAnalysis(
"Application failed to connect to Diamond, unable to access http://"
+ cause.getDomain() + ":" + cause.getPort()
+ "/diamond-server/diamond",
"config the right endpoint", cause);
}
}

@ -0,0 +1,52 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.diagnostics.analyzer;
/**
* A {@code DiamondConnectionFailureException} is thrown when the application fails to
* connect to Diamond Server.
*
* @author juven.xuxb, 07/11/2016.
*/
public class DiamondConnectionFailureException extends RuntimeException {
private final String domain;
private final String port;
public DiamondConnectionFailureException(String domain, String port, String message) {
super(message);
this.domain = domain;
this.port = port;
}
public DiamondConnectionFailureException(String domain, String port, String message,
Throwable cause) {
super(message, cause);
this.domain = domain;
this.port = port;
}
String getDomain() {
return domain;
}
String getPort() {
return port;
}
}

@ -0,0 +1,77 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.endpoint;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created on 01/10/2017.
*
* @author juven.xuxb
*/
@Endpoint(id = "acm")
public class AcmEndpoint {
private final AcmProperties properties;
private final AcmRefreshHistory refreshHistory;
private final AcmPropertySourceRepository propertySourceRepository;
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public AcmEndpoint(AcmProperties properties, AcmRefreshHistory refreshHistory,
AcmPropertySourceRepository propertySourceRepository) {
this.properties = properties;
this.refreshHistory = refreshHistory;
this.propertySourceRepository = propertySourceRepository;
}
@ReadOperation
public Map<String, Object> invoke() {
Map<String, Object> result = new HashMap<>();
result.put("config", properties);
Map<String, Object> runtime = new HashMap<>();
List<AcmPropertySource> all = propertySourceRepository.getAll();
List<Map<String, Object>> sources = new ArrayList<>();
for (AcmPropertySource ps : all) {
Map<String, Object> source = new HashMap<>();
source.put("dataId", ps.getDataId());
source.put("lastSynced", dateFormat.format(ps.getTimestamp()));
sources.add(source);
}
runtime.put("sources", sources);
runtime.put("refreshHistory", refreshHistory.getRecords());
result.put("runtime", runtime);
return result;
}
}

@ -0,0 +1,52 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.endpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
import org.springframework.context.annotation.Bean;
/**
* @author xiaojing
*/
@ConditionalOnWebApplication
@ConditionalOnClass(name = "org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration")
public class AcmEndpointAutoConfiguration {
@Autowired
private AcmProperties acmProperties;
@Autowired
private AcmRefreshHistory acmRefreshHistory;
@Autowired
private AcmPropertySourceRepository acmPropertySourceRepository;
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
@Bean
public AcmEndpoint acmEndpoint() {
return new AcmEndpoint(acmProperties, acmRefreshHistory,
acmPropertySourceRepository);
}
}

@ -0,0 +1,71 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.endpoint;
import com.alibaba.edas.acm.ConfigService;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author leijuan
* @author juven
*/
public class AcmHealthIndicator extends AbstractHealthIndicator {
private final AcmProperties acmProperties;
private final AcmPropertySourceRepository acmPropertySourceRepository;
private final List<String> dataIds;
public AcmHealthIndicator(AcmProperties acmProperties,
AcmPropertySourceRepository acmPropertySourceRepository) {
this.acmProperties = acmProperties;
this.acmPropertySourceRepository = acmPropertySourceRepository;
this.dataIds = new ArrayList<>();
for (AcmPropertySource acmPropertySource : this.acmPropertySourceRepository
.getAll()) {
this.dataIds.add(acmPropertySource.getDataId());
}
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
for (String dataId : dataIds) {
try {
String config = ConfigService.getConfig(dataId, acmProperties.getGroup(),
acmProperties.getTimeout());
if (StringUtils.isEmpty(config)) {
builder.down().withDetail(String.format("dataId: '%s', group: '%s'",
dataId, acmProperties.getGroup()), "config is empty");
}
} catch (Exception e) {
builder.down().withDetail(String.format("dataId: '%s', group: '%s'",
dataId, acmProperties.getGroup()), e.getMessage());
}
}
builder.up().withDetail("dataIds", dataIds);
}
}

@ -0,0 +1,125 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.refresh;
import com.alibaba.edas.acm.ConfigService;
import com.alibaba.edas.acm.listener.ConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* On application start up, AcmContextRefresher add diamond listeners to all application
* level dataIds, when there is a change in the data, listeners will refresh
* configurations.
*
* @author juven.xuxb, 5/13/16.
*/
public class AcmContextRefresher implements ApplicationListener<ApplicationReadyEvent> {
private Logger logger = LoggerFactory.getLogger(AcmContextRefresher.class);
private final ContextRefresher contextRefresher;
private final AcmProperties properties;
private final AcmRefreshHistory refreshHistory;
private final AcmPropertySourceRepository acmPropertySourceRepository;
private Map<String, ConfigChangeListener> listenerMap = new ConcurrentHashMap<>(16);
@Autowired
private Environment environment;
public AcmContextRefresher(ContextRefresher contextRefresher,
AcmProperties properties, AcmRefreshHistory refreshHistory,
AcmPropertySourceRepository acmPropertySourceRepository) {
this.contextRefresher = contextRefresher;
this.properties = properties;
this.refreshHistory = refreshHistory;
this.acmPropertySourceRepository = acmPropertySourceRepository;
}
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
this.registerDiamondListenersForApplications();
}
private void registerDiamondListenersForApplications() {
if (properties.isRefreshEnabled()) {
for (AcmPropertySource acmPropertySource : acmPropertySourceRepository
.getAll()) {
if (acmPropertySource.isGroupLevel()) {
continue;
}
String dataId = acmPropertySource.getDataId();
registerDiamondListener(dataId);
}
if (acmPropertySourceRepository.getAll().isEmpty()) {
String applicationName = environment
.getProperty("spring.application.name");
String dataId = applicationName + "." + properties.getFileExtension();
registerDiamondListener(dataId);
}
}
}
private void registerDiamondListener(final String dataId) {
ConfigChangeListener listener = listenerMap.computeIfAbsent(dataId,
i -> new ConfigChangeListener() {
@Override
public void receiveConfigInfo(String configInfo) {
String md5 = "";
if (!StringUtils.isEmpty(configInfo)) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md5 = new BigInteger(1,
md.digest(configInfo.getBytes("UTF-8")))
.toString(16);
}
catch (NoSuchAlgorithmException
| UnsupportedEncodingException e) {
logger.warn("unable to get md5 for dataId: " + dataId, e);
}
}
refreshHistory.add(dataId, md5);
contextRefresher.refresh();
}
});
ConfigService.addListener(dataId, properties.getGroup(), listener);
}
}

@ -0,0 +1,72 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm.refresh;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
/**
* @author juven.xuxb, 5/16/16.
*/
public class AcmRefreshHistory {
private static final int MAX_SIZE = 20;
private LinkedList<Record> records = new LinkedList<>();
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void add(String dataId, String md5) {
records.addFirst(new Record(dateFormat.format(new Date()), dataId, md5));
if (records.size() > MAX_SIZE) {
records.removeLast();
}
}
public LinkedList<Record> getRecords() {
return records;
}
}
class Record {
private final String timestamp;
private final String dataId;
private final String md5;
public Record(String timestamp, String dataId, String md5) {
this.timestamp = timestamp;
this.dataId = dataId;
this.md5 = md5;
}
public String getTimestamp() {
return timestamp;
}
public String getDataId() {
return dataId;
}
public String getMd5() {
return md5;
}
}

@ -0,0 +1,9 @@
{
"properties": [
{
"name": "spring.application.group",
"type": "java.lang.String",
"description": "spring application group."
}
]
}

@ -0,0 +1,9 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySourceLocator
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alicloud.acm.AcmAutoConfiguration,\
org.springframework.cloud.alicloud.acm.endpoint.AcmEndpointAutoConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.alicloud.acm.diagnostics.analyzer.DiamondConnectionFailureAnalyzer

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-ans</artifactId>
<name>Spring Cloud Alibaba Cloud ANS</name>
<dependencies>
<dependency>
<groupId>com.alibaba.ans</groupId>
<artifactId>ans-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-edas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<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.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-test-support</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,66 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.registry.AnsAutoServiceRegistration;
import org.springframework.cloud.alicloud.ans.registry.AnsRegistration;
import org.springframework.cloud.alicloud.ans.registry.AnsServiceRegistry;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaolongzuo
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(name = "org.springframework.boot.web.context.WebServerInitializedEvent")
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@ConditionalOnAnsEnabled
@AutoConfigureBefore({ AutoServiceRegistrationAutoConfiguration.class,
AnsDiscoveryClientAutoConfiguration.class })
public class AnsAutoConfiguration {
@Bean
public AnsServiceRegistry ansServiceRegistry() {
return new AnsServiceRegistry();
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public AnsRegistration ansRegistration() {
return new AnsRegistration();
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public AnsAutoServiceRegistration ansAutoServiceRegistration(
AnsServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
AnsRegistration registration) {
return new AnsAutoServiceRegistration(registry, autoServiceRegistrationProperties,
registration);
}
}

@ -0,0 +1,87 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans;
import java.util.*;
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;
/**
* @author xiaolongzuo
*/
public class AnsDiscoveryClient implements DiscoveryClient {
public static final String DESCRIPTION = "Spring Cloud ANS Discovery Client";
@Override
public String description() {
return DESCRIPTION;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
try {
List<Host> hosts = NamingService.getHosts(serviceId);
return hostToServiceInstanceList(hosts, serviceId);
}
catch (Exception e) {
throw new RuntimeException(
"Can not get hosts from ans server. serviceId: " + serviceId, e);
}
}
private static ServiceInstance hostToServiceInstance(Host host, String serviceId) {
AnsServiceInstance ansServiceInstance = new AnsServiceInstance();
ansServiceInstance.setHost(host.getIp());
ansServiceInstance.setPort(host.getPort());
ansServiceInstance.setServiceId(serviceId);
Map<String, String> metadata = new HashMap<String, String>(5);
metadata.put("appUseType", host.getAppUseType());
metadata.put("site", host.getSite());
metadata.put("unit", host.getUnit());
metadata.put("doubleWeight", "" + host.getDoubleWeight());
metadata.put("weight", "" + host.getWeight());
ansServiceInstance.setMetadata(metadata);
return ansServiceInstance;
}
private static List<ServiceInstance> hostToServiceInstanceList(List<Host> hosts,
String serviceId) {
List<ServiceInstance> result = new ArrayList<ServiceInstance>(hosts.size());
for (Host host : hosts) {
result.add(hostToServiceInstance(host, serviceId));
}
return result;
}
@Override
public List<String> getServices() {
Set<String> doms = NamingService.getDomsSubscribed();
List<String> result = new LinkedList<>();
for (String service : doms) {
result.add(service);
}
return result;
}
}

@ -0,0 +1,41 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.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.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaolongzuo
*/
@Configuration
@ConditionalOnMissingBean(DiscoveryClient.class)
@EnableConfigurationProperties
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
public class AnsDiscoveryClientAutoConfiguration {
@Bean
public DiscoveryClient ansDiscoveryClient() {
return new AnsDiscoveryClient();
}
}

@ -0,0 +1,90 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans;
import java.net.URI;
import java.util.Map;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
/**
* @author xiaolongzuo
*/
public class AnsServiceInstance implements ServiceInstance {
private String serviceId;
private String host;
private int port;
private boolean secure;
private Map<String, String> metadata;
@Override
public String getServiceId() {
return serviceId;
}
@Override
public String getHost() {
return host;
}
@Override
public int getPort() {
return port;
}
@Override
public boolean isSecure() {
return secure;
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return metadata;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}
}

@ -0,0 +1,33 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
/**
* @author xiaolongzuo
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(value = "spring.cloud.ans.enabled", matchIfMissing = true)
public @interface ConditionalOnAnsEnabled {
}

@ -0,0 +1,72 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.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 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;
/**
* @author xiaolongzuo
*/
@Endpoint(id = "ans")
public class AnsEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(AnsEndpoint.class);
private AnsProperties ansProperties;
public AnsEndpoint(AnsProperties ansProperties) {
this.ansProperties = ansProperties;
}
/**
* @return ans endpoint
*/
@ReadOperation
public Map<String, Object> invoke() {
Map<String, Object> ansEndpoint = new HashMap<>();
LOGGER.info("ANS endpoint invoke, ansProperties is {}", ansProperties);
ansEndpoint.put("ansProperties", ansProperties);
Map<String, Object> subscribes = new HashMap<>();
Set<String> subscribeServices = NamingService.getDomsSubscribed();
for (String service : subscribeServices) {
try {
List<Host> hosts = NamingService.getHosts(service);
subscribes.put(service, hosts);
}
catch (Exception ignoreException) {
}
}
ansEndpoint.put("subscribes", subscribes);
LOGGER.info("ANS endpoint invoke, subscribes is {}", subscribes);
return ansEndpoint;
}
}

@ -0,0 +1,36 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans.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.cloud.alicloud.context.ans.AnsProperties;
import org.springframework.context.annotation.Bean;
/**
* @author xiaolongzuo
*/
@ConditionalOnWebApplication
@ConditionalOnClass(Endpoint.class)
public class AnsEndpointAutoConfiguration {
@Bean
public AnsEndpoint ansEndpoint(AnsProperties ansProperties) {
return new AnsEndpoint(ansProperties);
}
}

@ -0,0 +1,103 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans.registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author xiaolongzuo
*/
public class AnsAutoServiceRegistration
extends AbstractAutoServiceRegistration<AnsRegistration> {
private static final Logger LOGGER = LoggerFactory
.getLogger(AnsAutoServiceRegistration.class);
@Autowired
private AnsRegistration registration;
public AnsAutoServiceRegistration(ServiceRegistry<AnsRegistration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
AnsRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
@Deprecated
public void setPort(int port) {
getPort().set(port);
}
@Override
protected AnsRegistration getRegistration() {
if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
this.registration.setPort(this.getPort().get());
}
Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
return this.registration;
}
@Override
protected AnsRegistration getManagementRegistration() {
return null;
}
@Override
protected void register() {
if (!this.registration.getAnsProperties().isRegisterEnabled()) {
LOGGER.debug("Registration disabled.");
return;
}
if (this.registration.getPort() < 0) {
this.registration.setPort(getPort().get());
}
super.register();
}
@Override
protected void registerManagement() {
if (!this.registration.getAnsProperties().isRegisterEnabled()) {
return;
}
super.registerManagement();
}
@Override
protected Object getConfiguration() {
return this.registration.getAnsProperties();
}
@Override
protected boolean isEnabled() {
return this.registration.getAnsProperties().isRegisterEnabled();
}
@Override
@SuppressWarnings("deprecation")
protected String getAppName() {
String appName = registration.getServiceId();
return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
}
}

@ -0,0 +1,131 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.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;
import org.springframework.cloud.client.discovery.ManagementServerPortUtils;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
/**
* @author xiaolongzuo
*/
public class AnsRegistration implements Registration, ServiceInstance {
private static final String MANAGEMENT_PORT = "management.port";
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;
@PostConstruct
public void init() {
Environment env = context.getEnvironment();
Integer managementPort = ManagementServerPortUtils.getPort(context);
if (null != managementPort) {
Map<String, String> metadata = ansProperties.getClientMetadata();
metadata.put(MANAGEMENT_PORT, managementPort.toString());
String contextPath = env
.getProperty("management.server.servlet.context-path");
String address = env.getProperty("management.server.address");
if (!StringUtils.isEmpty(contextPath)) {
metadata.put(MANAGEMENT_CONTEXT_PATH, contextPath);
}
if (!StringUtils.isEmpty(address)) {
metadata.put(MANAGEMENT_ADDRESS, address);
}
}
}
@Override
public String getServiceId() {
return ansProperties.getClientDomains();
}
@Override
public String getHost() {
return ansProperties.getClientIp();
}
@Override
public int getPort() {
return ansProperties.getClientPort();
}
public void setPort(int port) {
// if spring.cloud.ans.port is not set,use the port detected from context
if (ansProperties.getClientPort() < 0) {
this.ansProperties.setClientPort(port);
}
}
@Override
public boolean isSecure() {
return ansProperties.isSecure();
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return ansProperties.getClientMetadata();
}
public boolean isRegisterEnabled() {
return ansProperties.isRegisterEnabled();
}
public String getCluster() {
return ansProperties.getClientCluster();
}
public float getRegisterWeight(String dom) {
if (null != ansProperties.getClientWeights().get(dom)
&& ansProperties.getClientWeights().get(dom) > 0) {
return ansProperties.getClientWeights().get(dom);
}
return ansProperties.getClientWeight();
}
public AnsProperties getAnsProperties() {
return ansProperties;
}
@Override
public String toString() {
return "AnsRegistration{" + "ansProperties=" + ansProperties + '}';
}
}

@ -0,0 +1,114 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans.registry;
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 final String SEPARATOR = ",";
@Override
public void register(AnsRegistration registration) {
if (!registration.isRegisterEnabled()) {
logger.info("Registration is disabled...");
return;
}
if (StringUtils.isEmpty(registration.getServiceId())) {
logger.info("No service to register for client...");
return;
}
List<NodeReactor.Tag> tags = new ArrayList<>();
for (Map.Entry<String, String> entry : registration.getAnsProperties().getTags()
.entrySet()) {
NodeReactor.Tag tag = new NodeReactor.Tag();
tag.setName(entry.getKey());
tag.setValue(entry.getValue());
tags.add(tag);
}
for (String dom : registration.getServiceId().split(SEPARATOR)) {
try {
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());
}
catch (Exception e) {
logger.error("ERR_ANS_REGISTER, {} register failed...{},", dom,
registration.toString(), e);
}
}
}
@Override
public void deregister(AnsRegistration registration) {
logger.info("De-registering from ANSServer now...");
if (StringUtils.isEmpty(registration.getServiceId())) {
logger.info("No dom to de-register for client...");
return;
}
try {
NamingService.deRegDom(registration.getServiceId(), registration.getHost(),
registration.getPort(), registration.getCluster());
}
catch (Exception e) {
logger.error("ERR_ANS_DEREGISTER, de-register failed...{},",
registration.toString(), e);
}
logger.info("De-registration finished.");
}
@Override
public void close() {
}
@Override
public void setStatus(AnsRegistration registration, String status) {
}
@Override
public <T> T getStatus(AnsRegistration registration) {
return null;
}
}

@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans.ribbon;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ServerList;
/**
* @author xiaolongzuo
*/
@Configuration
public class AnsRibbonClientConfiguration {
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config) {
AnsServerList serverList = new AnsServerList(config.getClientName());
return serverList;
}
}

@ -0,0 +1,74 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.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;
/**
* @author xiaolongzuo
*/
public class AnsServer extends Server {
private final MetaInfo metaInfo;
private final Host host;
private final Map<String, String> metadata;
public AnsServer(final Host host, final String dom) {
super(host.getIp(), host.getPort());
this.host = host;
this.metadata = Collections.emptyMap();
metaInfo = new MetaInfo() {
@Override
public String getAppName() {
return dom;
}
@Override
public String getServerGroup() {
return getMetadata().get("group");
}
@Override
public String getServiceIdForDiscovery() {
return null;
}
@Override
public String getInstanceId() {
return null;
}
};
}
@Override
public MetaInfo getMetaInfo() {
return metaInfo;
}
public Host getHealthService() {
return this.host;
}
public Map<String, String> getMetadata() {
return metadata;
}
}

@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.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;
/**
* @author xiaolongzuo
*/
public class AnsServerList extends AbstractServerList<AnsServer> {
private String dom;
public AnsServerList(String dom) {
this.dom = dom;
}
@Override
public List<AnsServer> getInitialListOfServers() {
try {
List<Host> hosts = NamingService.getHosts(getDom());
return hostsToServerList(hosts);
}
catch (Exception e) {
throw new IllegalStateException("Can not get ans hosts, dom=" + getDom(), e);
}
}
@Override
public List<AnsServer> getUpdatedListOfServers() {
return getInitialListOfServers();
}
private AnsServer hostToServer(Host host) {
AnsServer server = new AnsServer(host, getDom());
return server;
}
private List<AnsServer> hostsToServerList(List<Host> hosts) {
List<AnsServer> result = new ArrayList<AnsServer>(hosts.size());
for (Host host : hosts) {
if (host.isValid()) {
result.add(hostToServer(host));
}
}
return result;
}
public String getDom() {
return dom;
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
this.dom = iClientConfig.getClientName();
}
}

@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans.ribbon;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
/**
* @author xiaolongzuo
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(value = "ribbon.ans.enabled", matchIfMissing = true)
public @interface ConditionalOnRibbonAns {
}

@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans.ribbon;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alicloud.ans.ConditionalOnAnsEnabled;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaolongzuo
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnAnsEnabled
@ConditionalOnBean(SpringClientFactory.class)
@ConditionalOnRibbonAns
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = AnsRibbonClientConfiguration.class)
public class RibbonAnsAutoConfiguration {
}

@ -0,0 +1,28 @@
{
"properties": [
{
"name": "spring.cloud.ans.server.list",
"type": "java.lang.String",
"defaultValue": "127.0.0.1",
"description": "ANS server list."
},
{
"name": "spring.cloud.ans.server.port",
"type": "java.lang.Integer",
"defaultValue": "80",
"description": "ANS server port."
},
{
"name": "spring.cloud.ans.client.domains",
"type": "java.lang.String",
"defaultValue": "",
"description": "Service name list, default value is ${spring.application.name}."
},
{
"name": "spring.cloud.ans.client.env",
"type": "java.lang.String",
"defaultValue": "DEFAULT",
"description": "The env for ans, default value is DEFAULT."
}
]
}

@ -0,0 +1,6 @@
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.client.discovery.EnableDiscoveryClient=\
org.springframework.cloud.alicloud.ans.AnsDiscoveryClientAutoConfiguration

@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.ans.ribbon;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.springframework.cloud.alicloud.ans.ribbon.AnsServer;
import org.springframework.cloud.alicloud.ans.ribbon.AnsServerList;
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
import com.netflix.loadbalancer.Server;
/**
* @author xiaolongzuo
*/
public class AnsServiceListTests {
static final String IP_ADDR = "10.0.0.2";
static final int PORT = 8080;
@Test
public void testAnsServer() {
AnsServerList serverList = getAnsServerList();
List<AnsServer> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
Server des = assertAnsServer(servers);
assertEquals("hostPort was wrong", IP_ADDR + ":" + PORT, des.getHostPort());
}
protected Server assertAnsServer(List<AnsServer> servers) {
Server actualServer = servers.get(0);
assertTrue("server was not a DomainExtractingServer",
actualServer instanceof AnsServer);
AnsServer des = AnsServer.class.cast(actualServer);
assertNotNull("host is null", des.getHealthService());
assertEquals("unit was wrong", "DEFAULT", des.getHealthService().getUnit());
return des;
}
protected AnsServerList getAnsServerList() {
Host host = mock(Host.class);
given(host.getIp()).willReturn(IP_ADDR);
given(host.getDoubleWeight()).willReturn(1.0);
given(host.getPort()).willReturn(PORT);
given(host.getWeight()).willReturn(1);
given(host.getUnit()).willReturn("DEFAULT");
AnsServer server = new AnsServer(host, "testDom");
@SuppressWarnings("unchecked")
AnsServerList originalServerList = mock(AnsServerList.class);
given(originalServerList.getInitialListOfServers())
.willReturn(Arrays.asList(server));
return originalServerList;
}
}

@ -0,0 +1,99 @@
<?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.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-context</artifactId>
<name>Spring Cloud AliCloud Context</name>
<dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-edas</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>alicloud-context</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<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>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba.edas.acm</groupId>
<artifactId>acm-sdk</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,29 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaolongzuo
*/
@Configuration
@EnableConfigurationProperties(AliCloudProperties.class)
public class AliCloudContextAutoConfiguration {
}

@ -0,0 +1,57 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.alibaba.cloud.context.AliCloudConfiguration;
/**
* @author xiaolongzuo
*/
@ConfigurationProperties("spring.cloud.alicloud")
public class AliCloudProperties implements AliCloudConfiguration {
/**
* alibaba cloud access key.
*/
private String accessKey;
/**
* alibaba cloud secret key.
*/
private String secretKey;
@Override
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
@Override
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
}

@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.acm;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alicloud.context.AliCloudProperties;
import org.springframework.cloud.alicloud.context.edas.EdasContextAutoConfiguration;
import org.springframework.cloud.alicloud.context.edas.EdasProperties;
import org.springframework.context.annotation.Configuration;
import com.alibaba.cloud.context.acm.AliCloudAcmInitializer;
/**
* @author xiaolongzuo
*/
@Configuration
@EnableConfigurationProperties(AcmProperties.class)
@ConditionalOnClass(name = "org.springframework.cloud.alicloud.acm.AcmAutoConfiguration")
@ImportAutoConfiguration(EdasContextAutoConfiguration.class)
public class AcmContextBootstrapConfiguration {
@Autowired
private AcmProperties acmProperties;
@Autowired
private EdasProperties edasProperties;
@Autowired
private AliCloudProperties aliCloudProperties;
@PostConstruct
public void initAcmProperties() {
AliCloudAcmInitializer.initialize(aliCloudProperties, edasProperties,
acmProperties);
}
}

@ -0,0 +1,158 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.acm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.alibaba.cloud.context.AliCloudServerMode;
import com.alibaba.cloud.context.acm.AcmConfiguration;
/**
* acm properties
*
* @author leijuan
* @author xiaolongzuo
*/
@ConfigurationProperties(prefix = "spring.cloud.alicloud.acm")
public class AcmProperties implements AcmConfiguration {
@Value("${spring.cloud.alicloud.acm.server-mode:LOCAL}")
private AliCloudServerMode serverMode;
private String serverList = "127.0.0.1";
private String serverPort = "8080";
/**
* diamond group
*/
private String group = "DEFAULT_GROUP";
/**
* timeout to get configuration
*/
private int timeout = 3000;
/**
* the AliYun endpoint2 for ACM
*/
private String endpoint;
/**
* ACM namespace
*/
private String namespace;
/**
* name of ram role granted to ECS
*/
private String ramRoleName;
private String fileExtension = "properties";
private boolean refreshEnabled = true;
public String getFileExtension() {
return fileExtension;
}
public void setFileExtension(String fileExtension) {
this.fileExtension = fileExtension;
}
@Override
public String getServerList() {
return serverList;
}
public void setServerList(String serverList) {
this.serverList = serverList;
}
@Override
public String getServerPort() {
return serverPort;
}
public void setServerPort(String serverPort) {
this.serverPort = serverPort;
}
@Override
public boolean isRefreshEnabled() {
return refreshEnabled;
}
public void setRefreshEnabled(boolean refreshEnabled) {
this.refreshEnabled = refreshEnabled;
}
@Override
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
@Override
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
@Override
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
@Override
public String getRamRoleName() {
return ramRoleName;
}
public void setRamRoleName(String ramRoleName) {
this.ramRoleName = ramRoleName;
}
@Override
public AliCloudServerMode getServerMode() {
return serverMode;
}
public void setServerMode(AliCloudServerMode serverMode) {
this.serverMode = serverMode;
}
}

@ -0,0 +1,54 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.ans;
import org.springframework.cloud.alicloud.context.AliCloudProperties;
import org.springframework.cloud.alicloud.context.edas.EdasProperties;
import org.springframework.cloud.alicloud.context.listener.AbstractOnceApplicationListener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import com.alibaba.cloud.context.ans.AliCloudAnsInitializer;
import com.alibaba.cloud.context.edas.AliCloudEdasSdk;
/**
* Init {@link com.alibaba.ans.core.NamingService} properties.
*
* @author xiaolongzuo
*/
public class AnsContextApplicationListener
extends AbstractOnceApplicationListener<ContextRefreshedEvent> {
@Override
protected String conditionalOnClass() {
return "org.springframework.cloud.alicloud.ans.AnsAutoConfiguration";
}
@Override
public void handleEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
AliCloudProperties aliCloudProperties = applicationContext
.getBean(AliCloudProperties.class);
EdasProperties edasProperties = applicationContext.getBean(EdasProperties.class);
AnsProperties ansProperties = applicationContext.getBean(AnsProperties.class);
AliCloudEdasSdk aliCloudEdasSdk = applicationContext
.getBean(AliCloudEdasSdk.class);
AliCloudAnsInitializer.initialize(aliCloudProperties, edasProperties,
ansProperties, aliCloudEdasSdk);
}
}

@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.ans;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alicloud.context.edas.EdasContextAutoConfiguration;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaolongzuo
*/
@Configuration
@ConditionalOnClass(name = "org.springframework.cloud.alicloud.ans.AnsAutoConfiguration")
@EnableConfigurationProperties({ AnsProperties.class, InetUtilsProperties.class })
@ImportAutoConfiguration(EdasContextAutoConfiguration.class)
public class AnsContextAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public InetUtils inetUtils(InetUtilsProperties inetUtilsProperties) {
return new InetUtils(inetUtilsProperties);
}
}

@ -0,0 +1,337 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.ans;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.util.StringUtils;
import com.alibaba.cloud.context.AliCloudServerMode;
import com.alibaba.cloud.context.ans.AnsConfiguration;
/**
* @author xiaolongzuo
*/
@ConfigurationProperties("spring.cloud.alicloud.ans")
public class AnsProperties implements AnsConfiguration {
/**
* LOCAL
*/
@Value("${spring.cloud.alicloud.ans.server-mode:LOCAL}")
private AliCloudServerMode serverMode;
/**
*
*/
@Value("${spring.cloud.alicloud.ans.server-list:127.0.0.1}")
private String serverList;
/**
*
*/
@Value("${spring.cloud.alicloud.ans.server-port:8080}")
private String serverPort;
/**
* spring.cloud.alicloud.ans.doms 使 spring.application.name
*/
@Value("${spring.cloud.alicloud.ans.client-domains:${spring.application.name:}}")
private String clientDomains;
/**
* spring.cloud.alicloud.ans.weight 1
*/
private float clientWeight = 1;
/**
* doms weight spring.cloud.alicloud.ans.weight.dom1=weight1
*/
private Map<String, Float> clientWeights = new HashMap<String, Float>();
/**
* token spring.cloud.alicloud.ans.token
*/
private String clientToken;
/**
* domstoken spring.cloud.alicloud.ans.tokens.dom1=token1
*/
private Map<String, String> clientTokens = new HashMap<String, String>();
/**
* spring.cloud.alicloud.ans.cluster DEFAULT
*/
private String clientCluster = "DEFAULT";
/**
* metadata serviceInstance ans
*/
private Map<String, String> clientMetadata = new HashMap<>();
/**
* spring.cloud.alicloud.ans.register-enabled=false
*/
private boolean registerEnabled = true;
/**
* ip spring.cloud.alicloud.ans.client-ip
*/
private String clientIp;
/**
* ip
*/
private String clientInterfaceName;
/**
* spring.cloud.alicloud.ans.port
*/
private int clientPort = -1;
/**
*
*/
@Value("${spring.cloud.alicloud.ans.env:${env.id:DEFAULT}}")
private String env;
/**
* https spring.cloud.alicloud.ans.secure false
*/
private boolean secure = false;
@Autowired
private InetUtils inetUtils;
private Map<String, String> tags = new HashMap<>();
@PostConstruct
public void init() throws SocketException {
// 增加注册类型,标记为 spring cloud 应用
tags.put("ANS_SERVICE_TYPE", "SPRING_CLOUD");
if (StringUtils.isEmpty(clientIp)) {
// 如果没有指定注册的ip对应的网卡名则通过遍历网卡去获取
if (StringUtils.isEmpty(clientInterfaceName)) {
clientIp = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
}
else {
NetworkInterface networkInterface = NetworkInterface
.getByName(clientInterfaceName);
if (null == networkInterface) {
throw new RuntimeException(
"no such network interface " + clientInterfaceName);
}
Enumeration<InetAddress> inetAddress = networkInterface
.getInetAddresses();
while (inetAddress.hasMoreElements()) {
InetAddress currentAddress = inetAddress.nextElement();
if (currentAddress instanceof Inet4Address
&& !currentAddress.isLoopbackAddress()) {
clientIp = currentAddress.getHostAddress();
break;
}
}
if (StringUtils.isEmpty(clientIp)) {
throw new RuntimeException(
"cannot find available ip from network interface "
+ clientInterfaceName);
}
}
}
}
@Override
public String getServerPort() {
return serverPort;
}
public void setServerPort(String serverPort) {
this.serverPort = serverPort;
}
@Override
public String getServerList() {
return serverList;
}
public void setServerList(String serverList) {
this.serverList = serverList;
}
@Override
public boolean isRegisterEnabled() {
return registerEnabled;
}
public void setRegisterEnabled(boolean registerEnabled) {
this.registerEnabled = registerEnabled;
}
@Override
public boolean isSecure() {
return secure;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
@Override
public String getEnv() {
return env;
}
public void setEnv(String env) {
this.env = env;
}
@Override
public Map<String, String> getTags() {
return tags;
}
public void setTags(Map<String, String> tags) {
this.tags = tags;
}
@Override
public AliCloudServerMode getServerMode() {
return serverMode;
}
public void setServerMode(AliCloudServerMode serverMode) {
this.serverMode = serverMode;
}
@Override
public String getClientDomains() {
return clientDomains;
}
public void setClientDomains(String clientDomains) {
this.clientDomains = clientDomains;
}
@Override
public float getClientWeight() {
return clientWeight;
}
public void setClientWeight(float clientWeight) {
this.clientWeight = clientWeight;
}
@Override
public Map<String, Float> getClientWeights() {
return clientWeights;
}
public void setClientWeights(Map<String, Float> clientWeights) {
this.clientWeights = clientWeights;
}
@Override
public String getClientToken() {
return clientToken;
}
public void setClientToken(String clientToken) {
this.clientToken = clientToken;
}
@Override
public Map<String, String> getClientTokens() {
return clientTokens;
}
public void setClientTokens(Map<String, String> clientTokens) {
this.clientTokens = clientTokens;
}
@Override
public String getClientCluster() {
return clientCluster;
}
public void setClientCluster(String clientCluster) {
this.clientCluster = clientCluster;
}
@Override
public Map<String, String> getClientMetadata() {
return clientMetadata;
}
public void setClientMetadata(Map<String, String> clientMetadata) {
this.clientMetadata = clientMetadata;
}
@Override
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
@Override
public String getClientInterfaceName() {
return clientInterfaceName;
}
public void setClientInterfaceName(String clientInterfaceName) {
this.clientInterfaceName = clientInterfaceName;
}
@Override
public int getClientPort() {
return clientPort;
}
public void setClientPort(int clientPort) {
this.clientPort = clientPort;
}
@Override
public String toString() {
return "AnsProperties{" + "doms='" + clientDomains + '\'' + ", weight="
+ clientWeight + ", weights=" + clientWeights + ", token='" + clientToken
+ '\'' + ", tokens=" + clientTokens + ", cluster='" + clientCluster + '\''
+ ", metadata=" + clientMetadata + ", registerEnabled=" + registerEnabled
+ ", ip='" + clientIp + '\'' + ", interfaceName='" + clientInterfaceName
+ '\'' + ", port=" + clientPort + ", env='" + env + '\'' + ", secure="
+ secure + ", tags=" + tags + '}';
}
}

@ -0,0 +1,48 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.edas;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alicloud.context.AliCloudContextAutoConfiguration;
import org.springframework.cloud.alicloud.context.AliCloudProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.cloud.context.edas.AliCloudEdasSdk;
import com.alibaba.cloud.context.edas.AliCloudEdasSdkFactory;
/**
* @author xiaolongzuo
*/
@Configuration
@EnableConfigurationProperties(EdasProperties.class)
@ImportAutoConfiguration(AliCloudContextAutoConfiguration.class)
public class EdasContextAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = "com.aliyuncs.edas.model.v20170801.GetSecureTokenRequest")
public AliCloudEdasSdk aliCloudEdasSdk(AliCloudProperties aliCloudProperties,
EdasProperties edasProperties) {
return AliCloudEdasSdkFactory.getDefaultAliCloudEdasSdk(aliCloudProperties,
edasProperties.getRegionId());
}
}

@ -0,0 +1,87 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.edas;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.alibaba.cloud.context.edas.EdasConfiguration;
/**
* @author xiaolongzuo
*/
@ConfigurationProperties("spring.cloud.alicloud.edas")
public class EdasProperties implements EdasConfiguration {
private static final String DEFAULT_APPLICATION_NAME = "";
/**
* edas application name.
*/
@Value("${spring.application.name:${spring.cloud.alicloud.edas.application.name:}}")
private String applicationName;
/**
* edas namespace
*/
private String namespace;
/**
* whether or not connect edas.
*/
private boolean enabled;
@Override
public String getRegionId() {
if (namespace == null) {
return null;
}
return namespace.contains(":") ? namespace.split(":")[0] : namespace;
}
@Override
public boolean isApplicationNameValid() {
return !DEFAULT_APPLICATION_NAME.equals(applicationName);
}
@Override
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
@Override
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
@Override
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

@ -0,0 +1,86 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.listener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextEvent;
/**
* @author xiaolongzuo
*/
public abstract class AbstractOnceApplicationListener<T extends ApplicationEvent>
implements ApplicationListener<T> {
private static final String BOOTSTRAP_CONFIG_NAME_VALUE = "bootstrap";
private static final String BOOTSTRAP_CONFIG_NAME_KEY = "spring.config.name";
private static ConcurrentHashMap<Class<?>, AtomicBoolean> lockMap = new ConcurrentHashMap<>();
@Override
public void onApplicationEvent(T event) {
if (event instanceof ApplicationContextEvent) {
ApplicationContext applicationContext = ((ApplicationContextEvent) event)
.getApplicationContext();
// skip bootstrap context or super parent context.
if (applicationContext.getParent() == null
|| BOOTSTRAP_CONFIG_NAME_VALUE.equals(applicationContext
.getEnvironment().getProperty(BOOTSTRAP_CONFIG_NAME_KEY))) {
return;
}
}
Class<?> clazz = getClass();
lockMap.putIfAbsent(clazz, new AtomicBoolean(false));
AtomicBoolean handled = lockMap.get(clazz);
// only execute once.
if (!handled.compareAndSet(false, true)) {
return;
}
if (conditionalOnClass() != null) {
try {
Class.forName(conditionalOnClass());
}
catch (ClassNotFoundException e) {
// ignored
return;
}
}
handleEvent(event);
}
/**
* handle event.
*
* @param event
*/
protected abstract void handleEvent(T event);
/**
* condition on class.
*
* @return
*/
protected String conditionalOnClass() {
return null;
}
}

@ -0,0 +1,80 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.oss;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alicloud.context.AliCloudContextAutoConfiguration;
import org.springframework.cloud.alicloud.context.AliCloudProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.alibaba.cloud.context.AliCloudAuthorizationMode;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
/**
* OSS Auto {@link Configuration}
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
* @author xiaolongzuo
*/
@Configuration
@ConditionalOnClass(name = "org.springframework.cloud.alicloud.oss.OssAutoConfiguration")
@EnableConfigurationProperties(OssProperties.class)
@ImportAutoConfiguration(AliCloudContextAutoConfiguration.class)
public class OssContextAutoConfiguration {
@ConditionalOnMissingBean
@Bean
public OSS ossClient(AliCloudProperties aliCloudProperties,
OssProperties ossProperties) {
if (ossProperties.getAuthorizationMode() == AliCloudAuthorizationMode.AK_SK) {
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getEndpoint()),
"Oss endpoint can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(aliCloudProperties.getAccessKey()),
"Access key can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(aliCloudProperties.getSecretKey()),
"Secret key can't be empty.");
return new OSSClientBuilder().build(ossProperties.getEndpoint(),
aliCloudProperties.getAccessKey(), aliCloudProperties.getSecretKey(),
ossProperties.getConfig());
}
else if (ossProperties.getAuthorizationMode() == AliCloudAuthorizationMode.STS) {
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getEndpoint()),
"Oss endpoint can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getSts().getAccessKey()),
"Access key can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getSts().getSecretKey()),
"Secret key can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getSts().getSecurityToken()),
"Security Token can't be empty.");
return new OSSClientBuilder().build(ossProperties.getEndpoint(),
ossProperties.getSts().getAccessKey(),
ossProperties.getSts().getSecretKey(),
ossProperties.getSts().getSecurityToken(), ossProperties.getConfig());
}
else {
throw new IllegalArgumentException("Unknown auth mode.");
}
}
}

@ -0,0 +1,109 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.oss;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.alibaba.cloud.context.AliCloudAuthorizationMode;
import com.aliyun.oss.ClientBuilderConfiguration;
/**
* {@link ConfigurationProperties} for configuring OSS.
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
* @author xiaolongzuo
*/
@ConfigurationProperties("spring.cloud.alicloud.oss")
public class OssProperties {
@Value("${spring.cloud.alicloud.oss.authorization-mode:AK_SK}")
private AliCloudAuthorizationMode authorizationMode;
private String endpoint;
private StsToken sts;
private ClientBuilderConfiguration config;
public AliCloudAuthorizationMode getAuthorizationMode() {
return authorizationMode;
}
public void setAuthorizationMode(AliCloudAuthorizationMode authorizationMode) {
this.authorizationMode = authorizationMode;
}
public ClientBuilderConfiguration getConfig() {
return config;
}
public void setConfig(ClientBuilderConfiguration config) {
this.config = config;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public StsToken getSts() {
return sts;
}
public void setSts(StsToken sts) {
this.sts = sts;
}
public static class StsToken {
private String accessKey;
private String secretKey;
private String securityToken;
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getSecurityToken() {
return securityToken;
}
public void setSecurityToken(String securityToken) {
this.securityToken = securityToken;
}
}
}

@ -0,0 +1,34 @@
{
"properties": [
{
"name": "spring.cloud.alicloud.ans.server.mode",
"type": "java.lang.String",
"defaultValue": "LOCAL",
"description": "Server mode."
},
{
"name": "spring.cloud.alicloud.ans.server.list",
"type": "java.lang.String",
"defaultValue": "127.0.0.1",
"description": "ANS server list."
},
{
"name": "spring.cloud.alicloud.ans.server.port",
"type": "java.lang.Integer",
"defaultValue": "80",
"description": "ANS server port."
},
{
"name": "spring.cloud.alicloud.ans.client.domains",
"type": "java.lang.String",
"defaultValue": "",
"description": "Service name list, default value is ${spring.application.name}."
},
{
"name": "spring.cloud.alicloud.ans.client.env",
"type": "java.lang.String",
"defaultValue": "DEFAULT",
"description": "The env for ans, default value is DEFAULT."
}
]
}

@ -0,0 +1,9 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.alicloud.context.acm.AcmContextBootstrapConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alicloud.context.AliCloudContextAutoConfiguration,\
org.springframework.cloud.alicloud.context.edas.EdasContextAutoConfiguration,\
org.springframework.cloud.alicloud.context.ans.AnsContextAutoConfiguration,\
org.springframework.cloud.alicloud.context.oss.OssContextAutoConfiguration
org.springframework.context.ApplicationListener=\
org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener

@ -0,0 +1,23 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.acm;
/**
* @author xiaolongzuo
*/
public class AcmAutoConfiguration {
}

@ -0,0 +1,23 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.ans;
/**
* @author xiaolongzuo
*/
public class AnsAutoConfiguration {
}

@ -0,0 +1,53 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
/**
* @author xiaolongzuo
*/
public class AliCloudPropertiesTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(AliCloudContextAutoConfiguration.class));
@Test
public void testConfigurationValueDefaultsAreAsExpected() {
this.contextRunner.run(context -> {
AliCloudProperties config = context.getBean(AliCloudProperties.class);
assertThat(config.getAccessKey()).isNull();
assertThat(config.getSecretKey()).isNull();
});
}
@Test
public void testConfigurationValuesAreCorrectlyLoaded() {
this.contextRunner.withPropertyValues("spring.cloud.alicloud.access-key=123",
"spring.cloud.alicloud.secret-key=123456").run(context -> {
AliCloudProperties config = context.getBean(AliCloudProperties.class);
assertThat(config.getAccessKey()).isEqualTo("123");
assertThat(config.getSecretKey()).isEqualTo("123456");
});
}
}

@ -0,0 +1,50 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author xiaolongzuo
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AliCloudSpringApplicationTests.EurekaClientDisabledApp.class, properties = {
"spring.application.name=myapp",
"spring.cloud.alicloud.edas.application.name=myapp",
"spring.cloud.alicloud.access-key=ak", "spring.cloud.alicloud.secret-key=sk",
"spring.cloud.alicloud.oss.endpoint=test" }, webEnvironment = RANDOM_PORT)
@DirtiesContext
public class AliCloudSpringApplicationTests {
@Test
public void contextLoads() {
System.out.println("Context load...");
}
@SpringBootApplication
public static class EurekaClientDisabledApp {
}
}

@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.acm;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.alicloud.context.AliCloudContextAutoConfiguration;
import org.springframework.cloud.alicloud.context.edas.EdasContextAutoConfiguration;
import com.alibaba.cloud.context.AliCloudServerMode;
/**
* @author xiaolongzuo
*/
public class AnsPropertiesTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(AcmContextBootstrapConfiguration.class,
EdasContextAutoConfiguration.class,
AliCloudContextAutoConfiguration.class));
@Test
public void testConfigurationValueDefaultsAreAsExpected() {
this.contextRunner.withPropertyValues().run(context -> {
AcmProperties config = context.getBean(AcmProperties.class);
assertThat(config.getServerMode()).isEqualTo(AliCloudServerMode.LOCAL);
assertThat(config.getServerList()).isEqualTo("127.0.0.1");
assertThat(config.getServerPort()).isEqualTo("8080");
assertThat(config.getEndpoint()).isNull();
assertThat(config.getFileExtension()).isEqualTo("properties");
assertThat(config.getGroup()).isEqualTo("DEFAULT_GROUP");
assertThat(config.getNamespace()).isNull();
assertThat(config.getRamRoleName()).isNull();
assertThat(config.getTimeout()).isEqualTo(3000);
});
}
@Test
public void testConfigurationValuesAreCorrectlyLoaded() {
this.contextRunner.withPropertyValues("spring.cloud.alicloud.access-key=ak",
"spring.cloud.alicloud.secret-key=sk",
"spring.cloud.alicloud.acm.server-mode=EDAS",
"spring.cloud.alicloud.acm.server-port=11111",
"spring.cloud.alicloud.acm.server-list=10.10.10.10",
"spring.cloud.alicloud.acm.namespace=testNamespace",
"spring.cloud.alicloud.acm.endpoint=testDomain",
"spring.cloud.alicloud.acm.group=testGroup",
"spring.cloud.alicloud.acm.file-extension=yaml").run(context -> {
AcmProperties config = context.getBean(AcmProperties.class);
assertThat(config.getServerMode()).isEqualTo(AliCloudServerMode.EDAS);
assertThat(config.getServerList()).isEqualTo("10.10.10.10");
assertThat(config.getServerPort()).isEqualTo("11111");
assertThat(config.getEndpoint()).isEqualTo("testDomain");
assertThat(config.getGroup()).isEqualTo("testGroup");
assertThat(config.getFileExtension()).isEqualTo("yaml");
assertThat(config.getNamespace()).isEqualTo("testNamespace");
});
}
}

@ -0,0 +1,101 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.ans;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.alicloud.context.AliCloudContextAutoConfiguration;
import org.springframework.cloud.alicloud.context.edas.EdasContextAutoConfiguration;
import com.alibaba.cloud.context.AliCloudServerMode;
/**
* @author xiaolongzuo
*/
public class AnsPropertiesTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(AnsContextAutoConfiguration.class,
EdasContextAutoConfiguration.class,
AliCloudContextAutoConfiguration.class));
@Test
public void testConfigurationValueDefaultsAreAsExpected()
throws ClassNotFoundException {
this.contextRunner.withPropertyValues().run(context -> {
AnsProperties config = context.getBean(AnsProperties.class);
assertThat(config.getServerMode()).isEqualTo(AliCloudServerMode.LOCAL);
assertThat(config.getServerList()).isEqualTo("127.0.0.1");
assertThat(config.getServerPort()).isEqualTo("8080");
assertThat(config.getClientDomains()).isEqualTo("");
assertThat(config.getClientWeight()).isEqualTo(1.0F);
assertThat(config.getClientWeights().size()).isEqualTo(0);
assertThat(config.getClientTokens().size()).isEqualTo(0);
assertThat(config.getClientMetadata().size()).isEqualTo(0);
assertThat(config.getClientToken()).isNull();
assertThat(config.getClientCluster()).isEqualTo("DEFAULT");
assertThat(config.isRegisterEnabled()).isTrue();
assertThat(config.getClientInterfaceName()).isNull();
assertThat(config.getClientPort()).isEqualTo(-1);
assertThat(config.getEnv()).isEqualTo("DEFAULT");
assertThat(config.isSecure()).isFalse();
assertThat(config.getTags().size()).isEqualTo(1);
assertThat(config.getTags().keySet().iterator().next())
.isEqualTo("ANS_SERVICE_TYPE");
assertThat(config.getTags().get("ANS_SERVICE_TYPE"))
.isEqualTo("SPRING_CLOUD");
});
}
@Test
public void testConfigurationValuesAreCorrectlyLoaded() {
this.contextRunner
.withPropertyValues("spring.cloud.alicloud.ans.server-mode=EDAS",
"spring.cloud.alicloud.ans.server-port=11111",
"spring.cloud.alicloud.ans.server-list=10.10.10.10",
"spring.cloud.alicloud.ans.client-domains=testDomain",
"spring.cloud.alicloud.ans.client-weight=0.9",
"spring.cloud.alicloud.ans.client-weights.testDomain=0.9")
.run(context -> {
AnsProperties config = context.getBean(AnsProperties.class);
assertThat(config.getServerMode()).isEqualTo(AliCloudServerMode.EDAS);
assertThat(config.getServerList()).isEqualTo("10.10.10.10");
assertThat(config.getServerPort()).isEqualTo("11111");
assertThat(config.getClientDomains()).isEqualTo("testDomain");
assertThat(config.getClientWeight()).isEqualTo(0.9F);
assertThat(config.getClientWeights().size()).isEqualTo(1);
assertThat(config.getClientTokens().size()).isEqualTo(0);
assertThat(config.getClientMetadata().size()).isEqualTo(0);
assertThat(config.getClientToken()).isNull();
assertThat(config.getClientCluster()).isEqualTo("DEFAULT");
assertThat(config.isRegisterEnabled()).isTrue();
assertThat(config.getClientInterfaceName()).isNull();
assertThat(config.getClientPort()).isEqualTo(-1);
assertThat(config.getEnv()).isEqualTo("DEFAULT");
assertThat(config.isSecure()).isFalse();
assertThat(config.getTags().size()).isEqualTo(1);
assertThat(config.getTags().keySet().iterator().next())
.isEqualTo("ANS_SERVICE_TYPE");
assertThat(config.getTags().get("ANS_SERVICE_TYPE"))
.isEqualTo("SPRING_CLOUD");
});
}
}

@ -0,0 +1,68 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.context.edas;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.alicloud.context.AliCloudContextAutoConfiguration;
/**
* @author xiaolongzuo
*/
public class EdasPropertiesTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(EdasContextAutoConfiguration.class,
AliCloudContextAutoConfiguration.class));
@Test
public void testConfigurationValueDefaultsAreAsExpected() {
this.contextRunner.withPropertyValues().run(context -> {
EdasProperties config = context.getBean(EdasProperties.class);
assertThat(config.getNamespace()).isNull();
assertThat(config.isApplicationNameValid()).isFalse();
});
}
@Test
public void testConfigurationValuesAreCorrectlyLoaded1() {
this.contextRunner
.withPropertyValues("spring.cloud.alicloud.edas.namespace=testns",
"spring.application.name=myapps")
.run(context -> {
EdasProperties config = context.getBean(EdasProperties.class);
assertThat(config.getNamespace()).isEqualTo("testns");
assertThat(config.getApplicationName()).isEqualTo("myapps");
});
}
@Test
public void testConfigurationValuesAreCorrectlyLoaded2() {
this.contextRunner
.withPropertyValues("spring.cloud.alicloud.edas.namespace=testns",
"spring.cloud.alicloud.edas.application.name=myapps")
.run(context -> {
EdasProperties config = context.getBean(EdasProperties.class);
assertThat(config.getNamespace()).isEqualTo("testns");
assertThat(config.getApplicationName()).isEqualTo("myapps");
});
}
}

@ -14,46 +14,45 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss.test;
package org.springframework.cloud.alicloud.context.oss;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.alibaba.oss.OSSAutoConfiguration;
import org.springframework.cloud.alibaba.oss.OSSProperties;
import org.springframework.cloud.alicloud.context.AliCloudProperties;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
/**
* {@link OSS} {@link OSSProperties} Test
* {@link OSS} {@link OssProperties} Test
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
public class OSSAutoConfigurationTests {
public class OssAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(OSSAutoConfiguration.class))
.withPropertyValues("spring.cloud.alibaba.oss.accessKeyId=your-ak")
.withPropertyValues("spring.cloud.alibaba.oss.secretAccessKey=your-sk")
.withConfiguration(AutoConfigurations.of(OssContextAutoConfiguration.class))
.withPropertyValues("spring.cloud.alicloud.accessKey=your-ak")
.withPropertyValues("spring.cloud.alicloud.secretKey=your-sk")
.withPropertyValues(
"spring.cloud.alibaba.oss.endpoint=http://oss-cn-beijing.aliyuncs.com")
.withPropertyValues(
"spring.cloud.alibaba.oss.configuration.userAgent=alibaba");
"spring.cloud.alicloud.oss.endpoint=http://oss-cn-beijing.aliyuncs.com")
.withPropertyValues("spring.cloud.alicloud.oss.config.userAgent=alibaba");
@Test
public void testOSSProperties() {
this.contextRunner.run(context -> {
assertThat(context.getBeansOfType(OSSProperties.class).size() == 1).isTrue();
OSSProperties ossProperties = context.getBean(OSSProperties.class);
assertThat(ossProperties.getAccessKeyId()).isEqualTo("your-ak");
assertThat(ossProperties.getSecretAccessKey()).isEqualTo("your-sk");
assertThat(context.getBeansOfType(OssProperties.class).size() == 1).isTrue();
AliCloudProperties aliCloudProperties = context
.getBean(AliCloudProperties.class);
OssProperties ossProperties = context.getBean(OssProperties.class);
assertThat(aliCloudProperties.getAccessKey()).isEqualTo("your-ak");
assertThat(aliCloudProperties.getSecretKey()).isEqualTo("your-sk");
assertThat(ossProperties.getEndpoint())
.isEqualTo("http://oss-cn-beijing.aliyuncs.com");
assertThat(ossProperties.getConfiguration().getUserAgent())
.isEqualTo("alibaba");
assertThat(ossProperties.getConfig().getUserAgent()).isEqualTo("alibaba");
});
}

@ -0,0 +1,23 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.oss;
/**
* @author xiaolongzuo
*/
public class OssAutoConfiguration {
}

@ -15,10 +15,14 @@
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-context</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<optional>true</optional>
</dependency>
<dependency>

@ -1,118 +0,0 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.aliyun.oss.ClientBuilderConfiguration;
/**
* {@link ConfigurationProperties} for configuring OSS.
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@ConfigurationProperties(prefix = OSSConstants.PREFIX)
public class OSSProperties {
private static final Logger logger = LoggerFactory.getLogger(OSSProperties.class);
public static final Map<String, String> endpointMap = new HashMap<>();
static {
endpointMap.put("cn-beijing", "http://oss-cn-beijing.aliyuncs.com");
endpointMap.put("cn-qingdao", "http://oss-cn-qingdao.aliyuncs.com");
endpointMap.put("cn-hangzhou", "http://oss-cn-hangzhou.aliyuncs.com");
endpointMap.put("cn-hongkong", "http://oss-cn-hongkong.aliyuncs.com");
endpointMap.put("cn-shenzhen", "http://oss-cn-shenzhen.aliyuncs.com");
endpointMap.put("us-west-1", "http://oss-us-west-1.aliyuncs.com");
endpointMap.put("ap-southeast-1", "http://oss-ap-southeast-1.aliyuncs.com");
}
private ClientBuilderConfiguration configuration;
private String accessKeyId;
private String secretAccessKey;
private String region;
private String endpoint;
// support ram sts
private String securityToken;
public ClientBuilderConfiguration getConfiguration() {
return configuration;
}
public void setConfiguration(ClientBuilderConfiguration configuration) {
this.configuration = configuration;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getSecretAccessKey() {
return secretAccessKey;
}
public void setSecretAccessKey(String secretAccessKey) {
this.secretAccessKey = secretAccessKey;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getSecurityToken() {
return securityToken;
}
public void setSecurityToken(String securityToken) {
this.securityToken = securityToken;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
if (!endpointMap.containsKey(region)) {
String errorStr = "error region: " + region + ", please choose from "
+ Arrays.toString(endpointMap.keySet().toArray());
logger.error(errorStr);
throw new IllegalArgumentException(errorStr);
}
this.region = region;
this.setEndpoint(endpointMap.get(region));
}
}

@ -1,72 +0,0 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss.endpoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.context.ApplicationContext;
import com.aliyun.oss.OSSClient;
/**
* Actuator {@link Endpoint} to expose OSS Meta Data
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@Endpoint(id = "oss")
public class OSSEndpoint {
@Autowired
private ApplicationContext applicationContext;
@ReadOperation
public Map<String, Object> invoke() {
Map<String, Object> result = new HashMap<>();
Map<String, OSSClient> ossClientMap = applicationContext
.getBeansOfType(OSSClient.class);
int size = ossClientMap.size();
List<Object> ossClientList = new ArrayList<>();
ossClientMap.keySet().forEach(beanName -> {
Map<String, Object> ossProperties = new HashMap<>();
OSSClient client = ossClientMap.get(beanName);
ossProperties.put("beanName", beanName);
ossProperties.put("endpoint", client.getEndpoint().toString());
ossProperties.put("clientConfiguration", client.getClientConfiguration());
ossProperties.put("credentials",
client.getCredentialsProvider().getCredentials());
ossProperties.put("bucketList", client.listBuckets().stream()
.map(bucket -> bucket.getName()).toArray());
ossClientList.add(ossProperties);
});
result.put("size", size);
result.put("info", ossClientList);
return result;
}
}

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss;
package org.springframework.cloud.alicloud.oss;
import java.util.Map;
@ -30,10 +30,10 @@ import com.aliyun.oss.OSS;
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
public class OSSApplicationListener implements ApplicationListener<ContextClosedEvent> {
public class OssApplicationListener implements ApplicationListener<ContextClosedEvent> {
private static final Logger logger = LoggerFactory
.getLogger(OSSApplicationListener.class);
.getLogger(OssApplicationListener.class);
@Override
public void onApplicationEvent(ContextClosedEvent event) {

@ -14,21 +14,16 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss;
package org.springframework.cloud.alicloud.oss;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.aliyun.oss.OSS;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alibaba.oss.resource.OSSStorageProtocolResolver;
import org.springframework.cloud.alicloud.oss.resource.OssStorageProtocolResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
/**
* OSS Auto {@link Configuration}
*
@ -36,26 +31,13 @@ import com.aliyun.oss.OSSClientBuilder;
*/
@Configuration
@ConditionalOnClass(OSS.class)
@ConditionalOnProperty(name = OSSConstants.ENABLED, havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(OSSProperties.class)
public class OSSAutoConfiguration {
private static final Logger logger = LoggerFactory
.getLogger(OSSAutoConfiguration.class);
@ConditionalOnMissingBean
@Bean
public OSS ossClient(OSSProperties ossProperties) {
logger.info("construct OSS because it is missing");
return new OSSClientBuilder().build(ossProperties.getEndpoint(),
ossProperties.getAccessKeyId(), ossProperties.getSecretAccessKey(),
ossProperties.getSecurityToken(), ossProperties.getConfiguration());
}
@ConditionalOnMissingBean
@Bean
public OSSStorageProtocolResolver ossStorageProtocolResolver() {
return new OSSStorageProtocolResolver();
}
@ConditionalOnProperty(name = OssConstants.ENABLED, havingValue = "true", matchIfMissing = true)
public class OssAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public OssStorageProtocolResolver ossStorageProtocolResolver() {
return new OssStorageProtocolResolver();
}
}

@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss;
package org.springframework.cloud.alicloud.oss;
/**
* OSS constants
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
public interface OSSConstants {
public interface OssConstants {
String PREFIX = "spring.cloud.alibaba.oss";
String ENABLED = PREFIX + ".enabled";

@ -0,0 +1,71 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alicloud.oss.endpoint;
import com.aliyun.oss.OSSClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.context.ApplicationContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Actuator {@link Endpoint} to expose OSS Meta Data
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@Endpoint(id = "oss")
public class OssEndpoint {
@Autowired
private ApplicationContext applicationContext;
@ReadOperation
public Map<String, Object> invoke() {
Map<String, Object> result = new HashMap<>();
Map<String, OSSClient> ossClientMap = applicationContext
.getBeansOfType(OSSClient.class);
int size = ossClientMap.size();
List<Object> ossClientList = new ArrayList<>();
ossClientMap.keySet().forEach(beanName -> {
Map<String, Object> ossProperties = new HashMap<>();
OSSClient client = ossClientMap.get(beanName);
ossProperties.put("beanName", beanName);
ossProperties.put("endpoint", client.getEndpoint().toString());
ossProperties.put("clientConfiguration", client.getClientConfiguration());
ossProperties.put("credentials",
client.getCredentialsProvider().getCredentials());
ossProperties.put("bucketList", client.listBuckets().stream()
.map(bucket -> bucket.getName()).toArray());
ossClientList.add(ossProperties);
});
result.put("size", size);
result.put("info", ossClientList);
return result;
}
}

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss.endpoint;
package org.springframework.cloud.alicloud.oss.endpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
@ -29,13 +29,13 @@ import org.springframework.context.annotation.Configuration;
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@ConditionalOnClass(Endpoint.class)
public class OSSEndpointAutoConfiguration {
public class OssEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public OSSEndpoint sentinelEndPoint() {
return new OSSEndpoint();
public OssEndpoint sentinelEndPoint() {
return new OssEndpoint();
}
}

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss.resource;
package org.springframework.cloud.alicloud.oss.resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -34,13 +34,13 @@ import com.aliyun.oss.OSS;
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
public class OSSStorageProtocolResolver
public class OssStorageProtocolResolver
implements ProtocolResolver, BeanFactoryPostProcessor, ResourceLoaderAware {
public static final String PROTOCOL = "oss://";
private static final Logger logger = LoggerFactory
.getLogger(OSSStorageProtocolResolver.class);
.getLogger(OssStorageProtocolResolver.class);
private ConfigurableListableBeanFactory beanFactory;
@ -62,7 +62,7 @@ public class OSSStorageProtocolResolver
if (!location.startsWith(PROTOCOL)) {
return null;
}
return new OSSStorageResource(getOSS(), location);
return new OssStorageResource(getOSS(), location);
}
@Override

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss.resource;
package org.springframework.cloud.alicloud.oss.resource;
import java.io.File;
import java.io.FileNotFoundException;
@ -42,17 +42,17 @@ import com.aliyun.oss.model.OSSObject;
* @see Bucket
* @see OSSObject
*/
public class OSSStorageResource implements Resource {
public class OssStorageResource implements Resource {
private final OSS oss;
private final String bucketName;
private final String objectKey;
private final URI location;
public OSSStorageResource(OSS oss, String location) {
public OssStorageResource(OSS oss, String location) {
Assert.notNull(oss, "Object Storage Service can not be null");
Assert.isTrue(location.startsWith(OSSStorageProtocolResolver.PROTOCOL),
"Location must start with " + OSSStorageProtocolResolver.PROTOCOL);
Assert.isTrue(location.startsWith(OssStorageProtocolResolver.PROTOCOL),
"Location must start with " + OssStorageProtocolResolver.PROTOCOL);
this.oss = oss;
try {
URI locationUri = new URI(location);
@ -123,7 +123,7 @@ public class OSSStorageResource implements Resource {
@Override
public Resource createRelative(String relativePath) throws IOException {
return new OSSStorageResource(this.oss,
return new OssStorageResource(this.oss,
this.location.resolve(relativePath).toString());
}

@ -1,5 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alibaba.oss.OSSAutoConfiguration,\
org.springframework.cloud.alibaba.oss.endpoint.OSSEndpointAutoConfiguration
org.springframework.cloud.alicloud.oss.OssAutoConfiguration,\
org.springframework.cloud.alicloud.oss.endpoint.OssEndpointAutoConfiguration
org.springframework.context.ApplicationListener=\
org.springframework.cloud.alibaba.oss.OSSApplicationListener
org.springframework.cloud.alicloud.oss.OssApplicationListener

@ -1,116 +0,0 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.oss.test;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.alibaba.oss.OSSAutoConfiguration;
import org.springframework.cloud.alibaba.oss.OSSProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
/**
* Multi {@link OSS} {@link OSSProperties} Test
*
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
public class OSSMultiClientAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(OSSAutoConfiguration.class))
.withPropertyValues("spring.cloud.alibaba.oss.accessKeyId=your-ak")
.withPropertyValues("spring.cloud.alibaba.oss.secretAccessKey=your-sk")
.withPropertyValues(
"spring.cloud.alibaba.oss.endpoint=http://oss-cn-beijing.aliyuncs.com")
.withPropertyValues(
"spring.cloud.alibaba.oss.configuration.userAgent=alibaba")
.withPropertyValues("spring.cloud.alibaba.oss1.accessKeyId=your-ak1")
.withPropertyValues("spring.cloud.alibaba.oss1.secretAccessKey=your-sk1")
.withPropertyValues(
"spring.cloud.alibaba.oss1.endpoint=http://oss-cn-beijing.aliyuncs.com")
.withPropertyValues(
"spring.cloud.alibaba.oss1.configuration.userAgent=alibaba1");
@Test
public void testOSSClient() {
this.contextRunner.withUserConfiguration(MultiClientConfiguration.class)
.run(context -> {
assertThat(context.getBeansOfType(OSS.class).size() == 2).isTrue();
OSSClient ossClient = (OSSClient) context.getBean("ossClient1",
OSS.class);
assertThat(ossClient.getEndpoint().toString())
.isEqualTo("http://oss-cn-beijing.aliyuncs.com");
assertThat(ossClient.getClientConfiguration().getUserAgent())
.isEqualTo("alibaba");
assertThat(ossClient.getCredentialsProvider().getCredentials()
.getAccessKeyId()).isEqualTo("your-ak");
assertThat(ossClient.getCredentialsProvider().getCredentials()
.getSecretAccessKey()).isEqualTo("your-sk");
OSSClient ossClient1 = (OSSClient) context.getBean("ossClient2",
OSS.class);
assertThat(ossClient1.getEndpoint().toString())
.isEqualTo("http://oss-cn-beijing.aliyuncs.com");
assertThat(ossClient1.getClientConfiguration().getUserAgent())
.isEqualTo("alibaba1");
assertThat(ossClient1.getCredentialsProvider().getCredentials()
.getAccessKeyId()).isEqualTo("your-ak1");
assertThat(ossClient1.getCredentialsProvider().getCredentials()
.getSecretAccessKey()).isEqualTo("your-sk1");
});
}
@Configuration
protected static class MultiClientConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.cloud.alibaba.oss")
public OSSProperties ossProperties1() {
return new OSSProperties();
}
@Bean
public OSS ossClient1(@Qualifier("ossProperties1") OSSProperties ossProperties) {
return new OSSClientBuilder().build(ossProperties.getEndpoint(),
ossProperties.getAccessKeyId(), ossProperties.getSecretAccessKey(),
ossProperties.getSecurityToken(), ossProperties.getConfiguration());
}
@Bean
@ConfigurationProperties(prefix = "spring.cloud.alibaba.oss1")
public OSSProperties ossProperties2() {
return new OSSProperties();
}
@Bean
public OSS ossClient2(@Qualifier("ossProperties2") OSSProperties ossProperties) {
return new OSSClientBuilder().build(ossProperties.getEndpoint(),
ossProperties.getAccessKeyId(), ossProperties.getSecretAccessKey(),
ossProperties.getSecurityToken(), ossProperties.getConfiguration());
}
}
}

@ -12,5 +12,7 @@
<description>Spring Cloud Alibaba Cloud Starters</description>
<modules>
<module>spring-cloud-starter-alicloud-oss</module>
<module>spring-cloud-starter-alicloud-acm</module>
<module>spring-cloud-starter-alicloud-ans</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.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
<name>Spring Cloud Starter Alibaba Cloud ACM</name>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-acm</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-starter-alibaba</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
<name>Spring Cloud Starter Alibaba Cloud ANS</name>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alicloud-ans</artifactId>
</dependency>
</dependencies>
</project>
Loading…
Cancel
Save