Tio Boot 整合 Spring Boot Starter
简介
传统上,我们通过引入 spring-boot-starter-web
,将 Spring Boot 的 Controller 与 Tio Boot 的 Service 进行整合。然而,这种方法虽然可行,但却丢失了 Tio Boot 在处理请求时的异步和非阻塞特性。
为了解决这一问题,我们提出了一种新的整合方法:仅集成 spring-boot-starter
,并使用 Tio Boot 的 Controller 来处理请求。这样既能保持 Tio Boot 的性能优势,又能利用 Spring Boot 的生态系统。
整合步骤
1. Maven 配置(pom.xml)
首先,配置 Maven 项目的 pom.xml
文件,关键点包括:
- Java 和 Spring Boot 版本:确保使用兼容的版本。
- 依赖项:除了
spring-boot-starter
,还需要引入tio-boot
、Lombok、Druid 数据库连接池、MySQL 驱动等。 - 构建插件:使用
spring-boot-maven-plugin
支持热部署和其他特性。
```xml
<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>
<hotswap-classloader.version>1.2.6</hotswap-classloader.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>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>hotswap-classloader</artifactId>
<version>${hotswap-classloader.version}</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>
2. 启动类(Application)
定义应用的主启动类,使用 Tio Boot 启动应用程序。
package com.litongjava.spring.boot.tio.boot.demo01;
import com.litongjava.hotswap.wrapper.tio.boot.TioApplicationWrapper;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
@AComponentScan
public class Application {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// 启动 Tio Boot
TioApplicationWrapper.run(Application.class, args);
long end = System.currentTimeMillis();
System.out.println("启动耗时:" + (end - start) + "ms");
}
}
3. 配置类(Configuration)
3.1 整合 Spring Boot
创建配置类,整合 Spring Boot 和 Tio Boot。
package com.litongjava.spring.boot.tio.boot.demo01.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.AopManager;
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
import com.litongjava.spring.boot.tio.boot.demo01.Application;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.utils.environment.EnvUtils;
@AConfiguration
public class SpringConfig {
@Initialization
public void config() {
// 启动 Spring Boot
ConfigurableApplicationContext context = SpringApplication.run(Application.class, EnvUtils.getArgs());
// 开启与 Spring 的整合
AopManager.me().getAopFactory().setEnableWithSpring(true);
SpringBeanContextUtils.setContext(context);
// 支持 @Autowired 注解
Aop.addFetchBeanAnnotation(Autowired.class);
// 注册关闭钩子
TioBootServer.me().addDestroyMethod(context::close);
}
}
3.2 整合 ActiveRecordPlugin
配置数据库连接池和 ActiveRecordPlugin。
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.annotation.AConfiguration;
import com.litongjava.tio.boot.server.TioBootServer;
@AConfiguration
public class ActiveRecordPluginConfig {
public void activeRecordPlugin() {
String jdbcUrl = "jdbc:mysql://localhost:3306/your_database";
String jdbcUser = "your_username";
String jdbcPswd = "your_password";
// 配置 Druid 数据库连接池
DruidPlugin druidPlugin = new DruidPlugin(jdbcUrl, jdbcUser, jdbcPswd);
druidPlugin.start();
// 配置 ActiveRecordPlugin
ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
arp.setContainerFactory(new OrderedFieldContainerFactory());
arp.start();
// 注册关闭钩子
TioBootServer.me().addDestroyMethod(() -> {
druidPlugin.stop();
arp.stop();
});
}
}
4. 编写 Service 和 Controller
4.1 定义 Service 接口和实现
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();
}
Service 实现类:
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 {
@Override
public List<Record> listAll() {
return Db.findAll("user");
}
}
4.2 定义 Controller
使用 Tio Boot 的 @RequestPath
注解定义路由。
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.annotation.RequestPath;
@RequestPath("/user")
public class UserController {
public List<Record> listAll() {
return Aop.get(UserService.class).listAll();
}
}
5. 启动和测试
启动应用后,访问 http://localhost/user/listAll
以测试接口。
6. 单元测试
6.1 测试 Service 层
package com.litongjava.spring.boot.tio.boot.demo01.services;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.spring.boot.tio.boot.demo01.Application;
import com.litongjava.spring.boot.tio.boot.demo01.service.UserService;
import com.litongjava.tio.boot.testing.TioBootTest;
import com.litongjava.jfinal.plugin.activerecord.Record;
public class UserServiceTest {
@Before
public void setUp() {
TioBootTest.before(Application.class);
}
@Test
public void testListAll() {
UserService userService = Aop.get(UserService.class);
List<Record> users = userService.listAll();
System.out.println(users);
}
}
6.2 测试 Spring 上下文
package com.litongjava.spring.boot.tio.boot.demo01.services;
import org.junit.Before;
import org.junit.Test;
import com.litongjava.jfinal.spring.SpringBeanContextUtils;
import com.litongjava.spring.boot.tio.boot.demo01.Application;
import com.litongjava.tio.boot.TioApplication;
import com.litongjava.tio.utils.json.JsonUtils;
public class SpringContextTest {
@Before
public void setUp() {
TioApplication.run(Application.class, new String[] {});
}
@Test
public void testBeanDefinitions() {
String[] beanNames = SpringBeanContextUtils.getContext().getBeanDefinitionNames();
System.out.println(JsonUtils.toJson(beanNames));
}
}
[
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor",
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor",
"org.springframework.context.annotation.internalCommonAnnotationProcessor",
"org.springframework.context.event.internalEventListenerProcessor",
"org.springframework.context.event.internalEventListenerFactory",
"applicaton",
"org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory",
"org.springframework.boot.autoconfigure.AutoConfigurationPackages",
"org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration",
"propertySourcesPlaceholderConfigurer",
"org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration",
"forceAutoProxyCreatorToUseClassProxying",
"org.springframework.boot.autoconfigure.aop.AopAutoConfiguration",
"org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration",
"applicationAvailability",
"org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration",
"org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor",
"org.springframework.boot.context.internalConfigurationPropertiesBinderFactory",
"org.springframework.boot.context.internalConfigurationPropertiesBinder",
"org.springframework.boot.context.properties.BoundConfigurationProperties",
"org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar.methodValidationExcludeFilter",
"org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration",
"lifecycleProcessor",
"spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties",
"org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration",
"spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties",
"org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration",
"spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties",
"org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor",
"org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration",
"taskExecutorBuilder",
"applicationTaskExecutor",
"spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties",
"org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration",
"scheduledBeanLazyInitializationExcludeFilter",
"taskSchedulerBuilder",
"spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties",
"org.springframework.aop.config.internalAutoProxyCreator"
]
通过以上步骤,我们成功实现了 Tio Boot 与 Spring Boot 的整合,既保留了 Tio Boot 的异步非阻塞特性,又充分利用了 Spring Boot 的生态优势。