diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..44439fd8d --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,40 @@ +version: 2 +jobs: + build: + docker: + - image: springcloud/pipeline-base + user: appuser + environment: + _JAVA_OPTIONS: "-Xms1024m -Xmx2048m" + TERM: dumb + branches: + ignore: + - gh-pages # list of branches to ignore + resource_class: large + steps: + - checkout + - restore_cache: + key: sc-alibaba-{{ .Branch }} + - run: + name: "Download dependencies" + command: ./mvnw -Pspring -U --fail-never dependency:go-offline || true + - save_cache: + key: sc-alibaba-{{ .Branch }} + paths: + - ~/.m2 + - run: + name: "Running build" + command: ./mvnw -Pspring clean install -U -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn + - run: + name: "Aggregate test results" + when: always + command: | + mkdir -p ~/junit/ + find . -type f -regex ".*/target/.*-reports/.*" -exec cp {} ~/junit/ \; + bash <(curl -s https://codecov.io/bash) + - store_artifacts: + path: ~/junit/ + destination: artifacts + - store_test_results: + path: ~/junit/ + destination: testartifacts \ No newline at end of file diff --git a/.gitignore b/.gitignore index e4b662ae1..e02b722f5 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ hs_err_pid* .project .settings target +.DS_Store diff --git a/README-zh.md b/README-zh.md index 54a9cfa12..c6afae181 100644 --- a/README-zh.md +++ b/README-zh.md @@ -8,7 +8,7 @@ Spring Cloud Alibaba 致力于提供分布式应用服务开发的一站式解 ## 主要功能 * **服务限流降级**:默认支持为 HTTP 服务的提供限流保护,也支持添加注解实现方法的自定义限流降级,且支持动态修改限流降级规则。 -* **服务注册与发现**:适配 sprig cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。 +* **服务注册与发现**:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。 * **分布式配置管理**:支持分布式系统中的外部化配置,配置更改时自动刷新。 * **阿里云对象存储**:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。 diff --git a/README.md b/README.md index c0941db39..c69092a13 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Spring Cloud Alibaba +A project maintained by Alibaba. + See the [中文文档](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/README-zh.md) for Chinese readme. Spring Cloud Alibaba provides a one-stop solution for distributed application development. It contains all the components required to develop distributed applications, making it easy for you to develop your applications using Spring Cloud. diff --git a/pom.xml b/pom.xml index 1353ad3e7..c10db5423 100644 --- a/pom.xml +++ b/pom.xml @@ -8,13 +8,13 @@ org.springframework.cloud spring-cloud-build - 2.0.0.RELEASE + 2.0.4.RELEASE org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT pom Spring Cloud Alibaba @@ -28,12 +28,12 @@ - https://github.com/spring-cloud-incubator/spring-cloud-alibabacloud + https://github.com/spring-cloud-incubator/spring-cloud-alibaba - scm:git:git://github.com/spring-cloud-incubator/spring-cloud-alibabacloud.git + scm:git:git://github.com/spring-cloud-incubator/spring-cloud-alibaba.git - scm:git:ssh://git@github.com/spring-cloud-incubator/spring-cloud-alibabacloud.git + scm:git:ssh://git@github.com/spring-cloud-incubator/spring-cloud-alibaba.git HEAD @@ -47,6 +47,10 @@ fangjian fangjian0423@gmail.com + + xiaolongzuo + 150349407@qq.com + hengyunabc hengyunabc@gmail.com @@ -55,9 +59,9 @@ - 2.0.0.RELEASE - 2.0.0.RELEASE - 2.0.0.RELEASE + 2.0.2.RELEASE + 2.0.2.RELEASE + 2.0.2.RELEASE 4.12 3.0 @@ -74,7 +78,7 @@ spring-cloud-alibaba-dependencies spring-cloud-alibaba-sentinel - + spring-cloud-alibaba-sentinel-datasource spring-cloud-alibaba-nacos-config spring-cloud-alibaba-nacos-discovery spring-cloud-alibaba-examples @@ -82,6 +86,9 @@ spring-cloud-starter-alibaba spring-cloud-starter-alicloud spring-cloud-alicloud-oss + spring-cloud-alicloud-context + spring-cloud-alicloud-acm + spring-cloud-alicloud-ans @@ -154,4 +161,69 @@ + + + + spring + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + true + + + false + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + true + + + false + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release-local + + false + + + + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 167f71e9d..33b5ad6af 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -6,24 +6,60 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.0.0.RELEASE + 2.0.4.RELEASE spring-cloud-alibaba-dependencies - 0.2.0 + 0.2.1.BUILD-SNAPSHOT pom Spring Cloud Alibaba Dependencies Spring Cloud Alibaba Dependencies - 0.2.0 + 1.3.0-GA 3.1.0 - 0.2.1 + 0.3.0 + 1.0.8 + 0.1.1 + 4.0.1 + 1.0.0 + 2.16.0 - + + + com.alibaba.cloud + alicloud-context + ${alicloud.context.version} + + + com.aliyun + aliyun-java-sdk-edas + ${aliyun.sdk.edas.version} + + + com.aliyun + aliyun-java-sdk-core + + + + + com.aliyun + aliyun-java-sdk-core + ${aliyun.sdk.version} + + + com.alibaba.ans + ans-sdk + ${ans.version} + + + com.alibaba.edas.acm + acm-sdk + ${acm.version} + com.alibaba.nacos nacos-client @@ -95,6 +131,11 @@ spring-cloud-alibaba-sentinel ${project.version} + + org.springframework.cloud + spring-cloud-alibaba-sentinel-datasource + ${project.version} + org.springframework.cloud spring-cloud-alicloud-oss @@ -110,6 +151,21 @@ spring-cloud-alibaba-nacos-config ${project.version} + + org.springframework.cloud + spring-cloud-alicloud-acm + ${project.version} + + + org.springframework.cloud + spring-cloud-alicloud-ans + ${project.version} + + + org.springframework.cloud + spring-cloud-alicloud-context + ${project.version} + @@ -135,9 +191,17 @@ ${project.version} + + org.springframework.cloud + spring-cloud-starter-alicloud-ans + ${project.version} + - - + + org.springframework.cloud + spring-cloud-starter-alicloud-acm + ${project.version} + diff --git a/spring-cloud-alibaba-examples/acm-example/acm-local-example/pom.xml b/spring-cloud-alibaba-examples/acm-example/acm-local-example/pom.xml new file mode 100644 index 000000000..35296f912 --- /dev/null +++ b/spring-cloud-alibaba-examples/acm-example/acm-local-example/pom.xml @@ -0,0 +1,27 @@ + + + + spring-cloud-alibaba-examples + org.springframework.cloud + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + acm-local-example + + + + org.springframework.cloud + spring-cloud-starter-alicloud-acm + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/AcmApplication.java b/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/AcmApplication.java new file mode 100644 index 000000000..5d48c381d --- /dev/null +++ b/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/AcmApplication.java @@ -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); + } + +} diff --git a/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoController.java b/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoController.java new file mode 100644 index 000000000..b7c874610 --- /dev/null +++ b/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoController.java @@ -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; + } +} diff --git a/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/resources/bootstrap.properties b/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/resources/bootstrap.properties new file mode 100644 index 000000000..448a0c7dd --- /dev/null +++ b/spring-cloud-alibaba-examples/acm-example/acm-local-example/src/main/resources/bootstrap.properties @@ -0,0 +1,5 @@ +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 \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/pom.xml b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/pom.xml new file mode 100644 index 000000000..21ea6aae7 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/pom.xml @@ -0,0 +1,31 @@ + + + + spring-cloud-alibaba-examples + org.springframework.cloud + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + ans-consumer-feign-example + + + + org.springframework.cloud + spring-cloud-starter-alicloud-ans + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ConsumerApplication.java b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ConsumerApplication.java new file mode 100644 index 000000000..e95b2e9cf --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ConsumerApplication.java @@ -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); + } + +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoService.java b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoService.java new file mode 100644 index 000000000..78b3c486a --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoService.java @@ -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); + +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/HomeController.java b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/HomeController.java new file mode 100644 index 000000000..8f2a3e8c2 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/HomeController.java @@ -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 + "
" + result; + } +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/resources/application.properties new file mode 100644 index 000000000..542653d94 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-feign-example/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.port=18083 +# The following configuration can be omitted. +spring.cloud.alicloud.ans.server.list=127.0.0.1 +spring.cloud.alicloud.ans.server.port=8080 \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/pom.xml b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/pom.xml new file mode 100644 index 000000000..775a2739e --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/pom.xml @@ -0,0 +1,27 @@ + + + + spring-cloud-alibaba-examples + org.springframework.cloud + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + ans-consumer-ribbon-example + + + + org.springframework.cloud + spring-cloud-starter-alicloud-ans + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ConsumerApplication.java b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ConsumerApplication.java new file mode 100644 index 000000000..223a2d891 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ConsumerApplication.java @@ -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); + } + +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/HomeController.java b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/HomeController.java new file mode 100644 index 000000000..e3853fdd3 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/HomeController.java @@ -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 + "
" + result; + } +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/resources/application.properties new file mode 100644 index 000000000..315a90331 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-consumer-ribbon-example/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.port=18082 +# The following configuration can be omitted. +spring.cloud.alicloud.ans.server.list=127.0.0.1 +spring.cloud.alicloud.ans.server.port=8080 \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/ans-example/ans-provider-example/pom.xml b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/pom.xml new file mode 100644 index 000000000..cbe5509ca --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/pom.xml @@ -0,0 +1,27 @@ + + + + spring-cloud-alibaba-examples + org.springframework.cloud + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + ans-provider-example + + + + org.springframework.cloud + spring-cloud-starter-alicloud-ans + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoController.java b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoController.java new file mode 100644 index 000000000..a9c031ead --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/EchoController.java @@ -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; + } +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ProviderApplication.java b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ProviderApplication.java new file mode 100644 index 000000000..03436dcb4 --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/ProviderApplication.java @@ -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); + } + +} diff --git a/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/resources/application.properties new file mode 100644 index 000000000..2fb389e2e --- /dev/null +++ b/spring-cloud-alibaba-examples/ans-example/ans-provider-example/src/main/resources/application.properties @@ -0,0 +1,4 @@ +spring.application.name=ans-provider +server.port=18081 +spring.cloud.alicloud.ans.server.list=127.0.0.1 +spring.cloud.alicloud.ans.server.port=8080 \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/pom.xml index a011d829a..7ee827cb9 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md index bef4f89d1..e7339058c 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md @@ -19,9 +19,10 @@ spring-cloud-starter-alibaba-nacos-config -2. 在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 地址 +2. 在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 元数据 - spring.cloud.nacos.config.server-addr=127.0.0.1:8848 + spring.application.name=nacos-config-example + spring.cloud.nacos.config.server-addr=127.0.0.1:8848 3. 完成上述两步后,应用会从 Nacos Config 中获取相应的配置,并添加在 Spring Environment 的 PropertySources 中。这里我们使用 @Value 注解来将对应的配置注入到 SampleController 的 userName 和 age 字段,并添加 @RefreshScope 打开动态刷新功能 @@ -70,8 +71,8 @@ 1. 增加配置,在应用的 /src/main/resources/application.properties 中添加基本配置信息 - spring.application.name=nacos-config-example - server.port=18084 + server.port=18084 + management.endpoints.web.exposure.include=* 2. 启动应用,支持 IDE 直接启动和编译打包后启动。 @@ -118,9 +119,9 @@ Nacos Client 从 Nacos Server 端获取数据时,调用的是此接口 `Config * `spring.active.profile` 即为当前环境对应的 profile,详情可以参考 [Spring Boot文档](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles) - **注意,当 activeprofile 为空时,对应的连接符 `-` 也将不存在,dataId 的拼接格式变成 `${prefix}`.`${context.type}`** + **注意,当 activeprofile 为空时,对应的连接符 `-` 也将不存在,dataId 的拼接格式变成 `${prefix}`.`${file-extension}`** -* `file-extension` 为配置内容的数据格式,可以通过配置项 `spring.cloud.nacos.config.content-type`来配置。 +* `file-extension` 为配置内容的数据格式,可以通过配置项 `spring.cloud.nacos.config.file-extension`来配置。 目前只支持 `properties` 类型。 #### group @@ -168,7 +169,7 @@ Spring Boot 2.x 可以通过访问 http://127.0.0.1:18084/actuator/nacos-config 服务端地址|spring.cloud.nacos.config.server-addr|| DataId前缀|spring.cloud.nacos.config.prefix||spring.application.name Group|spring.cloud.nacos.config.group|DEFAULT_GROUP| -dataID后缀及数据格式|spring.cloud.nacos.config.file-extension|properties|目前只支持 properties +dataID后缀及内容文件格式|spring.cloud.nacos.config.file-extension|properties|dataId的后缀,同时也是配置内容的文件格式,目前只支持 properties 配置内容的编码方式|spring.cloud.nacos.config.encode|UTF-8|配置的编码 获取配置的超时时间|spring.cloud.nacos.config.timeout|3000|单位为 ms 配置的命名空间|spring.cloud.nacos.config.namespace||常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源隔离等。 diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md index 05bda7fc7..58b499aef 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md @@ -19,9 +19,10 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl spring-cloud-starter-alibaba-nacos-config -2. Add Nacos server address configurations to file /src/main/resources/bootstrap.properties +2. Add Nacos config metadata configurations to file /src/main/resources/bootstrap.properties - spring.cloud.nacos.config.server-addr=127.0.0.1:8848 + spring.application.name=nacos-config-example + spring.cloud.nacos.config.server-addr=127.0.0.1:8848 3. After completing the above two steps, the application will get the externalized configuration from Nacos Server and put it in the Spring Environment's PropertySources.We use the @Value annotation to inject the corresponding configuration into the userName and age fields of the SampleController, and add @RefreshScope to turn on dynamic refresh . @RefreshScope @@ -70,8 +71,8 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl 1. Add necessary configurations to file /src/main/resources/application.properties - spring.application.name=nacos-config-example - server.port=18084 + server.port=18084 + management.endpoints.web.exposure.include=* 2. Start the application in IDE or by building a fatjar. @@ -119,9 +120,9 @@ In Nacos Config Starter, the splicing format of dataId is as follows * `spring.active.profile` is the profile corresponding to the current environment. For details, please refer to [Spring Boot Doc](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles) - **Note: when the activeprofile is empty, the corresponding connector `-` will also not exist, and the splicing format of the dataId becomes `${prefix}`.`${context.type}`** + **Note: when the activeprofile is empty, the corresponding connector `-` will also not exist, and the splicing format of the dataId becomes `${prefix}`.`${file-extension}`** -* `file-extension` is the data format of the configuration content, which can be configured by the configuration item `spring.cloud.nacos.config.content-type`. +* `file-extension` is the data format of the configuration content, which can be configured by the configuration item `spring.cloud.nacos.config.file-extension`. Currently only the `properties` type is supported. #### group diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/application.properties index a0e934e2a..c6e216ad7 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/application.properties @@ -1,3 +1,2 @@ -spring.application.name=nacos-config-example server.port=18084 management.endpoints.web.exposure.include=* \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties index 8d94d562d..6adb653ca 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties @@ -1 +1,2 @@ +spring.application.name=nacos-config-example spring.cloud.nacos.config.server-addr=127.0.0.1:8848 \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml index 65fbbfb0d..2699f7c35 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud nacos-discovery-example - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml index c2e5952aa..1266769bf 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud nacos-discovery-example - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml index d4041f669..5ad506a9e 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md index a04451d36..47b431792 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md @@ -197,7 +197,7 @@ AccessKey|spring.cloud.nacos.discovery.access-key|| SecretKey|spring.cloud.nacos.discovery.secret-key|| Metadata|spring.cloud.nacos.discovery.metadata||使用Map格式配置 日志文件名|spring.cloud.nacos.discovery.log-name|| -接入点|spring.cloud.nacos.discovery.enpoint|UTF-8|地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 +接入点|spring.cloud.nacos.discovery.endpoint|UTF-8|地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 是否集成Ribbon|ribbon.nacos.enabled|true| diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md index cd26ef587..da81f49b7 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme.md @@ -205,7 +205,7 @@ AccessKey|spring.cloud.nacos.discovery.access-key|| SecretKey|spring.cloud.nacos.discovery.secret-key|| Metadata|spring.cloud.nacos.discovery.metadata||Extended data, Configure using Map format log name|spring.cloud.nacos.discovery.log-name|| -endpoint|spring.cloud.nacos.discovery.enpoint||The domain name of a service, through which the server address can be dynamically obtained. +endpoint|spring.cloud.nacos.discovery.endpoint||The domain name of a service, through which the server address can be dynamically obtained. Integration Ribbon|ribbon.nacos.enabled|true| diff --git a/spring-cloud-alibaba-examples/oss-example/pom.xml b/spring-cloud-alibaba-examples/oss-example/pom.xml index 33442b3ad..16e7b8974 100644 --- a/spring-cloud-alibaba-examples/oss-example/pom.xml +++ b/spring-cloud-alibaba-examples/oss-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OSSApplication.java b/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OSSApplication.java deleted file mode 100644 index 0e4546fac..000000000 --- a/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OSSApplication.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.springframework.cloud.alibaba.cloud.examples; - -import java.net.URISyntaxException; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -import com.aliyun.oss.OSS; - -/** - * OSS Application - * - * @author Jim - */ -@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); - } - } - } - -} diff --git a/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OSSController.java b/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OSSController.java deleted file mode 100644 index 1f3aac896..000000000 --- a/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OSSController.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.springframework.cloud.alibaba.cloud.examples; - -import java.nio.charset.Charset; - -import org.apache.commons.codec.CharEncoding; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.Resource; -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; - -/** - * OSS Controller - * - * @author Jim - */ -@RestController -public class OSSController { - - @Autowired - private OSS ossClient; - - @Value("oss://" + OSSApplication.BUCKET_NAME + "/oss-test") - private Resource file; - - private String dir = "custom-dir/"; - - @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("/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(); - } - } - -} diff --git a/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OssApplication.java b/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OssApplication.java new file mode 100644 index 000000000..f9265800d --- /dev/null +++ b/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OssApplication.java @@ -0,0 +1,49 @@ +package org.springframework.cloud.alibaba.cloud.examples; + +import com.aliyun.oss.OSS; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import java.net.URISyntaxException; + +/** + * OSS Application + * + * @author Jim + */ +@SpringBootApplication +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); + } + } + } + +} diff --git a/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OssController.java b/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OssController.java new file mode 100644 index 000000000..7c6e427a9 --- /dev/null +++ b/spring-cloud-alibaba-examples/oss-example/src/main/java/org/springframework/cloud/alibaba/cloud/examples/OssController.java @@ -0,0 +1,65 @@ +package org.springframework.cloud.alibaba.cloud.examples; + +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; +import org.springframework.core.io.Resource; +import org.springframework.util.StreamUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.nio.charset.Charset; + +/** + * OSS Controller + * + * @author Jim + */ +@RestController +public class OssController { + + @Autowired + private OSS ossClient; + + @Value("oss://" + OssApplication.BUCKET_NAME + "/oss-test.json") + private Resource file; + + @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("/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(); + } + } + +} diff --git a/spring-cloud-alibaba-examples/oss-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/oss-example/src/main/resources/application.properties index 4b269483e..59c650d3d 100644 --- a/spring-cloud-alibaba-examples/oss-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/oss-example/src/main/resources/application.properties @@ -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=* \ No newline at end of file +spring.cloud.alicloud.access-key=AK +spring.cloud.alicloud.secret-key=SK +spring.cloud.alicloud.oss.endpoint=***.aliyuncs.com +management.endpoints.web.exposure.include=* diff --git a/spring-cloud-alibaba-examples/oss-example/src/main/resources/oss-test.json b/spring-cloud-alibaba-examples/oss-example/src/main/resources/oss-test.json index eb0fe5f89..f1683e94f 100644 --- a/spring-cloud-alibaba-examples/oss-example/src/main/resources/oss-test.json +++ b/spring-cloud-alibaba-examples/oss-example/src/main/resources/oss-test.json @@ -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" } \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/pom.xml b/spring-cloud-alibaba-examples/pom.xml index f02eadbb3..acdcb6049 100644 --- a/spring-cloud-alibaba-examples/pom.xml +++ b/spring-cloud-alibaba-examples/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 @@ -23,6 +23,10 @@ nacos-example/nacos-discovery-example nacos-example/nacos-config-example oss-example + ans-example/ans-consumer-feign-example + ans-example/ans-consumer-ribbon-example + ans-example/ans-provider-example + acm-example/acm-local-example diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml index 314ee8f82..91ae63304 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md index 4c0b2aeba..c07c20e37 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md @@ -222,7 +222,7 @@ Sentinel starter 整合了目前存在的几类 DataSource。只需要在配置 `spring.cloud.sentinel.datasource.converter`代表 `Converter` 在 Spring 容器里的 name。如果没找到,会抛出异常。 -type目前支持file, nacos, zk, apollo。 +type目前支持file, nacos, zk, apollo。其中nacos,zk,apollo的使用需要加上对应的依赖`sentinel-datasource-nacos`, `sentinel-datasource-zookeeper`, `sentinel-datasource-apollo` ### 自定义DataSource diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md index a51ed38ad..dcdd77fc3 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md @@ -193,7 +193,8 @@ spring.cloud.sentinel.datasource.recommendRefreshMs means the recommendRefreshMs spring.cloud.sentinel.datasource.converter means the name of spring bean that type is Converter. If the bean is not exists, will throw exception. -Now datasource type support 4 categories: file, nacos, zk, apollo. +Now datasource type support 4 categories: file, nacos, zk, apollo. If you want to using nacos, zk or apollo, you should add `sentinel-datasource-nacos`, `sentinel-datasource-zookeeper` or `sentinel-datasource-apollo` dependency. + ### User-defined DataSource diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-api/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-api/pom.xml index 6c989f5da..898734b09 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-api/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-api/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml index ba88981a0..d69b92ba3 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml index c59f4ba61..2c48b6b71 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-examples - 0.2.0 + 0.2.1.BUILD-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/spring-cloud-alibaba-nacos-config/pom.xml b/spring-cloud-alibaba-nacos-config/pom.xml index 6bbc12173..59663771c 100644 --- a/spring-cloud-alibaba-nacos-config/pom.xml +++ b/spring-cloud-alibaba-nacos-config/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfiguration.java index f08969121..5dbdb50af 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.cloud.alibaba.nacos; -import com.alibaba.nacos.api.config.ConfigService; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher; @@ -43,14 +41,6 @@ public class NacosConfigAutoConfiguration implements ApplicationContextAware { @Autowired private NacosRefreshProperties nacosRefreshProperties; - @Autowired - private ConfigService configService; - - @Bean - public NacosConfigProperties nacosConfigProperties() { - return new NacosConfigProperties(); - } - @Bean public NacosPropertySourceRepository nacosPropertySourceRepository() { return new NacosPropertySourceRepository(applicationContext); @@ -69,10 +59,10 @@ public class NacosConfigAutoConfiguration implements ApplicationContextAware { @Bean public NacosContextRefresher nacosContextRefresher(ContextRefresher contextRefresher, NacosRefreshHistory refreshHistory, - NacosPropertySourceRepository propertySourceRepository, - ConfigService configService) { + NacosPropertySourceRepository propertySourceRepository) { return new NacosContextRefresher(contextRefresher, nacosConfigProperties, - nacosRefreshProperties, refreshHistory, propertySourceRepository,configService); + nacosRefreshProperties, refreshHistory, propertySourceRepository, + nacosConfigProperties.configServiceInstance()); } @Override diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java index d5e3bd3b8..e643d35a8 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.alibaba.nacos; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,6 +33,7 @@ public class NacosConfigBootstrapConfiguration { } @Bean + @ConditionalOnMissingBean public NacosConfigProperties nacosConfigProperties() { return new NacosConfigProperties(); } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java index 446483d69..e279d9cbe 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/NacosConfigProperties.java @@ -16,9 +16,30 @@ package org.springframework.cloud.alibaba.nacos; +import java.util.Arrays; +import java.util.Objects; +import java.util.Properties; + +import javax.annotation.PostConstruct; + +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.config.ConfigService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.core.env.Environment; -import org.springframework.util.StringUtils; + +import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY; +import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME; +import static com.alibaba.nacos.api.PropertyKeyConst.CONTEXT_PATH; +import static com.alibaba.nacos.api.PropertyKeyConst.ENCODE; +import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT; +import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE; +import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY; +import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR; /** * nacos properties @@ -29,6 +50,9 @@ import org.springframework.util.StringUtils; @ConfigurationProperties("spring.cloud.nacos.config") public class NacosConfigProperties { + private static final Logger LOGGER = LoggerFactory + .getLogger(NacosConfigProperties.class); + /** * nacos config server address */ @@ -89,6 +113,21 @@ public class NacosConfigProperties { */ private String clusterName; + @Value("${spring.application.name}") + private String name; + + private String[] activeProfiles; + + private ConfigService configService; + + @Autowired + private Environment environment; + + @PostConstruct + public void init() { + this.activeProfiles = environment.getActiveProfiles(); + } + // todo sts support public String getServerAddr() { @@ -187,6 +226,14 @@ public class NacosConfigProperties { this.clusterName = clusterName; } + public String getName() { + return name; + } + + public String[] getActiveProfiles() { + return activeProfiles; + } + @Override public String toString() { return "NacosConfigProperties{" + "serverAddr='" + serverAddr + '\'' @@ -195,46 +242,32 @@ public class NacosConfigProperties { + ", timeout=" + timeout + ", endpoint='" + endpoint + '\'' + ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\'' + ", secretKey='" + secretKey + '\'' + ", contextPath='" + contextPath - + '\'' + ", clusterName='" + clusterName + '\'' + '}'; + + '\'' + ", clusterName='" + clusterName + '\'' + ", name='" + name + '\'' + + ", activeProfiles=" + Arrays.toString(activeProfiles) + '}'; } - public void overrideFromEnv(Environment env) { + public ConfigService configServiceInstance() { - if (StringUtils.isEmpty(this.getServerAddr())) { - this.setServerAddr( - env.resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}")); - } - if (StringUtils.isEmpty(this.getEncode())) { - this.setEncode( - env.resolvePlaceholders("${spring.cloud.nacos.config.encode:}")); - } - if (StringUtils.isEmpty(this.getNamespace())) { - this.setNamespace( - env.resolvePlaceholders("${spring.cloud.nacos.config.namespace:}")); + if (null != configService) { + return configService; } - if (StringUtils.isEmpty(this.getAccessKey())) { - this.setAccessKey( - env.resolvePlaceholders("${spring.cloud.nacos.config.access-key:}")); - } - if (StringUtils.isEmpty(this.getSecretKey())) { - this.setSecretKey( - env.resolvePlaceholders("${spring.cloud.nacos.config.secret-key:}")); - } - if (StringUtils.isEmpty(this.getContextPath())) { - this.setContextPath(env - .resolvePlaceholders("${spring.cloud.nacos.config.context-path:}")); - } - if (StringUtils.isEmpty(this.getClusterName())) { - this.setClusterName(env - .resolvePlaceholders("${spring.cloud.nacos.config.cluster-name:}")); - } - if (StringUtils.isEmpty(this.getEndpoint())) { - this.setEndpoint( - env.resolvePlaceholders("${spring.cloud.nacos.config.endpoint:}")); + + Properties properties = new Properties(); + properties.put(SERVER_ADDR, Objects.toString(this.serverAddr, "")); + properties.put(ENCODE, Objects.toString(this.encode, "")); + properties.put(NAMESPACE, Objects.toString(this.namespace, "")); + properties.put(ACCESS_KEY, Objects.toString(this.accessKey, "")); + properties.put(SECRET_KEY, Objects.toString(this.secretKey, "")); + properties.put(CONTEXT_PATH, Objects.toString(this.contextPath, "")); + properties.put(CLUSTER_NAME, Objects.toString(this.clusterName, "")); + properties.put(ENDPOINT, Objects.toString(this.endpoint, "")); + try { + configService = NacosFactory.createConfigService(properties); + return configService; } - if (StringUtils.isEmpty(this.getPrefix())) { - this.setPrefix( - env.resolvePlaceholders("${spring.cloud.nacos.config.prefix:}")); + catch (Exception e) { + LOGGER.error("create config service error!properties={},e=,", this, e); + return null; } } } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java index 4e5d63b67..16bf97d09 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceBuilder.java @@ -83,7 +83,6 @@ public class NacosPropertySourceBuilder { String data = null; try { data = configService.getConfig(dataId, group, timeout); - // todo add content type yaml support if (!StringUtils.isEmpty(data)) { logger.info(String.format("Loading nacos data, dataId: '%s', group: '%s'", dataId, group)); @@ -95,7 +94,7 @@ public class NacosPropertySourceBuilder { return properties; } else if (fileExtension.equalsIgnoreCase("yaml") - || fileExtension.equalsIgnoreCase("yml")) { + || fileExtension.equalsIgnoreCase("yml")) { YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); yamlFactory.setResources(new ByteArrayResource(data.getBytes())); return yamlFactory.getObject(); diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java index f507f1522..304fc5672 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/client/NacosPropertySourceLocator.java @@ -16,12 +16,9 @@ package org.springframework.cloud.alibaba.nacos.client; -import java.util.Properties; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.cloud.alibaba.nacos.NacosConfigProperties; import org.springframework.cloud.bootstrap.config.PropertySourceLocator; import org.springframework.core.annotation.Order; @@ -30,11 +27,7 @@ import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; import org.springframework.util.StringUtils; -import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.exception.NacosException; - -import static com.alibaba.nacos.api.PropertyKeyConst.*; /** * @author xiaojing @@ -48,47 +41,15 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { private static final String SEP1 = "-"; private static final String DOT = "."; - @Autowired - private ConfigurableListableBeanFactory beanFactory; - @Autowired private NacosConfigProperties nacosConfigProperties; - private ConfigService configService; - private NacosPropertySourceBuilder nacosPropertySourceBuilder; - private Properties getPropertiesFromEnv(Environment env) { - - nacosConfigProperties.overrideFromEnv(env); - - Properties properties = new Properties(); - properties.put(SERVER_ADDR, nacosConfigProperties.getServerAddr()); - properties.put(ENCODE, nacosConfigProperties.getEncode()); - properties.put(NAMESPACE, nacosConfigProperties.getNamespace()); - properties.put(ACCESS_KEY, nacosConfigProperties.getAccessKey()); - properties.put(SECRET_KEY, nacosConfigProperties.getSecretKey()); - properties.put(CONTEXT_PATH, nacosConfigProperties.getContextPath()); - properties.put(CLUSTER_NAME, nacosConfigProperties.getClusterName()); - properties.put(ENDPOINT, nacosConfigProperties.getEndpoint()); - return properties; - } - @Override public PropertySource locate(Environment env) { - Properties properties = getPropertiesFromEnv(env); - - try { - configService = NacosFactory.createConfigService(properties); - } - catch (NacosException e) { - logger.error("create config service error, nacosConfigProperties:{}, ", - properties, e); - return null; - } - - beanFactory.registerSingleton("configService", configService); + ConfigService configService = nacosConfigProperties.configServiceInstance(); if (null == configService) { logger.warn( @@ -99,13 +60,12 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService, timeout); - String applicationName = env.getProperty("spring.application.name"); - logger.info("Initialize spring.application.name '" + applicationName + "'."); + String name = nacosConfigProperties.getName(); String nacosGroup = nacosConfigProperties.getGroup(); String dataIdPrefix = nacosConfigProperties.getPrefix(); if (StringUtils.isEmpty(dataIdPrefix)) { - dataIdPrefix = applicationName; + dataIdPrefix = name; } String fileExtension = nacosConfigProperties.getFileExtension(); @@ -113,23 +73,21 @@ public class NacosPropertySourceLocator implements PropertySourceLocator { CompositePropertySource composite = new CompositePropertySource( NACOS_PROPERTY_SOURCE_NAME); - loadApplicationConfiguration(composite, env, nacosGroup, dataIdPrefix, - fileExtension); + loadApplicationConfiguration(composite, nacosGroup, dataIdPrefix, fileExtension); return composite; } private void loadApplicationConfiguration( - CompositePropertySource compositePropertySource, Environment environment, - String nacosGroup, String dataIdPrefix, String fileExtension) { + CompositePropertySource compositePropertySource, String nacosGroup, + String dataIdPrefix, String fileExtension) { loadNacosDataIfPresent(compositePropertySource, dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension); - for (String profile : environment.getActiveProfiles()) { + for (String profile : nacosConfigProperties.getActiveProfiles()) { String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension; loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup, fileExtension); } - // todo multi profile active order and priority } private void loadNacosDataIfPresent(final CompositePropertySource composite, diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpointAutoConfiguration.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpointAutoConfiguration.java index d6d8464bb..c0d92632f 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpointAutoConfiguration.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpointAutoConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.cloud.alibaba.nacos.endpoint; -import com.alibaba.nacos.api.config.ConfigService; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; @@ -46,15 +44,6 @@ public class NacosConfigEndpointAutoConfiguration { @Autowired private NacosPropertySourceRepository nacosPropertySourceRepository; - @Autowired - private ConfigService configService; - - @Bean - @ConditionalOnBean - public NacosConfigProperties nacosConfigProperties() { - return new NacosConfigProperties(); - } - @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint @Bean @@ -67,6 +56,7 @@ public class NacosConfigEndpointAutoConfiguration { public NacosConfigHealthIndicator nacosConfigHealthIndicator( NacosPropertySourceRepository nacosPropertySourceRepository) { return new NacosConfigHealthIndicator(nacosConfigProperties, - nacosPropertySourceRepository, configService); + nacosPropertySourceRepository, + nacosConfigProperties.configServiceInstance()); } } diff --git a/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfigurationTests.java b/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfigurationTests.java index 389e4fd20..66126759f 100644 --- a/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfigurationTests.java +++ b/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigAutoConfigurationTests.java @@ -39,66 +39,59 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class NacosConfigAutoConfigurationTests { - private ConfigurableApplicationContext context; - - @Before - public void setUp() throws Exception { - this.context = new SpringApplicationBuilder( - NacosConfigBootstrapConfiguration.class, - NacosConfigAutoConfiguration.class, - TestConfiguration.class) - .web(WebApplicationType.NONE).run( - "--spring.cloud.config.enabled=true", - "--spring.cloud.nacos.config.server-addr=127.0.0.1:8080", - "--spring.cloud.nacos.config.prefix=myapp"); - } - - @After - public void tearDown() throws Exception { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void testNacosConfigProperties() { - - NacosPropertySourceLocator nacosPropertySourceLocator = this.context.getBean(NacosPropertySourceLocator.class); - Environment environment = this.context.getEnvironment(); - try{ - nacosPropertySourceLocator.locate(environment); - }catch (Exception e){ - - } - - NacosConfigProperties nacosConfigProperties = this.context.getBean(NacosConfigProperties.class); - assertThat(nacosConfigProperties.getFileExtension()).isEqualTo("properties"); - assertThat(nacosConfigProperties.getPrefix()).isEqualTo("myapp"); - - } - - - @Test - public void testNacosRefreshProperties() { - - NacosRefreshProperties nacosRefreshProperties = this.context.getBean(NacosRefreshProperties.class); - assertThat(nacosRefreshProperties.isEnabled()).isEqualTo(true); - - } - - @Configuration - @AutoConfigureBefore(NacosConfigAutoConfiguration.class) - static class TestConfiguration{ - - - @Autowired - ConfigurableApplicationContext context; - - @Bean - ContextRefresher contextRefresher(){ - return new ContextRefresher(context, new RefreshScope()); - } - - } + private ConfigurableApplicationContext context; + + @Before + public void setUp() throws Exception { + this.context = new SpringApplicationBuilder( + NacosConfigBootstrapConfiguration.class, + NacosConfigAutoConfiguration.class, TestConfiguration.class) + .web(WebApplicationType.NONE) + .run("--spring.application.name=myapp", + "--spring.cloud.config.enabled=true", + "--spring.cloud.nacos.config.server-addr=127.0.0.1:8080", + "--spring.cloud.nacos.config.prefix=test"); + } + + @After + public void tearDown() throws Exception { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void testNacosConfigProperties() { + + NacosConfigProperties nacosConfigProperties = this.context.getParent() + .getBean(NacosConfigProperties.class); + assertThat(nacosConfigProperties.getFileExtension()).isEqualTo("properties"); + assertThat(nacosConfigProperties.getPrefix()).isEqualTo("test"); + assertThat(nacosConfigProperties.getName()).isEqualTo("myapp"); + + } + + @Test + public void testNacosRefreshProperties() { + + NacosRefreshProperties nacosRefreshProperties = this.context + .getBean(NacosRefreshProperties.class); + assertThat(nacosRefreshProperties.isEnabled()).isEqualTo(true); + + } + + @Configuration + @AutoConfigureBefore(NacosConfigAutoConfiguration.class) + static class TestConfiguration { + + @Autowired + ConfigurableApplicationContext context; + + @Bean + ContextRefresher contextRefresher() { + return new ContextRefresher(context, new RefreshScope()); + } + + } } diff --git a/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfigurationTests.java b/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfigurationTests.java index ae43f03f7..73cc98803 100644 --- a/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfigurationTests.java +++ b/spring-cloud-alibaba-nacos-config/src/test/java/org/springframework/cloud/alibaba/nacos/NacosConfigBootstrapConfigurationTests.java @@ -43,9 +43,10 @@ public class NacosConfigBootstrapConfigurationTests { public void setUp() throws Exception { this.context = new SpringApplicationBuilder( NacosConfigBootstrapConfiguration.class).web(WebApplicationType.NONE).run( + "--spring.application.name=myapp", "--spring.cloud.config.enabled=true", "--spring.cloud.nacos.config.server-addr=127.0.0.1:8080", - "--spring.cloud.nacos.config.prefix=myapp"); + "--spring.cloud.nacos.config.prefix=test"); } @After @@ -68,15 +69,14 @@ public class NacosConfigBootstrapConfigurationTests { } - Field configServiceField = ReflectionUtils - .findField(NacosPropertySourceLocator.class, "configService"); - configServiceField.setAccessible(true); + Field nacosConfigPropertiesField = ReflectionUtils + .findField(NacosPropertySourceLocator.class, "nacosConfigProperties"); + nacosConfigPropertiesField.setAccessible(true); - ConfigService configService = (ConfigService) ReflectionUtils - .getField(configServiceField, locator); + NacosConfigProperties configService = (NacosConfigProperties) ReflectionUtils + .getField(nacosConfigPropertiesField, locator); assertThat(configService).isNotNull(); } - } diff --git a/spring-cloud-alibaba-nacos-discovery/pom.xml b/spring-cloud-alibaba-nacos-discovery/pom.xml index e0aaa47d1..740c23982 100644 --- a/spring-cloud-alibaba-nacos-discovery/pom.xml +++ b/spring-cloud-alibaba-nacos-discovery/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java index 59ea1ec73..1d22cd67d 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryClient.java @@ -19,15 +19,11 @@ package org.springframework.cloud.alibaba.nacos; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.core.env.Environment; import java.util.*; -import javax.annotation.PostConstruct; - import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.ListView; @@ -44,17 +40,6 @@ public class NacosDiscoveryClient implements DiscoveryClient { @Autowired private NacosDiscoveryProperties discoveryProperties; - @Autowired - private Environment environment; - - private NamingService namingService; - - @PostConstruct - public void init() { - discoveryProperties.overrideFromEnv(environment); - namingService = discoveryProperties.getNamingService(); - } - @Override public String description() { return DESCRIPTION; @@ -63,7 +48,8 @@ public class NacosDiscoveryClient implements DiscoveryClient { @Override public List getInstances(String serviceId) { try { - List instances = namingService.getAllInstances(serviceId); + List instances = discoveryProperties.namingServiceInstance() + .getAllInstances(serviceId); return hostToServiceInstanceList(instances, serviceId); } catch (Exception e) { @@ -103,8 +89,8 @@ public class NacosDiscoveryClient implements DiscoveryClient { public List getServices() { try { - ListView services = namingService.getServicesOfServer(1, - Integer.MAX_VALUE); + ListView services = discoveryProperties.namingServiceInstance() + .getServicesOfServer(1, Integer.MAX_VALUE); return services.getData(); } catch (Exception e) { @@ -114,6 +100,6 @@ public class NacosDiscoveryClient implements DiscoveryClient { } public NamingService getNamingService() { - return namingService; + return discoveryProperties.namingServiceInstance(); } } diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java index aa9271a8d..fdb0d0e93 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java @@ -142,6 +142,11 @@ public class NacosDiscoveryProperties { @Autowired private InetUtils inetUtils; + @Autowired + private Environment environment; + + private NamingService namingService; + @PostConstruct public void init() throws SocketException { @@ -180,6 +185,8 @@ public class NacosDiscoveryProperties { } } + + this.overrideFromEnv(environment); } public String getEndpoint() { @@ -350,7 +357,12 @@ public class NacosDiscoveryProperties { } } - public NamingService getNamingService() { + public NamingService namingServiceInstance() { + + if (null != namingService) { + return namingService; + } + Properties properties = new Properties(); properties.put(SERVER_ADDR, serverAddr); properties.put(NAMESPACE, namespace); @@ -360,7 +372,8 @@ public class NacosDiscoveryProperties { properties.put(SECRET_KEY, secretKey); properties.put(CLUSTER_NAME, clusterName); try { - return NacosFactory.createNamingService(properties); + namingService = NacosFactory.createNamingService(properties); + return namingService; } catch (Exception e) { LOGGER.error("create naming service error!properties={},e=,", this, e); diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java index db384df5e..1cbcfb87d 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosDiscoveryEndpoint.java @@ -29,7 +29,6 @@ import org.slf4j.LoggerFactory; 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.cloud.alibaba.nacos.NacosDiscoveryClient; import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; /** @@ -45,9 +44,6 @@ public class NacosDiscoveryEndpoint { @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; - @Autowired - private NacosDiscoveryClient discoveryClient; - /** * @return nacos discovery endpoint */ @@ -56,7 +52,7 @@ public class NacosDiscoveryEndpoint { Map result = new HashMap<>(); result.put("NacosDiscoveryProperties", nacosDiscoveryProperties); - NamingService namingService = discoveryClient.getNamingService(); + NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); List subscribe = Collections.emptyList(); try { diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java index 639dad981..865358178 100644 --- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosRegistration.java @@ -48,15 +48,10 @@ public class NacosRegistration implements Registration, ServiceInstance { @Autowired private ApplicationContext context; - private NamingService nacosNamingService; - @PostConstruct public void init() { Environment env = context.getEnvironment(); - nacosDiscoveryProperties.overrideFromEnv(context.getEnvironment()); - nacosNamingService = nacosDiscoveryProperties.getNamingService(); - Integer managementPort = ManagementServerPortUtils.getPort(context); if (null != managementPort) { Map metadata = nacosDiscoveryProperties.getMetadata(); @@ -124,11 +119,7 @@ public class NacosRegistration implements Registration, ServiceInstance { } public NamingService getNacosNamingService() { - return nacosNamingService; - } - - public void setNacosNamingService(NamingService nacosNamingService) { - this.nacosNamingService = nacosNamingService; + return nacosDiscoveryProperties.namingServiceInstance(); } public void setNacosDiscoveryProperties( @@ -139,7 +130,6 @@ public class NacosRegistration implements Registration, ServiceInstance { @Override public String toString() { return "NacosRegistration{" + "nacosDiscoveryProperties=" - + nacosDiscoveryProperties + ", nacosNamingService=" + nacosNamingService - + '}'; + + nacosDiscoveryProperties + '}'; } } diff --git a/spring-cloud-alibaba-sentinel-datasource/pom.xml b/spring-cloud-alibaba-sentinel-datasource/pom.xml new file mode 100644 index 000000000..f2878dfe1 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -0,0 +1,69 @@ + + + + + org.springframework.cloud + spring-cloud-alibaba + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + + org.springframework.cloud + spring-cloud-alibaba-sentinel-datasource + Spring Cloud Alibaba Sentinel DataSource + + + + + com.alibaba.csp + sentinel-datasource-extension + + + + com.alibaba.csp + sentinel-datasource-nacos + provided + true + + + + com.alibaba.csp + sentinel-datasource-zookeeper + provided + true + + + + com.alibaba.csp + sentinel-datasource-apollo + provided + true + + + + + + org.springframework.boot + spring-boot + provided + true + + + + org.springframework.boot + spring-boot-autoconfigure + provided + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java new file mode 100644 index 000000000..40f17197d --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java @@ -0,0 +1,152 @@ +/* + * 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.sentinel.datasource; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import com.alibaba.csp.sentinel.datasource.ReadableDataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.PropertiesLoaderUtils; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; + +import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; + +/** + * {@link ReadableDataSource} Loader + * + * @author Jim + */ +public class DataSourceLoader { + + private static final Logger logger = LoggerFactory.getLogger(DataSourceLoader.class); + + private final static String PROPERTIES_RESOURCE_LOCATION = "META-INF/sentinel-datasource.properties"; + + private final static String ALL_PROPERTIES_RESOURCES_LOCATION = CLASSPATH_ALL_URL_PREFIX + + PROPERTIES_RESOURCE_LOCATION; + + private final static ConcurrentMap> dataSourceClassesCache + = new ConcurrentHashMap>( + 4); + + static void loadAllDataSourceClassesCache() { + Map> dataSourceClassesMap = loadAllDataSourceClassesCache( + ALL_PROPERTIES_RESOURCES_LOCATION); + + dataSourceClassesCache.putAll(dataSourceClassesMap); + } + + static Map> loadAllDataSourceClassesCache( + String resourcesLocation) { + + Map> dataSourcesMap + = new HashMap>( + 4); + + ClassLoader classLoader = DataSourceLoader.class.getClassLoader(); + + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + + try { + + Resource[] resources = resolver.getResources(resourcesLocation); + + for (Resource resource : resources) { + if (resource.exists()) { + Properties properties = PropertiesLoaderUtils + .loadProperties(resource); + for (Map.Entry entry : properties.entrySet()) { + + String type = (String)entry.getKey(); + String className = (String)entry.getValue(); + + if (!ClassUtils.isPresent(className, classLoader)) { + if (logger.isDebugEnabled()) { + logger.debug( + "Sentinel DataSource implementation [ type : " + + type + ": , class : " + className + + " , url : " + resource.getURL() + + "] was not present in current classpath , " + + "thus loading will be ignored , please add dependency if required !"); + } + continue; + } + + Assert.isTrue(!dataSourcesMap.containsKey(type), + "The duplicated type[" + type + + "] of SentinelDataSource were found in " + + "resource [" + resource.getURL() + "]"); + + Class dataSourceClass = ClassUtils.resolveClassName(className, + classLoader); + Assert.isAssignable(ReadableDataSource.class, dataSourceClass); + + dataSourcesMap.put(type, + (Class)dataSourceClass); + + if (logger.isDebugEnabled()) { + logger.debug("Sentinel DataSource implementation [ type : " + + type + ": , class : " + className + + "] was loaded."); + } + } + } + } + + } catch (IOException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + } + + return dataSourcesMap; + } + + public static Class loadClass(String type) + throws IllegalArgumentException { + + Class dataSourceClass = dataSourceClassesCache.get(type); + + if (dataSourceClass == null) { + if (dataSourceClassesCache.isEmpty()) { + loadAllDataSourceClassesCache(); + dataSourceClass = dataSourceClassesCache.get(type); + } + } + + if (dataSourceClass == null) { + throw new IllegalArgumentException( + "Sentinel DataSource implementation [ type : " + type + + " ] can't be found!"); + } + + return dataSourceClass; + + } + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java new file mode 100644 index 000000000..49549399f --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java @@ -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.alibaba.sentinel.datasource; + +/** + * @author Jim + */ +public interface SentinelDataSourceConstants { + + String PROPERTY_PREFIX = "spring.cloud.sentinel"; + + String PROPERTY_ITEM_SEPARATOR = "."; + + String PROPERTY_DATASOURCE_NAME = "datasource"; + + String PROPERTY_DATASOURCE_PREFIX = PROPERTY_PREFIX + PROPERTY_ITEM_SEPARATOR + + PROPERTY_DATASOURCE_NAME; + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java new file mode 100644 index 000000000..d54dd0299 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java @@ -0,0 +1,272 @@ +/* + * 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.sentinel.datasource; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.ReadableDataSource; +import com.alibaba.csp.sentinel.property.SentinelProperty; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.system.SystemRule; +import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.cloud.alibaba.sentinel.datasource.annotation.SentinelDataSource; +import org.springframework.cloud.alibaba.sentinel.datasource.util.PropertySourcesUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.context.event.EventListener; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; + +import static org.springframework.core.annotation.AnnotationUtils.getAnnotation; + +/** + * {@link SentinelDataSource @SentinelDataSource} Post Processor + * + * @author Jim + * @see ReadableDataSource + * @see SentinelDataSource + */ +public class SentinelDataSourcePostProcessor + extends InstantiationAwareBeanPostProcessorAdapter + implements MergedBeanDefinitionPostProcessor { + + private static final Logger logger = LoggerFactory + .getLogger(SentinelDataSourcePostProcessor.class); + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private ConfigurableEnvironment environment; + + private final Map> dataSourceFieldCache = new ConcurrentHashMap<>( + 64); + + @Override + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, + Class beanType, String beanName) { + // find all fields using by @SentinelDataSource annotation + ReflectionUtils.doWithFields(beanType, new ReflectionUtils.FieldCallback() { + @Override + public void doWith(Field field) + throws IllegalArgumentException, IllegalAccessException { + SentinelDataSource annotation = getAnnotation(field, + SentinelDataSource.class); + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + if (logger.isWarnEnabled()) { + logger.warn( + "@SentinelDataSource annotation is not supported on static fields: " + + field); + } + return; + } + if (dataSourceFieldCache.containsKey(beanName)) { + dataSourceFieldCache.get(beanName) + .add(new SentinelDataSourceField(annotation, field)); + } else { + List list = new ArrayList<>(); + list.add(new SentinelDataSourceField(annotation, field)); + dataSourceFieldCache.put(beanName, list); + } + } + } + }); + } + + @Override + public PropertyValues postProcessPropertyValues(PropertyValues pvs, + PropertyDescriptor[] pds, Object bean, String beanName) + throws BeanCreationException { + if (dataSourceFieldCache.containsKey(beanName)) { + List sentinelDataSourceFields = dataSourceFieldCache + .get(beanName); + sentinelDataSourceFields.forEach(sentinelDataSourceField -> { + try { + // construct DataSource field annotated by @SentinelDataSource + Field field = sentinelDataSourceField.getField(); + ReflectionUtils.makeAccessible(field); + String dataSourceBeanName = constructDataSource( + sentinelDataSourceField.getSentinelDataSource()); + field.set(bean, applicationContext.getBean(dataSourceBeanName)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + return pvs; + } + + private String constructDataSource(SentinelDataSource annotation) { + String prefix = annotation.value(); + if (StringUtils.isEmpty(prefix)) { + prefix = SentinelDataSourceConstants.PROPERTY_DATASOURCE_PREFIX; + } + Map propertyMap = PropertySourcesUtils + .getSubProperties(environment.getPropertySources(), prefix); + String alias = propertyMap.get("type").toString(); + Class dataSourceClass = DataSourceLoader.loadClass(alias); + + String beanName = StringUtils.isEmpty(annotation.name()) + ? StringUtils.uncapitalize(dataSourceClass.getSimpleName()) + "_" + prefix + : annotation.name(); + if (applicationContext.containsBean(beanName)) { + return beanName; + } + + Class targetClass = null; + // if alias exists in SentinelDataSourceRegistry, wired properties into + // FactoryBean + if (SentinelDataSourceRegistry.checkFactoryBean(alias)) { + targetClass = SentinelDataSourceRegistry.getFactoryBean(alias); + } else { + // if alias not exists in SentinelDataSourceRegistry, wired properties into + // raw class + targetClass = dataSourceClass; + } + + registerDataSource(beanName, targetClass, propertyMap); + + return beanName; + } + + private void registerDataSource(String beanName, Class targetClass, + Map propertyMap) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder + .genericBeanDefinition(targetClass); + for (String propertyName : propertyMap.keySet()) { + Field field = ReflectionUtils.findField(targetClass, propertyName); + if (field != null) { + if (field.getType().isAssignableFrom(Converter.class)) { + // Converter get from ApplicationContext + builder.addPropertyReference(propertyName, + propertyMap.get(propertyName).toString()); + } else { + // wired properties + builder.addPropertyValue(propertyName, propertyMap.get(propertyName)); + } + } + } + + DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)applicationContext + .getAutowireCapableBeanFactory(); + beanFactory.registerBeanDefinition(beanName, builder.getBeanDefinition()); + } + + @EventListener(classes = ApplicationStartedEvent.class) + public void appStartedListener(ApplicationStartedEvent event) throws Exception { + logger.info("[Sentinel Starter] Start to find ReadableDataSource"); + Map dataSourceMap = event.getApplicationContext().getBeansOfType( + ReadableDataSource.class); + if (dataSourceMap.size() == 1) { + logger.info("[Sentinel Starter] There exists only one ReadableDataSource named {}, start to load rules", + dataSourceMap.keySet().iterator().next()); + ReadableDataSource dataSource = dataSourceMap.values().iterator().next(); + Object ruleConfig = dataSource.loadConfig(); + SentinelProperty sentinelProperty = dataSource.getProperty(); + Integer rulesNum; + if ((rulesNum = checkRuleType(ruleConfig, FlowRule.class)) > 0) { + FlowRuleManager.register2Property(sentinelProperty); + logger.info("[Sentinel Starter] load {} flow rules", rulesNum); + } + if ((rulesNum = checkRuleType(ruleConfig, DegradeRule.class)) > 0) { + DegradeRuleManager.register2Property(sentinelProperty); + logger.info("[Sentinel Starter] load {} degrade rules", rulesNum); + } + if ((rulesNum = checkRuleType(ruleConfig, SystemRule.class)) > 0) { + SystemRuleManager.register2Property(sentinelProperty); + logger.info("[Sentinel Starter] load {} system rules", rulesNum); + } + if ((rulesNum = checkRuleType(ruleConfig, AuthorityRule.class)) > 0) { + AuthorityRuleManager.register2Property(sentinelProperty); + logger.info("[Sentinel Starter] load {} authority rules", rulesNum); + } + } else if (dataSourceMap.size() > 1) { + logger.warn( + "[Sentinel Starter] There exists more than one ReadableDataSource, can not choose which one to load"); + } else { + logger.warn( + "[Sentinel Starter] No ReadableDataSource exists"); + } + } + + private Integer checkRuleType(Object ruleConfig, Class type) { + if (ruleConfig.getClass() == type) { + return 1; + } else if (ruleConfig instanceof List) { + List ruleList = (List)ruleConfig; + if (ruleList.stream().filter(rule -> rule.getClass() == type).toArray().length == ruleList.size()) { + return ruleList.size(); + } + } + return -1; + } + + class SentinelDataSourceField { + private SentinelDataSource sentinelDataSource; + private Field field; + + public SentinelDataSourceField(SentinelDataSource sentinelDataSource, + Field field) { + this.sentinelDataSource = sentinelDataSource; + this.field = field; + } + + public SentinelDataSource getSentinelDataSource() { + return sentinelDataSource; + } + + public void setSentinelDataSource(SentinelDataSource sentinelDataSource) { + this.sentinelDataSource = sentinelDataSource; + } + + public Field getField() { + return field; + } + + public void setField(Field field) { + this.field = field; + } + } + +} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java similarity index 91% rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java rename to spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java index ceb90ee1f..5108196b5 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java @@ -16,7 +16,7 @@ package org.springframework.cloud.alibaba.sentinel.datasource; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; @@ -29,7 +29,7 @@ import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.Zookeep /** * Registry to save DataSource FactoryBean * - * @author fangjian + * @author Jim * @see ReadableDataSource * @see FileRefreshableDataSourceFactoryBean * @see ZookeeperDataSourceFactoryBean @@ -38,7 +38,7 @@ import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.Zookeep */ public class SentinelDataSourceRegistry { - private static ConcurrentHashMap> cache = new ConcurrentHashMap<>( + private static HashMap> cache = new HashMap<>( 32); static { @@ -54,7 +54,6 @@ public class SentinelDataSourceRegistry { public static synchronized void registerFactoryBean(String alias, Class clazz) { - cache.putIfAbsent(alias, clazz); cache.put(alias, clazz); } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/annotation/SentinelDataSource.java similarity index 91% rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java rename to spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/annotation/SentinelDataSource.java index 93ef1bdb9..b6b33226b 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/annotation/SentinelDataSource.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.alibaba.sentinel.annotation; +package org.springframework.cloud.alibaba.sentinel.datasource.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -31,7 +31,7 @@ import org.springframework.core.annotation.AliasFor; * into a Spring Bean. The Properties of DataSource bean get from config files with * specific prefix. * - * @author fangjian + * Jim * @see ReadableDataSource */ @Target({ElementType.FIELD}) diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java new file mode 100644 index 000000000..e0df905b1 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java @@ -0,0 +1,63 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link ApolloDataSource} instance. + * + * @author Jim + * @see ApolloDataSource + */ +public class ApolloDataSourceFactoryBean implements FactoryBean { + + private String namespaceName; + private String flowRulesKey; + private String defaultFlowRuleValue; + private Converter converter; + + @Override + public ApolloDataSource getObject() throws Exception { + return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue, + converter); + } + + @Override + public Class getObjectType() { + return ApolloDataSource.class; + } + + public String getNamespaceName() { + return namespaceName; + } + + public void setNamespaceName(String namespaceName) { + this.namespaceName = namespaceName; + } + + public String getFlowRulesKey() { + return flowRulesKey; + } + + public void setFlowRulesKey(String flowRulesKey) { + this.flowRulesKey = flowRulesKey; + } + + public String getDefaultFlowRuleValue() { + return defaultFlowRuleValue; + } + + public void setDefaultFlowRuleValue(String defaultFlowRuleValue) { + this.defaultFlowRuleValue = defaultFlowRuleValue; + } + + public Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java new file mode 100644 index 000000000..c7b4771f3 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java @@ -0,0 +1,76 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import java.io.File; +import java.nio.charset.Charset; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link FileRefreshableDataSource} instance. + * + * @author Jim + * @see FileRefreshableDataSource + */ +public class FileRefreshableDataSourceFactoryBean + implements FactoryBean { + + private String file; + private String charset; + private long recommendRefreshMs; + private int bufSize; + private Converter converter; + + @Override + public FileRefreshableDataSource getObject() throws Exception { + return new FileRefreshableDataSource(new File(file), converter, + recommendRefreshMs, bufSize, Charset.forName(charset)); + } + + @Override + public Class getObjectType() { + return FileRefreshableDataSource.class; + } + + public String getFile() { + return file; + } + + public void setFile(String file) { + this.file = file; + } + + public String getCharset() { + return charset; + } + + public void setCharset(String charset) { + this.charset = charset; + } + + public long getRecommendRefreshMs() { + return recommendRefreshMs; + } + + public void setRecommendRefreshMs(long recommendRefreshMs) { + this.recommendRefreshMs = recommendRefreshMs; + } + + public int getBufSize() { + return bufSize; + } + + public void setBufSize(int bufSize) { + this.bufSize = bufSize; + } + + public Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java new file mode 100644 index 000000000..12dbd138f --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -0,0 +1,62 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link NacosDataSource} instance. + * + * @author Jim + * @see NacosDataSource + */ +public class NacosDataSourceFactoryBean implements FactoryBean { + + private String serverAddr; + private String groupId; + private String dataId; + private Converter converter; + + @Override + public NacosDataSource getObject() throws Exception { + return new NacosDataSource(serverAddr, groupId, dataId, converter); + } + + @Override + public Class getObjectType() { + return NacosDataSource.class; + } + + public String getServerAddr() { + return serverAddr; + } + + public void setServerAddr(String serverAddr) { + this.serverAddr = serverAddr; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getDataId() { + return dataId; + } + + public void setDataId(String dataId) { + this.dataId = dataId; + } + + public Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java new file mode 100644 index 000000000..8b4ed177e --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java @@ -0,0 +1,81 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link ZookeeperDataSource} instance. + * + * @author Jim + * @see ZookeeperDataSource + */ +public class ZookeeperDataSourceFactoryBean implements FactoryBean { + + private String serverAddr; + + private String path; + + private String groupId; + private String dataId; + + private Converter converter; + + @Override + public ZookeeperDataSource getObject() throws Exception { + if (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) { + // the path will be /{groupId}/{dataId} + return new ZookeeperDataSource(serverAddr, groupId, dataId, converter); + } else { + // using path directly + return new ZookeeperDataSource(serverAddr, path, converter); + } + } + + @Override + public Class getObjectType() { + return ZookeeperDataSource.class; + } + + public String getServerAddr() { + return serverAddr; + } + + public void setServerAddr(String serverAddr) { + this.serverAddr = serverAddr; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getDataId() { + return dataId; + } + + public void setDataId(String dataId) { + this.dataId = dataId; + } + + public Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/util/PropertySourcesUtils.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/util/PropertySourcesUtils.java similarity index 96% rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/util/PropertySourcesUtils.java rename to spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/util/PropertySourcesUtils.java index 6eafbd63b..fde8fc44f 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/util/PropertySourcesUtils.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/util/PropertySourcesUtils.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package org.springframework.cloud.alibaba.sentinel.util; - -import org.springframework.core.env.EnumerablePropertySource; -import org.springframework.core.env.PropertySource; -import org.springframework.core.env.PropertySources; +package org.springframework.cloud.alibaba.sentinel.datasource.util; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.PropertySources; + /** * {@link PropertySources} Utilities * @@ -47,7 +47,7 @@ public abstract class PropertySourcesUtils { for (PropertySource source : propertySources) { if (source instanceof EnumerablePropertySource) { - for (String name : ((EnumerablePropertySource) source).getPropertyNames()) { + for (String name : ((EnumerablePropertySource)source).getPropertyNames()) { if (!subProperties.containsKey(name) && name.startsWith(normalizedPrefix)) { String subName = name.substring(normalizedPrefix.length()); if (!subProperties.containsKey(subName)) { // take first one diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/sentinel-datasource.properties b/spring-cloud-alibaba-sentinel-datasource/src/main/resources/META-INF/sentinel-datasource.properties similarity index 100% rename from spring-cloud-alibaba-sentinel/src/main/resources/META-INF/sentinel-datasource.properties rename to spring-cloud-alibaba-sentinel-datasource/src/main/resources/META-INF/sentinel-datasource.properties diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml index 74b58421b..3c3b41ead 100644 --- a/spring-cloud-alibaba-sentinel/pom.xml +++ b/spring-cloud-alibaba-sentinel/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 @@ -27,35 +27,17 @@ com.alibaba.csp - sentinel-datasource-extension - - - - com.alibaba.csp - sentinel-datasource-nacos - true - - - - com.alibaba.csp - sentinel-datasource-zookeeper - true - - - - com.alibaba.csp - sentinel-datasource-apollo - true + sentinel-annotation-aspectj com.alibaba.csp - sentinel-annotation-aspectj + sentinel-dubbo-adapter - com.alibaba.csp - sentinel-dubbo-adapter + org.springframework.cloud + spring-cloud-alibaba-sentinel-datasource diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java index 747044a50..620445a4a 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java @@ -23,11 +23,4 @@ public interface SentinelConstants { String PROPERTY_PREFIX = "spring.cloud.sentinel"; - String PROPERTY_ITEM_SEPARATOR = "."; - - String PROPERTY_DATASOURCE_NAME = "datasource"; - - String PROPERTY_DATASOURCE_PREFIX = PROPERTY_PREFIX + PROPERTY_ITEM_SEPARATOR - + PROPERTY_DATASOURCE_NAME; - } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java deleted file mode 100644 index 068717660..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java +++ /dev/null @@ -1,151 +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.sentinel.datasource; - -import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.PropertiesLoaderUtils; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -import com.alibaba.csp.sentinel.datasource.ReadableDataSource; - -/** - * {@link ReadableDataSource} Loader - * - * @author fangjian - */ -public class DataSourceLoader { - - private static final Logger logger = LoggerFactory.getLogger(DataSourceLoader.class); - - private final static String PROPERTIES_RESOURCE_LOCATION = "META-INF/sentinel-datasource.properties"; - - private final static String ALL_PROPERTIES_RESOURCES_LOCATION = CLASSPATH_ALL_URL_PREFIX - + PROPERTIES_RESOURCE_LOCATION; - - private final static ConcurrentMap> dataSourceClassesCache = new ConcurrentHashMap>( - 4); - - static void loadAllDataSourceClassesCache() { - Map> dataSourceClassesMap = loadAllDataSourceClassesCache( - ALL_PROPERTIES_RESOURCES_LOCATION); - - dataSourceClassesCache.putAll(dataSourceClassesMap); - } - - static Map> loadAllDataSourceClassesCache( - String resourcesLocation) { - - Map> dataSourcesMap = new HashMap>( - 4); - - ClassLoader classLoader = DataSourceLoader.class.getClassLoader(); - - ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - - try { - - Resource[] resources = resolver.getResources(resourcesLocation); - - for (Resource resource : resources) { - if (resource.exists()) { - Properties properties = PropertiesLoaderUtils - .loadProperties(resource); - for (Map.Entry entry : properties.entrySet()) { - - String type = (String) entry.getKey(); - String className = (String) entry.getValue(); - - if (!ClassUtils.isPresent(className, classLoader)) { - if (logger.isDebugEnabled()) { - logger.debug( - "Sentinel DataSource implementation [ type : " - + type + ": , class : " + className - + " , url : " + resource.getURL() - + "] was not present in current classpath , " - + "thus loading will be ignored , please add dependency if required !"); - } - continue; - } - - Assert.isTrue(!dataSourcesMap.containsKey(type), - "The duplicated type[" + type - + "] of SentinelDataSource were found in " - + "resource [" + resource.getURL() + "]"); - - Class dataSourceClass = ClassUtils.resolveClassName(className, - classLoader); - Assert.isAssignable(ReadableDataSource.class, dataSourceClass); - - dataSourcesMap.put(type, - (Class) dataSourceClass); - - if (logger.isDebugEnabled()) { - logger.debug("Sentinel DataSource implementation [ type : " - + type + ": , class : " + className - + "] was loaded."); - } - } - } - } - - } - catch (IOException e) { - if (logger.isErrorEnabled()) { - logger.error(e.getMessage(), e); - } - } - - return dataSourcesMap; - } - - public static Class loadClass(String type) - throws IllegalArgumentException { - - Class dataSourceClass = dataSourceClassesCache.get(type); - - if (dataSourceClass == null) { - if (dataSourceClassesCache.isEmpty()) { - loadAllDataSourceClassesCache(); - dataSourceClass = dataSourceClassesCache.get(type); - } - } - - if (dataSourceClass == null) { - throw new IllegalArgumentException( - "Sentinel DataSource implementation [ type : " + type - + " ] can't be found!"); - } - - return dataSourceClass; - - } - -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java deleted file mode 100644 index 627c5be03..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java +++ /dev/null @@ -1,264 +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.sentinel.datasource; - -import static org.springframework.core.annotation.AnnotationUtils.getAnnotation; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.PropertyValues; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.cloud.alibaba.sentinel.SentinelConstants; -import org.springframework.cloud.alibaba.sentinel.annotation.SentinelDataSource; -import org.springframework.cloud.alibaba.sentinel.util.PropertySourcesUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.event.EventListener; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.property.SentinelProperty; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; -import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; - -/** - * {@link SentinelDataSource @SentinelDataSource} Post Processor - * - * @author fangjian - * @see com.alibaba.csp.sentinel.datasource.ReadableDataSource - * @see SentinelDataSource - */ -public class SentinelDataSourcePostProcessor - extends InstantiationAwareBeanPostProcessorAdapter - implements MergedBeanDefinitionPostProcessor { - - private static final Logger logger = LoggerFactory - .getLogger(SentinelDataSourcePostProcessor.class); - - @Autowired - private ApplicationContext applicationContext; - - @Autowired - private ConfigurableEnvironment environment; - - private final Map> dataSourceFieldCache = new ConcurrentHashMap<>( - 64); - - @Override - public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, - Class beanType, String beanName) { - // find all fields using by @SentinelDataSource annotation - ReflectionUtils.doWithFields(beanType, new ReflectionUtils.FieldCallback() { - @Override - public void doWith(Field field) - throws IllegalArgumentException, IllegalAccessException { - SentinelDataSource annotation = getAnnotation(field, - SentinelDataSource.class); - if (annotation != null) { - if (Modifier.isStatic(field.getModifiers())) { - if (logger.isWarnEnabled()) { - logger.warn( - "@SentinelDataSource annotation is not supported on static fields: " - + field); - } - return; - } - if (dataSourceFieldCache.containsKey(beanName)) { - dataSourceFieldCache.get(beanName) - .add(new SentinelDataSourceField(annotation, field)); - } - else { - List list = new ArrayList<>(); - list.add(new SentinelDataSourceField(annotation, field)); - dataSourceFieldCache.put(beanName, list); - } - } - } - }); - } - - @Override - public PropertyValues postProcessPropertyValues(PropertyValues pvs, - PropertyDescriptor[] pds, Object bean, String beanName) - throws BeanCreationException { - if (dataSourceFieldCache.containsKey(beanName)) { - List sentinelDataSourceFields = dataSourceFieldCache - .get(beanName); - sentinelDataSourceFields.forEach(sentinelDataSourceField -> { - try { - // construct DataSource field annotated by @SentinelDataSource - Field field = sentinelDataSourceField.getField(); - ReflectionUtils.makeAccessible(field); - String dataSourceBeanName = constructDataSource( - sentinelDataSourceField.getSentinelDataSource()); - field.set(bean, applicationContext.getBean(dataSourceBeanName)); - } - catch (IllegalAccessException e) { - e.printStackTrace(); - } - catch (Exception e) { - e.printStackTrace(); - } - }); - } - return pvs; - } - - private String constructDataSource(SentinelDataSource annotation) { - String prefix = annotation.value(); - if (StringUtils.isEmpty(prefix)) { - prefix = SentinelConstants.PROPERTY_DATASOURCE_PREFIX; - } - Map propertyMap = PropertySourcesUtils - .getSubProperties(environment.getPropertySources(), prefix); - String alias = propertyMap.get("type").toString(); - Class dataSourceClass = DataSourceLoader.loadClass(alias); - - String beanName = StringUtils.isEmpty(annotation.name()) - ? StringUtils.uncapitalize(dataSourceClass.getSimpleName()) + "_" + prefix - : annotation.name(); - if (applicationContext.containsBean(beanName)) { - return beanName; - } - - Class targetClass = null; - // if alias exists in SentinelDataSourceRegistry, wired properties into - // FactoryBean - if (SentinelDataSourceRegistry.checkFactoryBean(alias)) { - targetClass = SentinelDataSourceRegistry.getFactoryBean(alias); - } - else { - // if alias not exists in SentinelDataSourceRegistry, wired properties into - // raw class - targetClass = dataSourceClass; - } - - registerDataSource(beanName, targetClass, propertyMap); - - return beanName; - } - - private void registerDataSource(String beanName, Class targetClass, - Map propertyMap) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(targetClass); - for (String propertyName : propertyMap.keySet()) { - Field field = ReflectionUtils.findField(targetClass, propertyName); - if (field != null) { - if (field.getType().isAssignableFrom(Converter.class)) { - // Converter get from ApplicationContext - builder.addPropertyReference(propertyName, - propertyMap.get(propertyName).toString()); - } - else { - // wired properties - builder.addPropertyValue(propertyName, propertyMap.get(propertyName)); - } - } - } - - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext - .getAutowireCapableBeanFactory(); - beanFactory.registerBeanDefinition(beanName, builder.getBeanDefinition()); - } - - - @EventListener(classes = ApplicationStartedEvent.class) - public void appStartedListener(ApplicationStartedEvent event) throws Exception { - Map dataSourceMap = event.getApplicationContext().getBeansOfType(ReadableDataSource.class); - if(dataSourceMap.size() == 1) { - ReadableDataSource dataSource = dataSourceMap.values().iterator().next(); - Object ruleConfig = dataSource.loadConfig(); - SentinelProperty sentinelProperty = dataSource.getProperty(); - if(checkRuleType(ruleConfig, FlowRule.class)) { - FlowRuleManager.register2Property(sentinelProperty); - } - if(checkRuleType(ruleConfig, DegradeRule.class)) { - DegradeRuleManager.register2Property(sentinelProperty); - } - if(checkRuleType(ruleConfig, SystemRule.class)) { - SystemRuleManager.register2Property(sentinelProperty); - } - if(checkRuleType(ruleConfig, AuthorityRule.class)) { - AuthorityRuleManager.register2Property(sentinelProperty); - } - } - } - - private boolean checkRuleType(Object ruleConfig, Class type) { - if(ruleConfig.getClass() == type) { - return true; - } else if(ruleConfig instanceof List) { - List ruleList = (List)ruleConfig; - if(ruleList.stream().filter(rule -> rule.getClass() == type).toArray().length == ruleList.size()) { - return true; - } - } - return false; - } - - class SentinelDataSourceField { - private SentinelDataSource sentinelDataSource; - private Field field; - - public SentinelDataSourceField(SentinelDataSource sentinelDataSource, - Field field) { - this.sentinelDataSource = sentinelDataSource; - this.field = field; - } - - public SentinelDataSource getSentinelDataSource() { - return sentinelDataSource; - } - - public void setSentinelDataSource(SentinelDataSource sentinelDataSource) { - this.sentinelDataSource = sentinelDataSource; - } - - public Field getField() { - return field; - } - - public void setField(Field field) { - this.field = field; - } - } - -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java deleted file mode 100644 index 09b39bb44..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import org.springframework.beans.factory.FactoryBean; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource; - -/** - * @author fangjian - * @see ApolloDataSource - */ -public class ApolloDataSourceFactoryBean implements FactoryBean { - - private String namespaceName; - private String flowRulesKey; - private String defaultFlowRuleValue; - private Converter converter; - - @Override - public ApolloDataSource getObject() throws Exception { - return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue, - converter); - } - - @Override - public Class getObjectType() { - return ApolloDataSource.class; - } - - public String getNamespaceName() { - return namespaceName; - } - - public void setNamespaceName(String namespaceName) { - this.namespaceName = namespaceName; - } - - public String getFlowRulesKey() { - return flowRulesKey; - } - - public void setFlowRulesKey(String flowRulesKey) { - this.flowRulesKey = flowRulesKey; - } - - public String getDefaultFlowRuleValue() { - return defaultFlowRuleValue; - } - - public void setDefaultFlowRuleValue(String defaultFlowRuleValue) { - this.defaultFlowRuleValue = defaultFlowRuleValue; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java deleted file mode 100644 index 759827647..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import java.io.File; -import java.nio.charset.Charset; - -import org.springframework.beans.factory.FactoryBean; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource; - -/** - * @author fangjian - * @see FileRefreshableDataSource - */ -public class FileRefreshableDataSourceFactoryBean - implements FactoryBean { - - private String file; - private String charset; - private long recommendRefreshMs; - private int bufSize; - private Converter converter; - - @Override - public FileRefreshableDataSource getObject() throws Exception { - return new FileRefreshableDataSource(new File(file), converter, - recommendRefreshMs, bufSize, Charset.forName(charset)); - } - - @Override - public Class getObjectType() { - return FileRefreshableDataSource.class; - } - - public String getFile() { - return file; - } - - public void setFile(String file) { - this.file = file; - } - - public String getCharset() { - return charset; - } - - public void setCharset(String charset) { - this.charset = charset; - } - - public long getRecommendRefreshMs() { - return recommendRefreshMs; - } - - public void setRecommendRefreshMs(long recommendRefreshMs) { - this.recommendRefreshMs = recommendRefreshMs; - } - - public int getBufSize() { - return bufSize; - } - - public void setBufSize(int bufSize) { - this.bufSize = bufSize; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java deleted file mode 100644 index 3de75fad4..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import org.springframework.beans.factory.FactoryBean; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; - -/** - * @author fangjian - * @see NacosDataSource - */ -public class NacosDataSourceFactoryBean implements FactoryBean { - - private String serverAddr; - private String groupId; - private String dataId; - private Converter converter; - - @Override - public NacosDataSource getObject() throws Exception { - return new NacosDataSource(serverAddr, groupId, dataId, converter); - } - - @Override - public Class getObjectType() { - return NacosDataSource.class; - } - - public String getServerAddr() { - return serverAddr; - } - - public void setServerAddr(String serverAddr) { - this.serverAddr = serverAddr; - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getDataId() { - return dataId; - } - - public void setDataId(String dataId) { - this.dataId = dataId; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java deleted file mode 100644 index aa10270a7..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.FactoryBean; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; - -/** - * @author fangjian - * @see ZookeeperDataSource - */ -public class ZookeeperDataSourceFactoryBean implements FactoryBean { - - private String serverAddr; - - private String path; - - private String groupId; - private String dataId; - - private Converter converter; - - @Override - public ZookeeperDataSource getObject() throws Exception { - if (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) { - // the path will be /{groupId}/{dataId} - return new ZookeeperDataSource(serverAddr, groupId, dataId, converter); - } - else { - // using path directly - return new ZookeeperDataSource(serverAddr, path, converter); - } - } - - @Override - public Class getObjectType() { - return ZookeeperDataSource.class; - } - - public String getServerAddr() { - return serverAddr; - } - - public void setServerAddr(String serverAddr) { - this.serverAddr = serverAddr; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getDataId() { - return dataId; - } - - public void setDataId(String dataId) { - this.dataId = dataId; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-test/core-support/pom.xml b/spring-cloud-alibaba-test/core-support/pom.xml index 72d30a988..93801772e 100644 --- a/spring-cloud-alibaba-test/core-support/pom.xml +++ b/spring-cloud-alibaba-test/core-support/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-test - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-test/pom.xml b/spring-cloud-alibaba-test/pom.xml index 1261226d7..6946dd9f1 100644 --- a/spring-cloud-alibaba-test/pom.xml +++ b/spring-cloud-alibaba-test/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alibaba-test/sentinel-test-support/pom.xml b/spring-cloud-alibaba-test/sentinel-test-support/pom.xml index 9197c5f82..2cff2a660 100644 --- a/spring-cloud-alibaba-test/sentinel-test-support/pom.xml +++ b/spring-cloud-alibaba-test/sentinel-test-support/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba-test - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-alicloud-acm/pom.xml b/spring-cloud-alicloud-acm/pom.xml new file mode 100644 index 000000000..e63810876 --- /dev/null +++ b/spring-cloud-alicloud-acm/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + + + org.springframework.cloud + spring-cloud-alibaba + 0.2.1.BUILD-SNAPSHOT + + + spring-cloud-alicloud-acm + Spring Cloud Alibaba Cloud ACM + + + + + org.springframework.cloud + spring-cloud-alicloud-context + + + + com.aliyun + aliyun-java-sdk-core + + + + com.aliyun + aliyun-java-sdk-edas + + + + com.alibaba.edas.acm + acm-sdk + + + + org.springframework.boot + spring-boot-autoconfigure + provided + true + + + org.springframework.boot + spring-boot-starter-actuator + true + + + + + org.springframework.cloud + spring-cloud-context + + + org.springframework.cloud + spring-cloud-commons + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/AcmAutoConfiguration.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/AcmAutoConfiguration.java new file mode 100644 index 000000000..36da2e858 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/AcmAutoConfiguration.java @@ -0,0 +1,75 @@ +/* + * 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.beans.BeansException; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +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.AcmIntegrationProperties; +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; + +import com.taobao.diamond.client.Diamond; + +/** + * Created on 01/10/2017. + * + * @author juven.xuxb + */ +@Configuration +@ConditionalOnClass({ Diamond.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( + AcmIntegrationProperties acmIntegrationProperties, + ContextRefresher contextRefresher, AcmRefreshHistory refreshHistory, + AcmPropertySourceRepository propertySourceRepository) { + return new AcmContextRefresher(contextRefresher, acmIntegrationProperties, + refreshHistory, propertySourceRepository); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/AcmPropertySourceRepository.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/AcmPropertySourceRepository.java new file mode 100644 index 000000000..42b84c89f --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/AcmPropertySourceRepository.java @@ -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 getAll() { + List 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 result) { + for (PropertySource p : composite.getPropertySources()) { + if (p instanceof AcmPropertySource) { + result.add((AcmPropertySource) p); + } + else if (p instanceof CompositePropertySource) { + collectAcmPropertySources((CompositePropertySource) p, result); + } + } + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java new file mode 100644 index 000000000..3ebae2773 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySource.java @@ -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 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; + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java new file mode 100644 index 000000000..2bf9cbba3 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceBuilder.java @@ -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 toMap(Properties properties) { + Map result = new HashMap<>(); + Enumeration keys = (Enumeration)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; + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceLocator.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceLocator.java new file mode 100644 index 000000000..a7c167619 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/bootstrap/AcmPropertySourceLocator.java @@ -0,0 +1,69 @@ +/* + * 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.beans.factory.annotation.Autowired; +import org.springframework.cloud.alicloud.context.acm.AcmIntegrationProperties; +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; + +/** + * @author juven.xuxb + * @author xiaolongzuo + */ +public class AcmPropertySourceLocator implements PropertySourceLocator { + + private static final String DIAMOND_PROPERTY_SOURCE_NAME = "diamond"; + + private static String defaultDiamondGroup = "DEFAULT_GROUP"; + + private AcmPropertySourceBuilder acmPropertySourceBuilder = new AcmPropertySourceBuilder(); + + @Autowired + private AcmIntegrationProperties acmIntegrationProperties; + + @Override + public PropertySource locate(Environment environment) { + + CompositePropertySource compositePropertySource = new CompositePropertySource( + DIAMOND_PROPERTY_SOURCE_NAME); + + for (String dataId : acmIntegrationProperties.getGroupConfigurationDataIds()) { + loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup, + true); + } + + for (String dataId : acmIntegrationProperties + .getApplicationConfigurationDataIds()) { + loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup, + false); + } + + return compositePropertySource; + } + + 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); + } + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/diagnostics/analyzer/DiamondConnectionFailureAnalyzer.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/diagnostics/analyzer/DiamondConnectionFailureAnalyzer.java new file mode 100644 index 000000000..64d56be39 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/diagnostics/analyzer/DiamondConnectionFailureAnalyzer.java @@ -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 { + + @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); + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/diagnostics/analyzer/DiamondConnectionFailureException.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/diagnostics/analyzer/DiamondConnectionFailureException.java new file mode 100644 index 000000000..a1b10abf6 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/diagnostics/analyzer/DiamondConnectionFailureException.java @@ -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; + } + +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java new file mode 100644 index 000000000..6c5518d76 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java @@ -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 invoke() { + Map result = new HashMap<>(); + result.put("config", properties); + + Map runtime = new HashMap<>(); + List all = propertySourceRepository.getAll(); + + List> sources = new ArrayList<>(); + for (AcmPropertySource ps : all) { + Map 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; + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpointAutoConfiguration.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpointAutoConfiguration.java new file mode 100644 index 000000000..2154c7701 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpointAutoConfiguration.java @@ -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); + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java new file mode 100644 index 000000000..27569ec1a --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmHealthIndicator.java @@ -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 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); + } +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java new file mode 100644 index 000000000..a6115912e --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmContextRefresher.java @@ -0,0 +1,120 @@ +/* + * 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.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.AcmIntegrationProperties; +import org.springframework.cloud.context.refresh.ContextRefresher; +import org.springframework.context.ApplicationListener; +import org.springframework.util.StringUtils; + +import com.alibaba.edas.acm.ConfigService; +import com.alibaba.edas.acm.listener.ConfigChangeListener; + +/** + * 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 { + + private Logger logger = LoggerFactory.getLogger(AcmContextRefresher.class); + + private final ContextRefresher contextRefresher; + + private final AcmIntegrationProperties acmIntegrationProperties; + + private final AcmRefreshHistory refreshHistory; + + private final AcmPropertySourceRepository acmPropertySourceRepository; + + private Map listenerMap = new ConcurrentHashMap<>(16); + + public AcmContextRefresher(ContextRefresher contextRefresher, + AcmIntegrationProperties acmIntegrationProperties, + AcmRefreshHistory refreshHistory, + AcmPropertySourceRepository acmPropertySourceRepository) { + this.contextRefresher = contextRefresher; + this.acmIntegrationProperties = acmIntegrationProperties; + this.refreshHistory = refreshHistory; + this.acmPropertySourceRepository = acmPropertySourceRepository; + } + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + this.registerDiamondListenersForApplications(); + } + + private void registerDiamondListenersForApplications() { + if (acmIntegrationProperties.getAcmProperties().isRefreshEnabled()) { + for (AcmPropertySource acmPropertySource : acmPropertySourceRepository + .getAll()) { + if (acmPropertySource.isGroupLevel()) { + continue; + } + String dataId = acmPropertySource.getDataId(); + registerDiamondListener(dataId); + } + if (acmPropertySourceRepository.getAll().isEmpty()) { + + registerDiamondListener(acmIntegrationProperties + .getApplicationConfigurationDataIdWithoutGroup()); + } + } + } + + 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, + acmIntegrationProperties.getAcmProperties().getGroup(), listener); + } + +} diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java new file mode 100644 index 000000000..439e63604 --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java @@ -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 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 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; + } +} diff --git a/spring-cloud-alicloud-acm/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alicloud-acm/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 000000000..29f53c76e --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,9 @@ +{ + "properties": [ + { + "name": "spring.application.group", + "type": "java.lang.String", + "description": "spring application group." + } + ] +} \ No newline at end of file diff --git a/spring-cloud-alicloud-acm/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-acm/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..4f39095fe --- /dev/null +++ b/spring-cloud-alicloud-acm/src/main/resources/META-INF/spring.factories @@ -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 \ No newline at end of file diff --git a/spring-cloud-alicloud-ans/pom.xml b/spring-cloud-alicloud-ans/pom.xml new file mode 100644 index 000000000..56fba7fbf --- /dev/null +++ b/spring-cloud-alicloud-ans/pom.xml @@ -0,0 +1,98 @@ + + + + spring-cloud-alibaba + org.springframework.cloud + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + + org.springframework.cloud + spring-cloud-alicloud-ans + Spring Cloud Alibaba Cloud ANS + + + + + com.alibaba.ans + ans-sdk + + + + com.aliyun + aliyun-java-sdk-core + + + + com.aliyun + aliyun-java-sdk-edas + + + + org.springframework.cloud + spring-cloud-alicloud-context + + + + org.springframework + spring-context + + + org.springframework.cloud + spring-cloud-commons + + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + org.springframework.boot + spring-boot-actuator + true + + + org.springframework.boot + spring-boot-actuator-autoconfigure + provided + true + + + org.springframework.boot + spring-boot-configuration-processor + provided + true + + + org.springframework.boot + spring-boot-autoconfigure + provided + true + + + org.springframework.boot + spring-boot-starter-web + test + + + org.springframework.boot + spring-boot-starter-actuator + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.cloud + spring-cloud-test-support + test + + + + + \ No newline at end of file diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java new file mode 100644 index 000000000..a14c6e12a --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java @@ -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); + } +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java new file mode 100644 index 000000000..c95757b22 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClient.java @@ -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 getInstances(String serviceId) { + try { + List 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 metadata = new HashMap(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 hostToServiceInstanceList(List hosts, + String serviceId) { + List result = new ArrayList(hosts.size()); + for (Host host : hosts) { + result.add(hostToServiceInstance(host, serviceId)); + } + return result; + } + + @Override + public List getServices() { + + Set doms = NamingService.getDomsSubscribed(); + List result = new LinkedList<>(); + for (String service : doms) { + result.add(service); + } + return result; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java new file mode 100644 index 000000000..7d2869763 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsDiscoveryClientAutoConfiguration.java @@ -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(); + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsServiceInstance.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsServiceInstance.java new file mode 100644 index 000000000..52f7858c0 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/AnsServiceInstance.java @@ -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 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 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 metadata) { + this.metadata = metadata; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ConditionalOnAnsEnabled.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ConditionalOnAnsEnabled.java new file mode 100644 index 000000000..dc12044e6 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ConditionalOnAnsEnabled.java @@ -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 { +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java new file mode 100644 index 000000000..a8bc64c7c --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpoint.java @@ -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 invoke() { + Map ansEndpoint = new HashMap<>(); + LOGGER.info("ANS endpoint invoke, ansProperties is {}", ansProperties); + ansEndpoint.put("ansProperties", ansProperties); + + Map subscribes = new HashMap<>(); + Set subscribeServices = NamingService.getDomsSubscribed(); + for (String service : subscribeServices) { + try { + List 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; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpointAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpointAutoConfiguration.java new file mode 100644 index 000000000..65f5803c7 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/endpoint/AnsEndpointAutoConfiguration.java @@ -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); + } +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java new file mode 100644 index 000000000..0774f1856 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsAutoServiceRegistration.java @@ -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 { + private static final Logger LOGGER = LoggerFactory + .getLogger(AnsAutoServiceRegistration.class); + + @Autowired + private AnsRegistration registration; + + public AnsAutoServiceRegistration(ServiceRegistry 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; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java new file mode 100644 index 000000000..1fcb292f3 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsRegistration.java @@ -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 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 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 + '}'; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java new file mode 100644 index 000000000..ebe65ee39 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/registry/AnsServiceRegistry.java @@ -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 { + + 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 tags = new ArrayList<>(); + for (Map.Entry 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 getStatus(AnsRegistration registration) { + return null; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java new file mode 100644 index 000000000..7734e0371 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsRibbonClientConfiguration.java @@ -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; + } + +} \ No newline at end of file diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java new file mode 100644 index 000000000..8438a7f35 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServer.java @@ -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 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 getMetadata() { + return metadata; + } + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java new file mode 100644 index 000000000..f34f19ffd --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/AnsServerList.java @@ -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 { + + private String dom; + + public AnsServerList(String dom) { + this.dom = dom; + } + + @Override + public List getInitialListOfServers() { + try { + List hosts = NamingService.getHosts(getDom()); + return hostsToServerList(hosts); + } + catch (Exception e) { + throw new IllegalStateException("Can not get ans hosts, dom=" + getDom(), e); + } + } + + @Override + public List getUpdatedListOfServers() { + return getInitialListOfServers(); + } + + private AnsServer hostToServer(Host host) { + AnsServer server = new AnsServer(host, getDom()); + return server; + } + + private List hostsToServerList(List hosts) { + List result = new ArrayList(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(); + } +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/ConditionalOnRibbonAns.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/ConditionalOnRibbonAns.java new file mode 100644 index 000000000..078e6fdd1 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/ConditionalOnRibbonAns.java @@ -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 { + +} diff --git a/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java new file mode 100644 index 000000000..4333cb534 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/java/org/springframework/cloud/alicloud/ans/ribbon/RibbonAnsAutoConfiguration.java @@ -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 { +} diff --git a/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..63d6cd5c8 --- /dev/null +++ b/spring-cloud-alicloud-ans/src/main/resources/META-INF/spring.factories @@ -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 diff --git a/spring-cloud-alicloud-ans/src/test/java/org/springframework/cloud/alibaba/ans/ribbon/AnsServiceListTests.java b/spring-cloud-alicloud-ans/src/test/java/org/springframework/cloud/alibaba/ans/ribbon/AnsServiceListTests.java new file mode 100644 index 000000000..5cb38532a --- /dev/null +++ b/spring-cloud-alicloud-ans/src/test/java/org/springframework/cloud/alibaba/ans/ribbon/AnsServiceListTests.java @@ -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 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 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; + } + +} diff --git a/spring-cloud-alicloud-context/pom.xml b/spring-cloud-alicloud-context/pom.xml new file mode 100644 index 000000000..5b3a0f1a1 --- /dev/null +++ b/spring-cloud-alicloud-context/pom.xml @@ -0,0 +1,106 @@ + + + + + org.springframework.cloud + spring-cloud-alibaba + 0.2.1.BUILD-SNAPSHOT + + 4.0.0 + + org.springframework.cloud + spring-cloud-alicloud-context + Spring Cloud AliCloud Context + + + + + com.aliyun + aliyun-java-sdk-edas + provided + + + com.aliyun + aliyun-java-sdk-core + + + + + + com.alibaba.cloud + alicloud-context + + + + com.aliyun + aliyun-java-sdk-core + provided + + + + com.alibaba.ans + ans-sdk + provided + + + + com.aliyun.oss + aliyun-sdk-oss + provided + + + + com.alibaba.edas.acm + acm-sdk + provided + + + + org.springframework.cloud + spring-cloud-commons + + + + org.springframework.boot + spring-boot-starter-logging + provided + true + + + + org.springframework.boot + spring-boot + provided + true + + + + org.springframework.boot + spring-boot-autoconfigure + provided + true + + + + org.springframework.boot + spring-boot-configuration-processor + provided + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-web + test + + + + + diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/AliCloudContextAutoConfiguration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/AliCloudContextAutoConfiguration.java new file mode 100644 index 000000000..f0f2f5722 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/AliCloudContextAutoConfiguration.java @@ -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 { + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/AliCloudProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/AliCloudProperties.java new file mode 100644 index 000000000..095173292 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/AliCloudProperties.java @@ -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; + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmContextBootstrapConfiguration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmContextBootstrapConfiguration.java new file mode 100644 index 000000000..13f038aa9 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmContextBootstrapConfiguration.java @@ -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.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.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +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; + + @Autowired + private Environment environment; + + @PostConstruct + public void initAcmProperties() { + AliCloudAcmInitializer.initialize(aliCloudProperties, edasProperties, + acmProperties); + } + + @Bean + public AcmIntegrationProperties acmIntegrationProperties() { + AcmIntegrationProperties acmIntegrationProperties = new AcmIntegrationProperties(); + String applicationName = environment.getProperty("spring.application.name"); + String applicationGroup = environment.getProperty("spring.application.group"); + Assert.isTrue(!StringUtils.isEmpty(applicationName), + "'spring.application.name' must be configured in bootstrap.properties or bootstrap.yml/yaml..."); + acmIntegrationProperties.setApplicationName(applicationName); + acmIntegrationProperties.setApplicationGroup(applicationGroup); + acmIntegrationProperties.setActiveProfiles(environment.getActiveProfiles()); + acmIntegrationProperties.setAcmProperties(acmProperties); + return acmIntegrationProperties; + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmIntegrationProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmIntegrationProperties.java new file mode 100644 index 000000000..8491ef129 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmIntegrationProperties.java @@ -0,0 +1,98 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; + +import org.springframework.util.StringUtils; + +/** + * @author xiaolongzuo + */ +public class AcmIntegrationProperties { + + private String applicationName; + + private String applicationGroup; + + private String[] activeProfiles = new String[0]; + + private AcmProperties acmProperties; + + public String getApplicationConfigurationDataIdWithoutGroup() { + return applicationName + "." + acmProperties.getFileExtension(); + } + + public List getGroupConfigurationDataIds() { + List groupConfigurationDataIds = new ArrayList<>(); + if (StringUtils.isEmpty(applicationGroup)) { + return groupConfigurationDataIds; + } + String[] parts = applicationGroup.split("\\."); + for (int i = 1; i < parts.length; i++) { + StringBuilder subGroup = new StringBuilder(parts[0]); + for (int j = 1; j <= i; j++) { + subGroup.append(".").append(parts[j]); + } + groupConfigurationDataIds + .add(subGroup + ":application." + acmProperties.getFileExtension()); + } + return groupConfigurationDataIds; + } + + public List getApplicationConfigurationDataIds() { + List applicationConfigurationDataIds = new ArrayList<>(); + if (!StringUtils.isEmpty(applicationGroup)) { + applicationConfigurationDataIds.add(applicationGroup + ":" + applicationName + + "." + acmProperties.getFileExtension()); + for (String profile : activeProfiles) { + applicationConfigurationDataIds + .add(applicationGroup + ":" + applicationName + "-" + profile + + "." + acmProperties.getFileExtension()); + } + + } + applicationConfigurationDataIds + .add(applicationName + "." + acmProperties.getFileExtension()); + for (String profile : activeProfiles) { + applicationConfigurationDataIds.add(applicationName + "-" + profile + "." + + acmProperties.getFileExtension()); + } + return applicationConfigurationDataIds; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public void setApplicationGroup(String applicationGroup) { + this.applicationGroup = applicationGroup; + } + + public void setActiveProfiles(String[] activeProfiles) { + this.activeProfiles = activeProfiles; + } + + public void setAcmProperties(AcmProperties acmProperties) { + this.acmProperties = acmProperties; + } + + public AcmProperties getAcmProperties() { + return acmProperties; + } +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmProperties.java new file mode 100644 index 000000000..2a1993e90 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/acm/AcmProperties.java @@ -0,0 +1,156 @@ +/* + * 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.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 { + + private AliCloudServerMode serverMode = AliCloudServerMode.LOCAL; + + 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 endpoint 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; + } +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsContextApplicationListener.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsContextApplicationListener.java new file mode 100644 index 000000000..6d9e9ca20 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsContextApplicationListener.java @@ -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 { + + @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); + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsContextAutoConfiguration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsContextAutoConfiguration.java new file mode 100644 index 000000000..fc58b69e9 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsContextAutoConfiguration.java @@ -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); + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsProperties.java new file mode 100644 index 000000000..2852ff573 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/ans/AnsProperties.java @@ -0,0 +1,334 @@ +/* + * 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 + */ + private AliCloudServerMode serverMode = AliCloudServerMode.LOCAL; + + /** + * 服务端列表 + */ + private String serverList = "127.0.0.1"; + + /** + * 服务端列表 + */ + private String serverPort = "8080"; + + /** + * 注册的服务名,默认从 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 clientWeights = new HashMap(); + + /** + * 注册服务的 token ,从 spring.cloud.alicloud.ans.token 中获取 + */ + private String clientToken; + + /** + * 当存在多个doms,需要对应不同的token时,通过 spring.cloud.alicloud.ans.tokens.dom1=token1 的方式配置 + */ + private Map clientTokens = new HashMap(); + + /** + * 配置注册到哪个集群,从 spring.cloud.alicloud.ans.cluster 中获取,默认为 DEFAULT + */ + private String clientCluster = "DEFAULT"; + + /** + * metadata 实现 serviceInstance 接口所需的字段,但 ans 目前尚不支持此字段,配置了也没用 + */ + private Map 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 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 = 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 getTags() { + return tags; + } + + public void setTags(Map 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 getClientWeights() { + return clientWeights; + } + + public void setClientWeights(Map clientWeights) { + this.clientWeights = clientWeights; + } + + @Override + public String getClientToken() { + return clientToken; + } + + public void setClientToken(String clientToken) { + this.clientToken = clientToken; + } + + @Override + public Map getClientTokens() { + return clientTokens; + } + + public void setClientTokens(Map clientTokens) { + this.clientTokens = clientTokens; + } + + @Override + public String getClientCluster() { + return clientCluster; + } + + public void setClientCluster(String clientCluster) { + this.clientCluster = clientCluster; + } + + @Override + public Map getClientMetadata() { + return clientMetadata; + } + + public void setClientMetadata(Map 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 + '}'; + } +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/edas/EdasContextAutoConfiguration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/edas/EdasContextAutoConfiguration.java new file mode 100644 index 000000000..12945c231 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/edas/EdasContextAutoConfiguration.java @@ -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()); + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/edas/EdasProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/edas/EdasProperties.java new file mode 100644 index 000000000..43c9a7cb9 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/edas/EdasProperties.java @@ -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; + } +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/listener/AbstractOnceApplicationListener.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/listener/AbstractOnceApplicationListener.java new file mode 100644 index 000000000..d8b822a9b --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/listener/AbstractOnceApplicationListener.java @@ -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 + implements ApplicationListener { + + private static final String BOOTSTRAP_CONFIG_NAME_VALUE = "bootstrap"; + + private static final String BOOTSTRAP_CONFIG_NAME_KEY = "spring.config.name"; + + private static ConcurrentHashMap, 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; + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/oss/OssContextAutoConfiguration.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/oss/OssContextAutoConfiguration.java new file mode 100644 index 000000000..e1993a376 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/oss/OssContextAutoConfiguration.java @@ -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 Jim + * @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."); + } + } + +} diff --git a/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/oss/OssProperties.java b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/oss/OssProperties.java new file mode 100644 index 000000000..59f64cc3c --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/java/org/springframework/cloud/alicloud/context/oss/OssProperties.java @@ -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 Jim + * @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; + } + + } + +} diff --git a/spring-cloud-alicloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alicloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 000000000..2b81aad2a --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,16 @@ +{ + "properties": [ + { + "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.env", + "type": "java.lang.String", + "defaultValue": "DEFAULT", + "description": "The env for ans, default value is DEFAULT." + } + ] +} \ No newline at end of file diff --git a/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..e10dcb959 --- /dev/null +++ b/spring-cloud-alicloud-context/src/main/resources/META-INF/spring.factories @@ -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 \ No newline at end of file diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/acm/AcmAutoConfiguration.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/acm/AcmAutoConfiguration.java new file mode 100644 index 000000000..1ecff17f8 --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/acm/AcmAutoConfiguration.java @@ -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 { +} diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java new file mode 100644 index 000000000..1f15f8827 --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/ans/AnsAutoConfiguration.java @@ -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 { +} diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/AliCloudPropertiesTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/AliCloudPropertiesTests.java new file mode 100644 index 000000000..1094b928f --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/AliCloudPropertiesTests.java @@ -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.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 aliCloudProperties = context + .getBean(AliCloudProperties.class); + assertThat(aliCloudProperties.getAccessKey()).isNull(); + assertThat(aliCloudProperties.getSecretKey()).isNull(); + }); + } + + @Test + public void testConfigurationValuesAreCorrectlyLoaded() { + this.contextRunner.withPropertyValues("spring.cloud.alicloud.access-key=123", + "spring.cloud.alicloud.secret-key=123456").run(context -> { + AliCloudProperties aliCloudProperties = context + .getBean(AliCloudProperties.class); + assertThat(aliCloudProperties.getAccessKey()).isEqualTo("123"); + assertThat(aliCloudProperties.getSecretKey()).isEqualTo("123456"); + }); + } + +} diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/AliCloudSpringApplicationTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/AliCloudSpringApplicationTests.java new file mode 100644 index 000000000..636adf64e --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/AliCloudSpringApplicationTests.java @@ -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.AliCloudDisabledApp.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 AliCloudDisabledApp { + + } + +} diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/acm/AcmPropertiesTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/acm/AcmPropertiesTests.java new file mode 100644 index 000000000..d129d64e9 --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/acm/AcmPropertiesTests.java @@ -0,0 +1,127 @@ +/* + * 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 AcmPropertiesTests { + + private ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration( + AutoConfigurations.of(AcmContextBootstrapConfiguration.class, + EdasContextAutoConfiguration.class, + AliCloudContextAutoConfiguration.class)); + + @Test + public void testConfigurationValueDefaultsAreAsExpected() { + this.contextRunner.withPropertyValues("spring.application.name=myapp") + .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.application.name=myapp", + "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 acmProperties = context.getBean(AcmProperties.class); + assertThat(acmProperties.getServerMode()) + .isEqualTo(AliCloudServerMode.EDAS); + assertThat(acmProperties.getServerList()).isEqualTo("10.10.10.10"); + assertThat(acmProperties.getServerPort()).isEqualTo("11111"); + assertThat(acmProperties.getEndpoint()).isEqualTo("testDomain"); + assertThat(acmProperties.getGroup()).isEqualTo("testGroup"); + assertThat(acmProperties.getFileExtension()).isEqualTo("yaml"); + assertThat(acmProperties.getNamespace()).isEqualTo("testNamespace"); + }); + } + + @Test + public void testAcmIntegrationConfigurationValuesAreCorrectlyLoaded() { + this.contextRunner.withPropertyValues("spring.application.name=myapp", + "spring.application.group=com.alicloud.test", + "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 -> { + AcmIntegrationProperties acmIntegrationProperties = context + .getBean(AcmIntegrationProperties.class); + assertThat(acmIntegrationProperties.getGroupConfigurationDataIds() + .size()).isEqualTo(2); + assertThat(acmIntegrationProperties + .getApplicationConfigurationDataIds().size()).isEqualTo(2); + }); + } + + @Test + public void testAcmIntegrationConfigurationValuesAreCorrectlyLoaded2() { + this.contextRunner.withPropertyValues("spring.application.name=myapp", + "spring.application.group=com.alicloud.test", + "spring.profiles.active=profile1,profile2", + "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 -> { + AcmIntegrationProperties acmIntegrationProperties = context + .getBean(AcmIntegrationProperties.class); + assertThat(acmIntegrationProperties.getGroupConfigurationDataIds() + .size()).isEqualTo(2); + assertThat(acmIntegrationProperties + .getApplicationConfigurationDataIds().size()).isEqualTo(6); + }); + } + +} diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/ans/AnsPropertiesTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/ans/AnsPropertiesTests.java new file mode 100644 index 000000000..a81f0ab5b --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/ans/AnsPropertiesTests.java @@ -0,0 +1,102 @@ +/* + * 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 ansProperties = context.getBean(AnsProperties.class); + assertThat(ansProperties.getServerMode()).isEqualTo(AliCloudServerMode.LOCAL); + assertThat(ansProperties.getServerList()).isEqualTo("127.0.0.1"); + assertThat(ansProperties.getServerPort()).isEqualTo("8080"); + assertThat(ansProperties.getClientDomains()).isEqualTo(""); + assertThat(ansProperties.getClientWeight()).isEqualTo(1.0F); + assertThat(ansProperties.getClientWeights().size()).isEqualTo(0); + assertThat(ansProperties.getClientTokens().size()).isEqualTo(0); + assertThat(ansProperties.getClientMetadata().size()).isEqualTo(0); + assertThat(ansProperties.getClientToken()).isNull(); + assertThat(ansProperties.getClientCluster()).isEqualTo("DEFAULT"); + assertThat(ansProperties.isRegisterEnabled()).isTrue(); + assertThat(ansProperties.getClientInterfaceName()).isNull(); + assertThat(ansProperties.getClientPort()).isEqualTo(-1); + assertThat(ansProperties.getEnv()).isEqualTo("DEFAULT"); + assertThat(ansProperties.isSecure()).isFalse(); + assertThat(ansProperties.getTags().size()).isEqualTo(1); + assertThat(ansProperties.getTags().keySet().iterator().next()) + .isEqualTo("ANS_SERVICE_TYPE"); + assertThat(ansProperties.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 ansProperties = context.getBean(AnsProperties.class); + assertThat(ansProperties.getServerMode()) + .isEqualTo(AliCloudServerMode.EDAS); + assertThat(ansProperties.getServerList()).isEqualTo("10.10.10.10"); + assertThat(ansProperties.getServerPort()).isEqualTo("11111"); + assertThat(ansProperties.getClientDomains()).isEqualTo("testDomain"); + assertThat(ansProperties.getClientWeight()).isEqualTo(0.9F); + assertThat(ansProperties.getClientWeights().size()).isEqualTo(1); + assertThat(ansProperties.getClientTokens().size()).isEqualTo(0); + assertThat(ansProperties.getClientMetadata().size()).isEqualTo(0); + assertThat(ansProperties.getClientToken()).isNull(); + assertThat(ansProperties.getClientCluster()).isEqualTo("DEFAULT"); + assertThat(ansProperties.isRegisterEnabled()).isTrue(); + assertThat(ansProperties.getClientInterfaceName()).isNull(); + assertThat(ansProperties.getClientPort()).isEqualTo(-1); + assertThat(ansProperties.getEnv()).isEqualTo("DEFAULT"); + assertThat(ansProperties.isSecure()).isFalse(); + assertThat(ansProperties.getTags().size()).isEqualTo(1); + assertThat(ansProperties.getTags().keySet().iterator().next()) + .isEqualTo("ANS_SERVICE_TYPE"); + assertThat(ansProperties.getTags().get("ANS_SERVICE_TYPE")) + .isEqualTo("SPRING_CLOUD"); + }); + } + +} diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/edas/EdasPropertiesTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/edas/EdasPropertiesTests.java new file mode 100644 index 000000000..ed59a46c2 --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/edas/EdasPropertiesTests.java @@ -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 edasProperties = context.getBean(EdasProperties.class); + assertThat(edasProperties.getNamespace()).isNull(); + assertThat(edasProperties.isApplicationNameValid()).isFalse(); + }); + } + + @Test + public void testConfigurationValuesAreCorrectlyLoaded1() { + this.contextRunner + .withPropertyValues("spring.cloud.alicloud.edas.namespace=testns", + "spring.application.name=myapps") + .run(context -> { + EdasProperties edasProperties = context.getBean(EdasProperties.class); + assertThat(edasProperties.getNamespace()).isEqualTo("testns"); + assertThat(edasProperties.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 edasProperties = context.getBean(EdasProperties.class); + assertThat(edasProperties.getNamespace()).isEqualTo("testns"); + assertThat(edasProperties.getApplicationName()).isEqualTo("myapps"); + }); + } + +} diff --git a/spring-cloud-alicloud-oss/src/test/java/org/springframework/cloud/alibaba/oss/test/OSSAutoConfigurationTests.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/oss/OssAutoConfigurationTests.java similarity index 66% rename from spring-cloud-alicloud-oss/src/test/java/org/springframework/cloud/alibaba/oss/test/OSSAutoConfigurationTests.java rename to spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/oss/OssAutoConfigurationTests.java index 96a145535..042ec0873 100644 --- a/spring-cloud-alicloud-oss/src/test/java/org/springframework/cloud/alibaba/oss/test/OSSAutoConfigurationTests.java +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/context/oss/OssAutoConfigurationTests.java @@ -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 Jim */ -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"); }); } diff --git a/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/oss/OssAutoConfiguration.java b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/oss/OssAutoConfiguration.java new file mode 100644 index 000000000..2f6961c6d --- /dev/null +++ b/spring-cloud-alicloud-context/src/test/java/org/springframework/cloud/alicloud/oss/OssAutoConfiguration.java @@ -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 { +} diff --git a/spring-cloud-alicloud-oss/pom.xml b/spring-cloud-alicloud-oss/pom.xml index 09e114540..6b67c470d 100644 --- a/spring-cloud-alicloud-oss/pom.xml +++ b/spring-cloud-alicloud-oss/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT 4.0.0 @@ -15,10 +15,14 @@ + + org.springframework.cloud + spring-cloud-alicloud-context + + com.aliyun.oss aliyun-sdk-oss - true diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSProperties.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSProperties.java deleted file mode 100644 index 323c1754a..000000000 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSProperties.java +++ /dev/null @@ -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 Jim - */ -@ConfigurationProperties(prefix = OSSConstants.PREFIX) -public class OSSProperties { - - private static final Logger logger = LoggerFactory.getLogger(OSSProperties.class); - - public static final Map 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)); - } -} diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/endpoint/OSSEndpoint.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/endpoint/OSSEndpoint.java deleted file mode 100644 index d417a858a..000000000 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/endpoint/OSSEndpoint.java +++ /dev/null @@ -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 Jim - */ -@Endpoint(id = "oss") -public class OSSEndpoint { - - @Autowired - private ApplicationContext applicationContext; - - @ReadOperation - public Map invoke() { - Map result = new HashMap<>(); - - Map ossClientMap = applicationContext - .getBeansOfType(OSSClient.class); - - int size = ossClientMap.size(); - - List ossClientList = new ArrayList<>(); - - ossClientMap.keySet().forEach(beanName -> { - Map 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; - } - -} diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSApplicationListener.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssApplicationListener.java similarity index 90% rename from spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSApplicationListener.java rename to spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssApplicationListener.java index d29039b04..23120e388 100644 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSApplicationListener.java +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssApplicationListener.java @@ -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 Jim */ -public class OSSApplicationListener implements ApplicationListener { +public class OssApplicationListener implements ApplicationListener { private static final Logger logger = LoggerFactory - .getLogger(OSSApplicationListener.class); + .getLogger(OssApplicationListener.class); @Override public void onApplicationEvent(ContextClosedEvent event) { diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSAutoConfiguration.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssAutoConfiguration.java similarity index 52% rename from spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSAutoConfiguration.java rename to spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssAutoConfiguration.java index 194933c35..5d7b57317 100644 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSAutoConfiguration.java +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssAutoConfiguration.java @@ -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(); + } } diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSConstants.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssConstants.java similarity index 90% rename from spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSConstants.java rename to spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssConstants.java index 4f0587923..e764ebacc 100644 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/OSSConstants.java +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/OssConstants.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package org.springframework.cloud.alibaba.oss; +package org.springframework.cloud.alicloud.oss; /** * OSS constants * * @author Jim */ -public interface OSSConstants { +public interface OssConstants { String PREFIX = "spring.cloud.alibaba.oss"; String ENABLED = PREFIX + ".enabled"; diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/endpoint/OssEndpoint.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/endpoint/OssEndpoint.java new file mode 100644 index 000000000..a09e53fde --- /dev/null +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/endpoint/OssEndpoint.java @@ -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 Jim + */ +@Endpoint(id = "oss") +public class OssEndpoint { + + @Autowired + private ApplicationContext applicationContext; + + @ReadOperation + public Map invoke() { + Map result = new HashMap<>(); + + Map ossClientMap = applicationContext + .getBeansOfType(OSSClient.class); + + int size = ossClientMap.size(); + + List ossClientList = new ArrayList<>(); + + ossClientMap.keySet().forEach(beanName -> { + Map 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; + } + +} diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/endpoint/OSSEndpointAutoConfiguration.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/endpoint/OssEndpointAutoConfiguration.java similarity index 88% rename from spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/endpoint/OSSEndpointAutoConfiguration.java rename to spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/endpoint/OssEndpointAutoConfiguration.java index c056d5864..0378dd4f7 100644 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/endpoint/OSSEndpointAutoConfiguration.java +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/endpoint/OssEndpointAutoConfiguration.java @@ -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 Jim */ @ConditionalOnClass(Endpoint.class) -public class OSSEndpointAutoConfiguration { +public class OssEndpointAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint - public OSSEndpoint sentinelEndPoint() { - return new OSSEndpoint(); + public OssEndpoint sentinelEndPoint() { + return new OssEndpoint(); } } diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/resource/OSSStorageProtocolResolver.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/resource/OssStorageProtocolResolver.java similarity index 92% rename from spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/resource/OSSStorageProtocolResolver.java rename to spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/resource/OssStorageProtocolResolver.java index 159f2c49e..681f3e882 100644 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/resource/OSSStorageProtocolResolver.java +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/resource/OssStorageProtocolResolver.java @@ -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 Jim */ -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 diff --git a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/resource/OSSStorageResource.java b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/resource/OssStorageResource.java similarity index 93% rename from spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/resource/OSSStorageResource.java rename to spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/resource/OssStorageResource.java index 08ef10aa8..82f38fe50 100644 --- a/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alibaba/oss/resource/OSSStorageResource.java +++ b/spring-cloud-alicloud-oss/src/main/java/org/springframework/cloud/alicloud/oss/resource/OssStorageResource.java @@ -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()); } diff --git a/spring-cloud-alicloud-oss/src/main/resources/META-INF/spring.factories b/spring-cloud-alicloud-oss/src/main/resources/META-INF/spring.factories index 4f71c2da2..598bc2166 100644 --- a/spring-cloud-alicloud-oss/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alicloud-oss/src/main/resources/META-INF/spring.factories @@ -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 \ No newline at end of file +org.springframework.cloud.alicloud.oss.OssApplicationListener \ No newline at end of file diff --git a/spring-cloud-alicloud-oss/src/test/java/org/springframework/cloud/alibaba/oss/test/OSSMultiClientAutoConfigurationTests.java b/spring-cloud-alicloud-oss/src/test/java/org/springframework/cloud/alibaba/oss/test/OSSMultiClientAutoConfigurationTests.java deleted file mode 100644 index 1af1f2853..000000000 --- a/spring-cloud-alicloud-oss/src/test/java/org/springframework/cloud/alibaba/oss/test/OSSMultiClientAutoConfigurationTests.java +++ /dev/null @@ -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 Jim - */ -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()); - } - - } - -} diff --git a/spring-cloud-starter-alibaba/pom.xml b/spring-cloud-starter-alibaba/pom.xml index 303e785f7..5223b1d61 100644 --- a/spring-cloud-starter-alibaba/pom.xml +++ b/spring-cloud-starter-alibaba/pom.xml @@ -4,7 +4,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT spring-cloud-starter-alibaba pom diff --git a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-config/pom.xml b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-config/pom.xml index 60c0e4891..6962945c2 100644 --- a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-config/pom.xml +++ b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-config/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-starter-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT spring-cloud-starter-alibaba-nacos-config Spring Cloud Starter Alibaba Nacos Config diff --git a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-discovery/pom.xml b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-discovery/pom.xml index 08bcf547d..50a538535 100644 --- a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-discovery/pom.xml +++ b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-nacos-discovery/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-starter-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT spring-cloud-starter-alibaba-nacos-discovery Spring Cloud Starter Alibaba Nacos Discovery diff --git a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml index 32aab630f..9d202c543 100644 --- a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml +++ b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-starter-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT spring-cloud-starter-alibaba-sentinel Spring Cloud Starter Alibaba Sentinel @@ -15,18 +15,6 @@ org.springframework.cloud spring-cloud-alibaba-sentinel - - com.alibaba.csp - sentinel-datasource-nacos - - - com.alibaba.csp - sentinel-datasource-zookeeper - - - com.alibaba.csp - sentinel-datasource-apollo - diff --git a/spring-cloud-starter-alicloud/pom.xml b/spring-cloud-starter-alicloud/pom.xml index a28fc12b4..eb2ae1aa9 100644 --- a/spring-cloud-starter-alicloud/pom.xml +++ b/spring-cloud-starter-alicloud/pom.xml @@ -4,7 +4,7 @@ org.springframework.cloud spring-cloud-alibaba - 0.2.0 + 0.2.1.BUILD-SNAPSHOT spring-cloud-starter-alicloud pom @@ -12,5 +12,7 @@ Spring Cloud Alibaba Cloud Starters spring-cloud-starter-alicloud-oss + spring-cloud-starter-alicloud-acm + spring-cloud-starter-alicloud-ans \ No newline at end of file diff --git a/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-acm/pom.xml b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-acm/pom.xml new file mode 100644 index 000000000..4f878e58f --- /dev/null +++ b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-acm/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + + + org.springframework.cloud + spring-cloud-starter-alicloud + 0.2.1.BUILD-SNAPSHOT + + spring-cloud-starter-alicloud-acm + Spring Cloud Starter Alibaba Cloud ACM + + + + org.springframework.cloud + spring-cloud-alicloud-acm + + + + diff --git a/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-ans/pom.xml b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-ans/pom.xml new file mode 100644 index 000000000..002adbbff --- /dev/null +++ b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-ans/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-starter-alicloud + 0.2.1.BUILD-SNAPSHOT + + + spring-cloud-starter-alicloud-ans + Spring Cloud Starter Alibaba Cloud ANS + + + + org.springframework.cloud + spring-cloud-alicloud-ans + + + + \ No newline at end of file diff --git a/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-oss/pom.xml b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-oss/pom.xml index 74ed72f33..ad465ec2e 100644 --- a/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-oss/pom.xml +++ b/spring-cloud-starter-alicloud/spring-cloud-starter-alicloud-oss/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-starter-alicloud - 0.2.0 + 0.2.1.BUILD-SNAPSHOT spring-cloud-starter-alicloud-oss Spring Cloud Starter Alibaba Cloud OSS