要使用 SOFABoot,需要先准备好基础环境,SOFABoot 依赖以下环境:

  • JDK7 或 JDK8
  • 需要采用 Apache Maven 3.2.5 或者以上的版本来编译

创建工程

SOFABoot 是直接构建在 Spring Boot 之上,因此可以使用 来生成,在本文档中,我们需要添加一个 Web 的依赖,以便最后在浏览器中查看效果。

在创建好一个 Spring Boot 的工程之后,接下来就需要引入 SOFABoot 的依赖,首先,需要将上文中生成的 Spring Boot 工程的 包解压后,修改 maven 项目的配置文件 pom.xml,将

替换为:

  1. <parent>
  2. <groupId>com.alipay.sofa</groupId>
  3. <artifactId>sofaboot-dependencies</artifactId>
  4. <version>2.4.0</version>
  5. </parent>

然后,添加一个 SOFABoot 健康检查扩展能力的依赖:

  1. <dependency>
  2. <groupId>com.alipay.sofa</groupId>
  3. <artifactId>healthcheck-sofa-boot-starter</artifactId>
  4. </dependency>

最后,在工程的 application.properties 文件下添加一个 SOFABoot 必须要使用的参数,包括spring.application.name 用于标示当前应用的名称;logging path 用于指定日志的输出目录。

  1. # Application Name
  2. spring.application.name=SOFABoot Demo
  3. # logging path
  4. logging.path=./logs

运行

可以将工程导入到 IDE 中运行生成的工程里面中的 main 方法(一般上在 XXXApplication 这个类中)启动应用,也可以直接在该工程的根目录下运行 mvn spring-boot:run,将会在控制台中看到启动打印的日志:

  1. 2018-04-05 21:36:26.572 INFO ---- Initializing ProtocolHandler ["http-nio-8080"]
  2. 2018-04-05 21:36:26.587 INFO ---- Starting ProtocolHandler [http-nio-8080]
  3. 2018-04-05 21:36:26.608 INFO ---- Using a shared selector for servlet write/read
  4. 2018-04-05 21:36:26.659 INFO ---- Tomcat started on port(s): 8080 (http)

可以通过在浏览器中输入 来查看当前 SOFABoot 中使用 Maven 插件生成的版本信息汇总,结果类似如下:

  1. [
  2. {
  3. GroupId: "com.alipay.sofa",
  4. Doc-Url: "https://github.com/alipay/sofa-boot",
  5. ArtifactId: "infra-sofa-boot-starter",
  6. Built-Time: "2018-04-05T20:55:26+0800",
  7. Commit-Time: "2018-04-05T20:54:26+0800",
  8. Commit-Id: "049bf890bb468aafe6a3e07b77df45c831076996",
  9. Version: "2.4.0"
  10. }
  11. ]

可以通过在浏览器中输入 http://localhost:8080/health/readiness 查看应用 Readiness Check 的状况,类似如下:

  1. {
  2. status: "UP",
  3. sofaBootComponentHealthCheckInfo: {
  4. status: "UP"
  5. },
  6. springContextHealthCheckInfo: {
  7. status: "UP"
  8. },
  9. DiskSpace: {
  10. status: "UP",
  11. total: 250140434432,
  12. free: 22845308928,
  13. threshold: 10485760
  14. }
  15. }

status: "UP" 表示应用 Readiness Check 健康的。可以通过在浏览器中输入 http://localhost:8080/health 来查看应用的运行时健康状态(可能会随着时间发生变化)。

在上面的 application.properties 里面,我们配置的日志打印目录是 ./logs 即当前应用的根目录(我们可以根据自己的实践需要配置),在当前工程的根目录下可以看到类似如下结构的日志文件:

  1. ./logs
  2. ├── sofaboot-common-default.log
  3. └── sofaboot-common-error.log
  4. ├── infra
  5. ├── common-default.log
  6. └── common-error.log
  7. └── spring.log

如果应用启动失败或者健康检查返回失败,可以通过相应的日志文件找到错误的原因,有些需要关注 common-error.log 日志。

测试

