写给正在做技术选型或迁移调研的 Java 开发者
一、写在前面
如果你会 Spring Boot,那你已经会了一大半 Solon。
Solon 不是 Spring 的分支或封装,它是独立发展的全栈应用开发框架。但在设计哲学上,Solon 遵循了 Java 主流的 IoC、AOP、MVC 范式------概念相同,注解名不同。
这篇文章把 Spring Boot 到 Solon 的注解映射、配置迁移、关键差异整理成对照表,供迁移参考。
二、IoC/DI 容器:注解对照
核心原则:Solon 将 Spring 的多个细分注解合并为少数几个核心注解。
2.1 组件注册
| Solon | Spring Boot | 说明 |
|---|---|---|
@Component |
@Component / @Service / @Repository / @Dao |
Solon 统一用一个注解 |
@Configuration |
@Configuration |
完全一致 |
@Bean |
@Bean |
完全一致 |
2.2 依赖注入
| Solon | Spring Boot | 说明 |
|---|---|---|
@Inject |
@Autowired |
按类型注入(by type) |
@Inject("name") |
@Qualifier + @Autowired |
按名称注入(by name) |
@Inject("${key}") |
@Value("${key}") |
注入配置值 |
@BindProps(prefix="xxx") |
@ConfigurationProperties(prefix="xxx") |
绑定属性集 |
注意 :Solon 的
@Inject一个注解兼顾了 Spring 中@Autowired、@Qualifier、@Value三个注解的功能。
2.3 生命周期与作用域
| Solon | Spring Boot | 说明 |
|---|---|---|
@Init |
@PostConstruct |
组件初始化回调 |
@Destroy |
@PreDestroy |
组件销毁回调 |
LifecycleBean |
InitializingBean + DisposableBean |
接口方式控制生命周期 |
AppLoadEndEvent |
ApplicationRunner / CommandLineRunner |
应用启动后执行 |
@Singleton(默认) |
@Scope("singleton") |
单例(Solon 默认) |
@Singleton(false) |
@Scope("prototype") |
多例 |
@Condition(...) |
@ConditionalOnClass / @ConditionalOnProperty 等 |
Solon 统一为单一注解 |
@Import |
@Import + @ComponentScan |
导入组件/配置类 |
三、Web 层:Controller 改写
3.1 注解映射
| Solon | Spring Boot | 说明 |
|---|---|---|
@Controller |
@Controller / @RestController |
Solon 默认 JSON 输出 |
@Mapping |
@RequestMapping |
路由映射 |
@Get + @Mapping |
@GetMapping |
GET 方法限定 |
@Post + @Mapping |
@PostMapping |
POST 方法限定 |
@Put + @Mapping |
@PutMapping |
PUT 方法限定 |
@Delete + @Mapping |
@DeleteMapping |
DELETE 方法限定 |
@Param |
@RequestParam |
请求参数 |
@Path |
@PathVariable |
路径变量 |
@Body |
@RequestBody |
请求体 |
@Header |
@RequestHeader |
请求头 |
@Cookie |
@CookieValue |
Cookie |
@Produces |
---(Spring 无直接等价) | 声明输出类型 |
@Consumes |
---(Spring 无直接等价) | 声明输入类型 |
3.2 Before / After 示例
Spring Boot 写法:
java
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public User create(@RequestBody User user) {
return userService.save(user);
}
}
Solon 写法:
java
@Controller
@Mapping("/users")
public class UserController {
@Inject
private UserService userService;
@Get
@Mapping("/{id}")
public User getUser(@Path Long id) {
return userService.findById(id);
}
@Post
@Mapping
public User create(@Body User user) {
return userService.save(user);
}
}
3.3 关键差异:Context 替代 Servlet API
Solon 不依赖 Servlet 容器 ,因此 HttpServletRequest / HttpServletResponse 需替换为 Context:
java
// Spring 写法
public User get(HttpServletRequest request) {
String token = request.getHeader("Token");
String id = request.getParameter("id");
}
// Solon 写法
public User get(Context ctx) {
String token = ctx.header("Token");
String id = ctx.param("id");
// ctx.redirect(url) 重定向
// ctx.render(obj) 渲染
// ctx.remoteIp() 客户端 IP
}
⚠️
Context只能在方法参数中注入,不能作为字段注入。
四、配置文件迁移
4.1 文件命名
| 项目 | Spring Boot | Solon |
|---|---|---|
| 主配置文件 | application.yml |
app.yml |
| 环境配置文件 | application-dev.yml |
app-dev.yml |
| 激活方式 | spring.profiles.active=dev |
solon.env=dev |
4.2 常用配置键名对照
| 含义 | Spring Boot | Solon |
|---|---|---|
| 应用名 | spring.application.name |
solon.app.name |
| 端口 | server.port |
server.port(不变) |
| 上下文路径 | server.servlet.context-path |
server.contextPath |
| 数据源 | spring.datasource.url |
solon.dataSources.db1.url |
| 日志级别 | logging.level.com.xx |
solon.logging.level.com.xx |
| 环境切换 | spring.profiles.active |
solon.env |
⚠️ Solon 配置键名统一使用驼峰命名 (
contextPath),不是短横线(context-path)。
五、数据访问:@Db 一站式注入
5.1 多数据源配置(YAML)
yaml
solon.dataSources:
db1:
class: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://localhost/test
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: 123456
db2:
url: jdbc:mysql://localhost/order
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: 123456
5.2 @Db 注入
java
// Solon 一行搞定多数据源
@Db("db1") UserMapper userMapper;
@Db("db2") OrderMapper orderMapper;
对比 Spring Boot 多数据源需要配置:多个 DataSource + 多个 SqlSessionFactory + 多个 TransactionManager + @MapperScan... Solon 使用 @Db。
5.3 ORM 集成
| ORM | Spring Boot 依赖 | Solon 依赖 |
|---|---|---|
| MyBatis | mybatis-spring-boot-starter |
mybatis-solon-plugin |
| MyBatis-Plus | mybatis-plus-spring-boot-starter |
mybatis-plus-solon-plugin |
| JPA | spring-boot-starter-data-jpa |
solon-data-jpa |
| Easy-Query | easy-query-spring-boot-starter |
easy-query-solon-plugin |
5.4 事务
| Solon | Spring Boot | 说明 |
|---|---|---|
@Transaction |
@Transactional |
声明式事务 |
@Transaction(policy = TranPolicy.requires_new) |
@Transactional(propagation = Propagation.REQUIRES_NEW) |
事务传播策略 |
Solon 的
@Transaction默认遇到任何异常都回滚,无需指定异常类型。
六、测试迁移
| Solon | Spring Boot | 说明 |
|---|---|---|
@SolonTest(App.class) |
@SpringBootTest |
测试启动 |
@SolonTest(env="test") |
@ActiveProfiles("test") |
测试环境 |
HttpTester |
MockMvc |
HTTP 接口测试 |
@Rollback |
@Transactional + @Rollback |
事务回滚 |
@Import(profiles=...) |
@TestPropertySource |
导入测试属性 |
HttpTester 用法示例:
java
@SolonTest(App.class)
public class UserControllerTest extends HttpTester {
@Test
public void testGetUser() {
// GET 请求
String resp = path("/users/1").get();
assertEquals(200, resp.code());
// POST 请求
String json = "{\"name\":\"test\"}";
String resp2 = path("/users").body(json).post();
assertContains(resp2, "test");
}
}
七、其他常见对照
| 场景 | Spring Boot | Solon |
|---|---|---|
| 拦截器 | HandlerInterceptor |
@Around 注解或 Solon Filter |
| 定时任务 | @Scheduled |
@Scheduled(同名)+ @EnableScheduling |
| 文件上传 | MultipartFile |
UploadedFile(用法一致) |
| RPC 调用 | @FeignClient |
@NamiClient |
| 注册发现 | @EnableDiscoveryClient |
无需注解,引入插件自动生效 |
| 配置刷新 | @RefreshScope |
无需注解,配置变更自动感知 |
八、迁移检查清单
- POM:
spring-boot-starter-parent→solon-parent - POM:
spring-boot-starter-*→solon-*/*-solon-plugin - 配置:
application.yml→app.yml(环境文件同理) - 启动类:
@SpringBootApplication→@SolonMain - 启动:
SpringApplication.run()→Solon.start() - IoC:
@Autowired→@Inject - IoC:
@Service/@Repository→@Component - Web:
@RestController→@Controller - Web:
@RequestMapping→@Mapping - Web:
@PathVariable→@Path - Web:
HttpServletRequest→Context - 配置:
@Value→@Inject("${...}") - 数据:
spring.datasource.*→solon.dataSources.* - 数据:
@Transactional→@Transaction - 测试:
@SpringBootTest→@SolonTest - 测试:
MockMvc→HttpTester
九、写在最后
这篇对照表覆盖了日常开发中最常用的 90% 场景。Solon 的注解体系并非简单的"换皮",它在统一性(@Component / @Inject / @Condition)和简便性(@Db / 无需 @RefreshScope)上做了明显的设计取舍。
建议迁移前先通读一遍官方对比文档:solon.noear.org/article/compare-springboot
如有具体的迁移场景未覆盖,欢迎在评论区留言。