Tio Boot 与 Spring Boot Starter 的集成

背景

在以前的整合模式中,我们通过 spring-boot-starter-web 将 Spring Boot 的 Controller 与 Tio Boot 的 Service 相整合。这种方法虽然能够工作,但却失去了 Tio Boot 在处理请求时的异步和非阻塞特性。

新的整合方式

为了充分利用 Tio Boot 的异步和非阻塞优势,我们提出了一个新的整合方法:仅仅整合 spring-boot-starter,并使用 Tio Boot 的 Controller 来处理请求。

Maven 配置(pom.xml)

首先,我们配置 Maven 项目的 pom.xml 文件。以下是主要的配置部分:

  1. Java 和 Spring Boot 版本设置:确保使用适合的 Java 版本和 Spring Boot 版本。
  2. 依赖项:除了标准的 Spring Boot Starter 依赖,还包括 tio-boot 和其他必要的库,如 Lombok、数据库连接池(Druid)和数据库驱动(MySQL)。
  3. 构建配置:使用 spring-boot-maven-plugin 来支持热启动和其他 Spring Boot 特性。
<properties>
  <java.version>1.8</java.version>
  <maven.compiler.source>${java.version}</maven.compiler.source>
  <maven.compiler.target>${java.version}</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <spring-boot.version>2.5.6</spring-boot.version>
  <main.class>com.litongjava.spring.boot.tio.boot.demo01.Applicaton</main.class>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
  </dependency>

  <!-- SpringBoot集成Test -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>com.litongjava</groupId>
    <artifactId>tio-boot</artifactId>
    <version>1.3.5</version>
  </dependency>

  <dependency>
    <groupId>com.litongjava</groupId>
    <artifactId>java-db</artifactId>
    <version>1.0.3</version>
  </dependency>
  <!-- 连接池 -->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
  </dependency>
  <!-- 数据库驱动 -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>

</dependencies>

<build>
  <plugins>
    <!-- Spring Boot -->
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <version>${spring-boot.version}</version>
      <configuration>
        <includeSystemScope>true</includeSystemScope>
        <!--使该插件支持热启动 -->
        <fork>true</fork>
        <mainClass>${main.class}</mainClass>
        <excludeGroupIds>org.projectlombok</excludeGroupIds>
      </configuration>
      <!-- 设置执行目标 -->
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring-boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

启动类(Application)

接下来,定义 Spring Boot 应用的启动类:

package com.litongjava.spring.boot.tio.boot.demo01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.litongjava.jfinal.aop.annotation.AComponentScan;

@SpringBootApplication
@AComponentScan
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

这个类标记为 Spring Boot 应用,并启动整个应用。

配置类(Configuration)

配置类负责整合 Tio Boot:

package com.litongjava.spring.boot.tio.boot.demo01.config;

import org.springframework.boot.ApplicationArguments;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.litongjava.spring.boot.tio.boot.demo01.Applicaton;
import com.litongjava.tio.boot.TioApplication;
import com.litongjava.tio.boot.context.Context;

@Configuration
public class TioApplicationConfig {

  @Bean(destroyMethod = "close")
  public Context myBean(ApplicationArguments args) {
    String[] sourceArgs = args.getSourceArgs();
    return TioApplication.run(Applicaton.class, sourceArgs);
  }
}

配置类负责整合 ActiveRecordPlugin

package com.litongjava.spring.boot.tio.boot.demo01.config;

import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.annotation.ABean;
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.litongjava.jfinal.plugin.activerecord.OrderedFieldContainerFactory;
import com.litongjava.jfinal.plugin.druid.DruidPlugin;

@AConfiguration
public class ActiveRecordPluginConfig {
  @ABean(priority = 10,destroyMethod = "stop")
  public DruidPlugin druidPlugin() {
    String jdbcUrl = "jdbc:mysql://192.168.3.9:3306/mybatis_plus_study";
    String jdbcUser = "root";
    String jdbcPswd = "robot_123456#";

    DruidPlugin druidPlugin = new DruidPlugin(jdbcUrl, jdbcUser, jdbcPswd);
    druidPlugin.start();
    return druidPlugin;
  }

  @ABean(destroyMethod = "stop")
  public ActiveRecordPlugin activeRecordPlugin() {
    DruidPlugin druidPlugin = Aop.get(DruidPlugin.class);
    ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
    arp.setContainerFactory(new OrderedFieldContainerFactory());
    arp.start();
    return arp;
  }
}

Service 和 Controller

定义 Service 接口和实现,以及相应的 Controller 来处理请求。例如,UserController 使用 Tio Boot 的注解 @RequestPath 来定义路由。 service

package com.litongjava.spring.boot.tio.boot.demo01.service;

import java.util.List;

import com.litongjava.jfinal.plugin.activerecord.Record;

public interface UserService {
  List<Record> listAll();
}
package com.litongjava.spring.boot.tio.boot.demo01.service;

import java.util.List;

import com.litongjava.jfinal.aop.annotation.AService;
import com.litongjava.jfinal.plugin.activerecord.Db;
import com.litongjava.jfinal.plugin.activerecord.Record;

@AService
public class UserServiceImpl implements UserService {

  public List<Record> listAll() {
    return Db.findAll("user");
  }
}

controller

package com.litongjava.spring.boot.tio.boot.demo01.controller;

import java.util.List;

import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.plugin.activerecord.Record;
import com.litongjava.spring.boot.tio.boot.demo01.service.UserService;
import com.litongjava.tio.http.server.annotation.RequestPath;

@RequestPath("/user")
public class UserController {

  public List<Record> listAll() {
    return Aop.get(UserService.class).listAll();
  }
}

启动测试

启动访问 http://localhost/user/listAll

###单独测试 Service 我们可以编写单元测试来测试 Service 层的逻辑。

package com.litongjava.spring.boot.tio.boot.demo01.services;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.plugin.activerecord.Record;
import com.litongjava.spring.boot.tio.boot.demo01.Applicaton;
import com.litongjava.spring.boot.tio.boot.demo01.service.UserService;
import com.litongjava.tio.boot.TioApplication;

public class UserServiceTest {

  @Before
  public void before() {
    List<String> list = new ArrayList<String>();
    list.add("--tio.noServer=true");
    String[] args = list.toArray(new String[] {});
    TioApplication.run(Applicaton.class, args);
  }

  @Test
  public void test() {
    UserService userService = Aop.get(UserService.class);
    List<Record> listAll = userService.listAll();
    System.out.println(listAll);
  }
}