我们知道,SpringBoot 官方提供了和 JUnit4 集成的 , 用于集成测试用例的编写; 在 SOFABoot 中,依然可以使用原生的 SpringRunner, 但是推荐使用 SOFABoot 自带的 SofaBootRunner 以及 SofaJUnit4Runner 编写集成测试和单元测试;应用需要额外引入如下 Starter:

  1. <dependency>
  2. <groupId>com.alipay.sofa</groupId>
  3. <artifactId>test-sofa-boot-starter</artifactId>
  4. </dependency>

需要注意的是,如果需要使用 SOFABoot 的类隔离的能力,则必须需要引入上述的依赖,并且使用 SofaBootRunnerSofaJUnit4Runner 来测试。

这部分将演示如何在 SOFABoot 环境下进行模块化开发,您可以直接在工程下找到本文档的,项目一共包括四个模块:

各个模块的作用如下:

  • service-facade: 演示 JVM 服务发布与引用的 API 包;
  • service-provider: 演示 XML 方式、Annotation 方式、API 方式发布 JVM 服务;
  • service-consumer: 演示 XML 方式、Annotation 方式、API 方式引用 JVM 服务;
  • sofa-boot-run: 启动包含 SOFABoot 模块的 SOFA Boot 应用。

service-facade 模块包含用于演示 JVM 服务发布与引用的 API :

  1. public interface SampleJvmService {
  2. String message();
  3. }

service-provider 是一个 SOFABoot 模块,用于演示 XML 方式、Annotation 方式、API 方式发布 JVM 服务。

定义 SOFABoot 模块

为 service-provider 模块增加 sofa-module.properties 文件,将其定义为 SOFABoot 模块:

  1. Module-Name=com.alipay.sofa.service-provider

XML 方式发布服务

实现 SampleJvmService 接口:

  1. public class SampleJvmServiceImpl implements SampleJvmService {
  2. private String message;
  3. @Override
  4. public String message() {
  5. System.out.println(message);
  6. return message;
  7. }
  8. // getters and setters
  9. }

增加 META-INF/spring/service-provide.xml 文件,将 SampleJvmServiceImpl 发布为 JVM 服务:

  1. <bean id="sampleJvmService" class="com.alipay.sofa.isle.sample.SampleJvmServiceImpl">
  2. <property name="message" value="Hello, jvm service xml implementation."/>
  3. </bean>
  4. <sofa:service ref="sampleJvmService" interface="com.alipay.sofa.isle.sample.SampleJvmService">
  5. <sofa:binding.jvm/>
  6. </sofa:service>

Annotation 方式发布服务

实现 SampleJvmService 接口并增加 注解:

  1. @SofaService(uniqueId = "annotationImpl")
  2. public class SampleJvmServiceAnnotationImpl implements SampleJvmService {
  3. @Override
  4. public String message() {
  5. String message = "Hello, jvm service annotation implementation.";
  6. System.out.println(message);
  7. return message;
  8. }
  9. }

为了区分 XML 方式发布的 JVM 服务,注解上需要增加 uniqueId 属性。

将 SampleJvmServiceAnnotationImpl 配置成一个 Spring Bean,保证 @SofaService 注解生效:

  1. <bean id="sampleJvmServiceAnnotation" class="com.alipay.sofa.isle.sample.SampleJvmServiceAnnotationImpl"/>

API 方式发布服务

  1. public class PublishServiceWithClient implements ClientFactoryAware {
  2. private ClientFactory clientFactory;
  3. public void init() {
  4. ServiceClient serviceClient = clientFactory.getClient(ServiceClient.class);
  5. ServiceParam serviceParam = new ServiceParam();
  6. serviceParam.setInstance(new SampleJvmServiceImpl(
  7. "Hello, jvm service service client implementation."));
  8. serviceParam.setInterfaceType(SampleService.class);
  9. serviceParam.setUniqueId("serviceClientImpl");
  10. serviceClient.service(serviceParam);
  11. }
  12. @Override
  13. public void setClientFactory(ClientFactory clientFactory) {
  14. this.clientFactory = clientFactory;
  15. }
  16. }

将 PublishServiceWithClient 配置为 Spring Bean,并设置 init-method ,使PublishServiceWithClient 在 Spring 刷新时发布服务:

  1. <bean id="publishServiceWithClient" class="com.alipay.sofa.isle.sample.PublishServiceWithClient" init-method="init"/>

