Spring Boot 的整合 Tio Boot
简介
这边文章讲解,如果使用 spring-boot 整合 tio-boot
- 使用 spring-boot 自带的 servlet 容器
- 使用 spring-boot 的 controller
- 使用 tio-boot 的其他部分
什么是 Spring Boot 框架?
- Spring Boot 是一个广泛使用的框架,它提供了一种快速、简单的方式来设置和启动 Spring 应用。它的自动配置、内置服务器和控制器使得开发 Web 应用变得更加容易。
为什么使用 Spring Boot 框架整合 Tio-Boot? 使用 Spring Boot 整合 Tio-Boot 有以下几个优势:
- Tio-Boot 框架的代码可以在 Spring Boot 框架下运行。
- 开发时使用 Tio-Boot 框架进行快速开发,开发完成后使用 Spring Boot 框架运行。
- 可以利用 Spring Boot 对微服务的支持,将 Tio-Boot 框架作为一个微服务整合到 Spring Cloud 中。
Spring Boot 和 Tio-Boot 能否实现无缝整合?
- 无法实现完全无缝的整合。
- 对于 HTTP 服务器、请求参数封装、控制器以及微服务,仍然使用 Spring Boot 框架。
- 对于其他服务,如服务器和数据库查询等,使用 Tio-Boot 框架。
- 整合 Spring Boot 之后因为使用的是 spring-boot 内置的 http server 将无法使用 tio boot 的异步和非阻塞的方式处理网络请求
整合
添加依赖
请将以下依赖添加到你的项目中,这些依赖包括 spring-boot 和 tio-boot 的相关依赖,以及一些其他必要的库。
properties:这部分定义了一些全局变量,可以在 pom.xml 文件的其他地方引用。例如,
${java.version}
在这里被定义为1.8
,然后在<maven.compiler.source>
和<maven.compiler.target>
中被引用,表示编译源代码和目标 JVM 的版本都是 1.8。dependencies:这部分列出了项目所依赖的库。每个
<dependency>
标签定义了一个依赖项,包括其 groupId(通常是项目的包名),artifactId(项目名),以及版本号。有些依赖项还定义了<scope>
,这决定了依赖在什么阶段可用。例如,<scope>test</scope>
表示这个依赖只在测试阶段可用。
- spring-boot-starter-web:这是 Spring Boot 的一个启动器,它包含了创建一个基于 Spring MVC 的 Web 应用所需的所有依赖。这意味着你的项目可能是一个 Web 应用。
- lombok:Lombok 是一个可以通过注解的方式,使 Java 代码更简洁的库。它提供了一系列的注解,如
@Data
,@Getter
,@Setter
等,可以自动为类生成 getter 和 setter 方法,以及equals()
,hashCode()
和toString()
方法。<scope>provided</scope>
表示这个依赖在编译和运行时都需要,但在打包成最终的 JAR 或 WAR 文件时,不需要包含进去。
- lombok:Lombok 是一个可以通过注解的方式,使 Java 代码更简洁的库。它提供了一系列的注解,如
- spring-boot-starter-test 和 junit:这两个依赖都是用于测试的。
spring-boot-starter-test
包含了使用 Spring Boot 进行集成测试所需的所有依赖,而junit
是 Java 的一个单元测试框架。这两个依赖的<scope>
都被设置为test
,表示它们只在测试阶段可用。
- spring-boot-starter-test 和 junit:这两个依赖都是用于测试的。
- tio-boot: 高性能的 JavaWeb 开发框架
- java-db:JFinal 框架的插件库。
- druid:Druid 是 Alibaba 开发的一个数据库连接池。它提供了强大的监控和扩展功能。
7 mysql-connector-java:这是 MySQL 的 JDBC 驱动,用于在 Java 应用中连接 MySQL 数据库。
build:这部分定义了构建项目时要使用的插件和配置。在这里,你使用了
spring-boot-maven-plugin
插件,它可以创建一个可执行的 JAR 文件,包含了所有的依赖和应用服务器。dependencyManagement:这部分允许你集中管理项目中所有的版本号,避免在每个
<dependency>
标签中都要写版本号。在这里,你引入了spring-boot-dependencies
,这是一个特殊的依赖,它包含了 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-web</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>hotswap-classloader</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>java-db</artifactId>
<version>1.2.5</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>
编写代码
启动类
这是一个 Spring Boot 应用的启动类,它同时启动了 SpringApplication 和 TioApplication。:
@SpringBootApplication:这是一个组合注解,它包含了
@AConfiguration
,@EnableAutoConfiguration
和@AComponentScan
。这个注解告诉 Spring Boot 这个类是一个配置类,也是自动配置和组件扫描的起点。@AComponentScan:这是一个自定义注解,用于 tio-boot 扫描类
main 方法:这是 Java 程序的入口点。在这个方法中,首先启动了 SpringApplication,然后又启动了 TioApplication。
SpringApplication.run(Applicaton.class, args):这行代码启动了 Spring Boot 应用。它会创建一个 Spring 应用上下文,执行自动配置,然后启动 Spring Boot 的内嵌服务器(如果有的话)。
TioApplication.run(Applicaton.class, newArgs):这行代码启动了 TioApplication。在启动之前,它添加了一个参数
--tio.noServer=true
到参数列表中。这个参数的目的是告诉 TioApplication 不启动 Tio Boot 的服务器。这样就可以只启动 Spring Boot 的服务器.
计算启动时间:这段代码计算了从启动 SpringApplication 到启动 TioApplication 的总时间,并打印出来。
package com.litongjava.spring.boot.tio.boot.demo01;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
import com.litongjava.tio.boot.TioApplication;
@SpringBootApplication
@AComponentScan
public class Applicaton {
public static void main(String[] args) {
long start = System.currentTimeMillis();
SpringApplication.run(Applicaton.class, args);
List<String> list = new ArrayList<String>();
for (int i = 0; i < args.length; i++) {
list.add(args[i]);
}
list.add("--tio.no.server=true");
String[] newArgs = list.toArray(new String[] {});
TioApplication.run(Applicaton.class, newArgs);
long end = System.currentTimeMillis();
System.out.println(end - start + "(ms)");
}
}
编写配置类连接数据库
配置类中包含了连接数据库的设置,使用 DruidPlugin 和 ActiveRecordPlugin。
@AConfiguration:这是一个 tio-boot 注解,用于标记这个类是一个配置类。
druidPlugin 方法:这个方法用于创建和配置一个 DruidPlugin 对象,这是一个数据库连接池插件。它使用了
@ABean(priority = 10)
注解用于告诉 Tio Boot 在其他 Bean 之前创建这个 Bean。在这个方法中,首先定义了数据库的连接信息,然后创建了一个 DruidPlugin 对象,并启动了它。activeRecordPlugin 方法:这个方法用于创建和配置一个 ActiveRecordPlugin 对象,这是一个 数库查询 插件。它使用了
@ABean
注解,用于告诉 Tio Boot 这个方法返回的对象应该被管理为一个 Bean。在这个方法中,首先从 Tio Boot 的 Aop 容器中获取了 DruidPlugin 对象,然后创建了一个 ActiveRecordPlugin 对象,并设置了一个新的 OrderedFieldContainerFactory 对象作为其容器工厂,最后启动了它。
package com.litongjava.spring.boot.tio.boot.demo01.config;
import com.litongjava.db.activerecord.ActiveRecordPlugin;
import com.litongjava.db.activerecord.OrderedFieldContainerFactory;
import com.litongjava.db.druid.DruidPlugin;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.annotation.ABean;
import com.litongjava.jfinal.aop.annotation.AConfiguration;
@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;
}
}
编写 UserService 接口
创建 UserService 接口,定义了获取用户列表的方法。
package com.litongjava.spring.boot.tio.boot.demo01.services;
import java.util.List;
import com.litongjava.db.activerecord.Record;
public interface UserService {
List<Record> listAll();
}
编写 UserServiceImpl 实现类
实现 UserService 接口,通过调用数据库操作获取用户列表。这是一个 tio boot 的 service,使用了@AService 注解
package com.litongjava.spring.boot.tio.boot.demo01.services;
import java.util.List;
import com.litongjava.db.activerecord.Db;
import com.litongjava.db.activerecord.Record;
import com.litongjava.jfinal.aop.annotation.AService;
@AService
public class UserServiceImpl implements UserService {
public List<Record> listAll() {
return Db.findAll("user");
}
}
编写 UserController
在 Controller 中调用 UserService,返回获取的用户数据。这个是 spring 的 controller 使用了@RestController,在方法中使用了 Aop.get 方法从 tio boot 的 aop 容器中获取一个 bean
package com.litongjava.spring.boot.tio.boot.demo01.controller;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.litongjava.db.activerecord.Record;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.spring.boot.tio.boot.demo01.services.UserService;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/listAll")
public List<Record> listAll(){
return Aop.get(UserService.class).listAll();
}
}
访问接口测试
启动项目后,访问接口测试:http://localhost:10510/user/listAll
打包成 fastjar
使用以下命令将项目打包成 fastjar:
mvn clean install -DskipTests -Dgpg.skip
启动 fastjar
使用以下命令启动 fastjar:
java -jar target\spring-boot-2.5.6-tio-boot-1.0.jar
再次访问接口测试:http://localhost:10510/user/listAll
测试 UserService
编写一个测试类 UserServiceTest,测试 UserService
package com.litongjava.spring.boot.tio.boot.demo01.services;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.litongjava.db.activerecord.Record;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.spring.boot.tio.boot.demo01.Applicaton;
import com.litongjava.tio.boot.tesing.TioBootTest;
public class UserServiceTest {
@Before
public void before() {
try {
TioBootTest.scan(Applicaton.class);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void test() {
UserService userService = Aop.get(UserService.class);
List<Record> listAll = userService.listAll();
System.out.println(listAll);
}
}
这是一个使用 JUnit 框架编写的测试类,用于测试 UserService
类的功能。
@Before:这是一个 JUnit 注解,表示
before()
方法会在每个测试方法执行之前运行。在这个方法中,它启动了 TioApplication,但是通过添加--tio.noServer=true
参数,不启动 Tio Boot 的服务器。@Test:这是一个 JUnit 注解,表示
test()
方法是一个测试方法。在这个方法中,首先从 tio-boot aop 容器中获取了UserService
对象,然后调用了listAll()
方法获取所有的用户记录,并打印出来。
这个测试类的目的是验证 UserService
类的 listAll()
方法是否能正确地获取所有的用户记录。