## 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.3</version> </dependency> <dependency> <groupId>com.litongjava</groupId> <artifactId>jfinal-plugins</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 应用的启动类:
```java 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 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) 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 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); } } ```