service-consumer 是一个 SOFABoot 模块,用于演示 XML 方式、Annotation 方式、API 方式引用 JVM 服务。

定义 SOFABoot 模块

为 service-consumer 模块增加 sofa-module.properties 文件,将其定义为 SOFABoot 模块:

在 sofa-module.properties 文件中需要指定 Require-Module,保证 service-provider 模块在 service-consumer 模块之前刷新。

XML 方式引用服务

增加 META-INF/spring/service-consumer.xml 文件,引用 service-provider 模块发布的服务:

  1. <sofa:binding.jvm/>

Annotation 方式引用服务

定义 JvmServiceConsumer 类,并在其 sampleJvmServiceAnnotationImpl 属性上增加 注解:

  1. public class JvmServiceConsumer implements ClientFactoryAware {
  2. @SofaReference(uniqueId = "annotationImpl")
  3. private SampleJvmService sampleJvmServiceAnnotationImpl;
  4. }

将 JvmServiceConsumer 配置成一个 Spring Bean,保证 @SofaReference 注解生效:

  1. <bean id="consumer" class="com.alipay.sofa.isle.sample.JvmServiceConsumer" init-method="init" />

API 方式引用服务

JvmServiceConsumer 实现 ClientFactoryAware 接口,并在其 init 方法中引用 JVM 服务:

  1. public class JvmServiceConsumer implements ClientFactoryAware {
  2. private ClientFactory clientFactory;
  3. public void init() {
  4. ReferenceClient referenceClient = clientFactory.getClient(ReferenceClient.class);
  5. ReferenceParam<SampleJvmService> referenceParam = new ReferenceParam<>();
  6. referenceParam.setInterfaceType(SampleJvmService.class);
  7. referenceParam.setUniqueId("serviceClientImpl");
  8. SampleJvmService sampleJvmServiceClientImpl = referenceClient.reference(referenceParam);
  9. sampleJvmServiceClientImpl.message();
  10. }
  11. @Override
  12. public void setClientFactory(ClientFactory clientFactory) {
  13. this.clientFactory = clientFactory;
  14. }
  15. }

将模块 parent 配置为 SOFABoot:

  1. <parent>
  2. <groupId>com.alipay.sofa</groupId>
  3. <artifactId>sofaboot-dependencies</artifactId>
  4. <version>2.4.0</version>
  5. </parent>

为模块增加 isle-sofa-boot-starter 及 service-provider 、 service-consumer 依赖:

  1. <dependency>
  2. <groupId>com.alipay.sofa</groupId>
  3. <artifactId>isle-sofa-boot-starter</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>com.alipay.sofa</groupId>
  7. <artifactId>service-provider</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>com.alipay.sofa</groupId>
  11. <artifactId>service-consumer</artifactId>
  12. </dependency>

启动 ApplicationRun 类,控制台将看到以下输出:

  1. Hello, jvm service xml implementation.
  2. Hello, jvm service annotation implementation.
  3. Hello, jvm service service client implementation.

SOFABoot 模块化测试方法与 Spring Boot 测试方法一致,只需在测试用例上增加 @SpringBootTest 注解及 (SpringRunner.class) 注解即可。在测试用例中,还可以使用 @SofaReference 注解,对 SOFABoot 模块发布的服务进行测试:

  1. @SpringBootTest
  2. @RunWith(SpringRunner.class)
  3. public class SofaBootWithModulesTest {
  4. @SofaReference
  5. private SampleJvmService sampleJvmService;
  6. @SofaReference(uniqueId = "annotationImpl")
  7. private SampleJvmService sampleJvmServiceAnnotationImpl;
  8. @SofaReference(uniqueId = "serviceClientImpl")
  9. private SampleJvmService sampleJvmServiceClientImpl;
  10. @Test
  11. public void test() {
  12. Assert.assertEquals("Hello, jvm service xml implementation.", sampleJvmService.message());
  13. Assert.assertEquals("Hello, jvm service annotation implementation.",
  14. sampleJvmServiceAnnotationImpl.message());
  15. Assert.assertEquals("Hello, jvm service service client implementation.",
  16. sampleJvmServiceClientImpl.message());
  17. }