Core library for Spring Moon framework
一个轻量级的 Node.js 框架,灵感来自 Spring Framework,支持分层架构和依赖注入。
- 🚀 TypeScript 支持
- 💉 依赖注入容器(构造器注入)
- 🏗️ 分层架构装饰器(@Controller、@Service、@Mapper)
- 🔄 模块系统和组件扫描
- 🌐 请求上下文管理
- 📦 事务管理
- 🔒 HTTP 过滤器和处理器拦截器
- ⚙️ 配置文件支持(application.yml,类似 Spring Boot)
类似 Spring Boot 的装饰器系统:
| 装饰器 | 用途 | 作用域 |
| ---------------- | ---------- | --------- |
| @Controller | 控制器层 | Request |
| @Service | 业务逻辑层 | Singleton |
| @Mapper | 数据访问层 | Singleton |
| @Component | 通用组件 | Singleton |
| @Configuration | 配置类 | Singleton |
| @Filter | HTTP 过滤器 | Singleton |
| @Interceptor | 处理器拦截器 | Singleton |
``bash`
npm install spring-moon或
pnpm add spring-moon或
yarn add spring-moon
`typescript
import { Controller, Service, Mapper, Module } from 'spring-moon'
// 数据访问层
@Mapper()
class UserMapper {
private users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]
findAll() {
return this.users
}
findById(id: number) {
return this.users.find(user => user.id === id)
}
}
// 业务逻辑层
@Service()
class UserService {
constructor(private userMapper: UserMapper) {}
getAllUsers() {
return this.userMapper.findAll()
}
getUserById(id: number) {
const user = this.userMapper.findById(id)
if (!user) {
throw new Error(User with id ${id} not found)
}
return user
}
}
// 控制器层
@Controller()
class UserController {
constructor(private userService: UserService) {}
@GetMapping('/api/users')
async handleGetAllUsers() {
return this.userService.getAllUsers()
}
@GetMapping('/api/users/:id')
async handleGetUser(@PathVariable('id') id: number) {
return this.userService.getUserById(id)
}
}
// 创建应用模块
const appModule = Module.create({
components: [
UserMapper, // @Mapper
UserService, // @Service
UserController, // @Controller
],
})
// 启动应用
async function bootstrap() {
const context = appModule.getContext()
const requestContext = context.startRequest()
try {
const userController = appModule.resolve
const allUsers = await userController.handleGetAllUsers()
console.log('All users:', allUsers)
const user = await userController.handleGetUser(1)
console.log('User 1:', user)
console.log(Controllers: ${appModule.getControllers().length})Services: ${appModule.getServices().length}
console.log()Mappers: ${appModule.getRepositories().length}
console.log()
} finally {
context.endRequest()
}
}
bootstrap().catch(console.error)
`
Spring Moon 使用构造器注入来管理依赖关系:
`typescriptSending email to ${to}: ${subject}
@Service()
class EmailService {
sendEmail(to: string, subject: string, body: string) {
console.log()
}
}
@Service()
class UserService {
constructor(
private userMapper: UserMapper,
private emailService: EmailService // 自动注入
) {}
async createUser(userData: any) {
const user = this.userMapper.create(userData)
await this.emailService.sendEmail(user.email, 'Welcome!', 'Welcome to our platform!')
return user
}
}
`
- Singleton: 单例模式(默认),整个应用生命周期内只创建一个实例
- Request: 请求作用域,每个请求创建新实例
`typescript
@Controller() // Request 作用域
class ApiController {}
@Service() // Singleton 作用域
class BusinessService {}
`
Spring Moon 支持类似 Spring Boot 的 YAML 配置文件,遵循"约定大于配置"的原则:
#### 配置文件位置
YAML 仅从项目根下 resources/(与 src 同级)读取,不兼容 src/config 等其它路径:resources/application.yml
- resources/application-dev.yml
- resources/application-prod.yml
-
#### 多环境配置
支持多环境配置,通过 SPRING_PROFILES_ACTIVE 环境变量切换:
`bash开发环境
SPRING_PROFILES_ACTIVE=dev pnpm run dev
#### 配置文件示例
resources/application.yml(与 src 同级):`yaml
server:
port: 3000
host: localhostspring:
moon:
application:
name: my-app
scanBasePackages: [] # 可选,默认扫描 src 目录
database:
url: postgresql://user:password@localhost:5432/dbname
`resources/application-dev.yml:`yaml
server:
port: 3000
host: localhostspring:
moon:
application:
name: my-app-dev
`resources/application-prod.yml:`yaml
server:
port: 8080
host: 0.0.0.0spring:
moon:
application:
name: my-app-prod
`#### 配置优先级
配置优先级(从高到低):
1. 环境变量(
SPRING_MOON_SERVER_PORT, DATABASE_URL 等)
2. application-{profile}.yml(环境特定配置)
3. application.yml(基础配置)
4. 默认配置(约定)#### 读取配置
在代码中读取配置:
`typescript
import { environment, getConfigValue } from 'spring-moon'// 方式 1: 使用 Environment API
const port = environment.getNumber('server.port', 3000)
const dbUrl = environment.getString('database.url')
// 方式 2: 使用 getConfigValue
const appName = getConfigValue('spring.moon.application.name')
`#### 环境变量支持
支持以下环境变量:
-
SPRING_PROFILES_ACTIVE - 激活的环境(dev/prod)
- SPRING_MOON_SERVER_PORT - 服务器端口
- SPRING_MOON_SERVER_HOST - 服务器主机
- DATABASE_URL - 数据库连接 URL
- SPRING_MOON_DATABASE_URL - 数据库连接 URL(别名)
- SPRING_MOON_APPLICATION_NAME - 应用名称$3
使用模块来组织和管理组件:
`typescript
const userModule = Module.create({
components: [UserMapper, UserService, UserController],
})const emailModule = Module.create({
components: [EmailService, EmailController],
})
const appModule = Module.create({
imports: [userModule, emailModule],
components: [AppController],
})
`$3
管理请求级别的数据和状态:
`typescript
const context = appModule.getContext()// 开始请求
const requestContext = context.startRequest('req-123')
// 存储请求数据
context.setRequestData('userId', 123)
context.setRequestData('permissions', ['read', 'write'])
// 获取请求数据
const userId = context.getRequestData('userId')
// 结束请求(清理资源)
context.endRequest()
`$3
简单的事务管理支持:
`typescript
import { TransactionManager } from 'spring-moon'const txManager = new TransactionManager()
async function transferMoney(fromId: number, toId: number, amount: number) {
const tx = await txManager.begin()
try {
// 添加操作到事务
txManager.addOperation(tx.id, {
type: 'debit',
data: { accountId: fromId, amount },
rollback: async () => {
// 回滚逻辑
await creditAccount(fromId, amount)
},
})
txManager.addOperation(tx.id, {
type: 'credit',
data: { accountId: toId, amount },
rollback: async () => {
await debitAccount(toId, amount)
},
})
// 提交事务
await txManager.commit(tx.id)
} catch (error) {
// 回滚事务
await txManager.rollback(tx.id)
throw error
}
}
`$3
HTTP 过滤器作用于最外层 HTTP 请求链路,围绕整个
handleRequest 执行。适用于日志记录、CORS 处理、全局鉴权、统一 header 处理等场景。`typescript
import { Filter, HttpFilter, Request, Response } from 'spring-moon'@Filter({ order: 0, patterns: ['/api/**'] })
class LoggingFilter implements HttpFilter {
order = 0
patterns = ['/api/**']
async doFilter(req: Request, res: Response, next: () => Promise): Promise {
const startTime = Date.now()
const method = req.method ?? 'GET'
const url = req.url ?? '/'
console.log(
📥 ${method} ${url} - Start) await next()
const duration = Date.now() - startTime
console.log(
📤 ${method} ${url} - End (${duration}ms))
}
}@Filter({ order: 1, patterns: ['/api/**'], methods: ['POST', 'PUT', 'PATCH'] })
class BodySizeLimitFilter implements HttpFilter {
order = 1
patterns = ['/api/**']
methods = ['POST', 'PUT', 'PATCH']
async doFilter(req: Request, res: Response, next: () => Promise): Promise {
const contentLength = parseInt(req.headers['content-length'] || '0', 10)
const maxSize = 10 1024 1024 // 10MB
if (contentLength > maxSize) {
res.status(413).json({ error: 'Payload Too Large' })
return
}
await next()
}
}
`过滤器选项说明:
-
order: 执行顺序,数值越小越先执行(默认:0)
- patterns: 路径匹配模式
- 精确匹配:'/api/users'
- 前缀匹配:'/api/**'(匹配所有以 /api/ 开头的路径)
- methods: HTTP 方法限定(大写),如 ['GET', 'POST']。不指定则匹配所有方法$3
处理器拦截器作用于"路由匹配 + 控制器方法调用"阶段,可以拦截控制器方法的执行,适用于权限验证、返回值包装、异常处理等场景。
`typescript
import { Interceptor, HandlerInterceptor, HandlerContext, Request, Response } from 'spring-moon'@Interceptor({ order: 0, patterns: ['/admin/**'], methods: ['GET', 'POST'] })
class AuthInterceptor implements HandlerInterceptor {
order = 0
patterns = ['/admin/**']
methods = ['GET', 'POST']
async preHandle(req: Request, res: Response, handlerCtx: HandlerContext): Promise {
const token = req.headers['x-auth-token'] as string
if (!token || token !== 'secret-token') {
res.status(403).json({ error: 'Forbidden', message: 'Invalid authentication token' })
return false // 返回 false 中断后续处理
}
// 可以在这里设置请求上下文数据
console.log(
✅ Authenticated request to ${handlerCtx.controllerName}.${handlerCtx.methodName})
return true // 返回 true 或 void 继续处理
} postHandle(req: Request, res: Response, handlerCtx: HandlerContext, result: any): any {
// 包装返回值
return {
success: true,
data: result,
timestamp: new Date().toISOString(),
}
}
async afterCompletion(req: Request, res: Response, handlerCtx: HandlerContext, error?: Error): Promise {
if (error) {
console.error(
❌ Error in ${handlerCtx.controllerName}.${handlerCtx.methodName}:, error.message)
} else {
console.log(✅ Completed ${handlerCtx.controllerName}.${handlerCtx.methodName})
}
}
}@Interceptor({ patterns: ['/api/**'] })
class ResponseTimeInterceptor implements HandlerInterceptor {
patterns = ['/api/**']
async preHandle(req: Request, res: Response, handlerCtx: HandlerContext): Promise {
// 在请求对象上存储开始时间
;(req as any).startTime = Date.now()
}
postHandle(req: Request, res: Response, handlerCtx: HandlerContext, result: any): any {
const duration = Date.now() - ((req as any).startTime || Date.now())
// 在响应头中添加处理时间
res.setHeader('X-Response-Time',
${duration}ms)
return result
}
}
`拦截器方法说明:
-
preHandle: 在控制器方法调用之前执行
- 返回 false 表示中断后续处理(不调用 controller)
- 返回 true 或 void 继续处理
- postHandle: 在控制器方法调用之后、响应写入之前执行
- 可以修改返回值:返回新值将覆盖原返回值
- 返回 undefined 则保留原值
- afterCompletion: 在整个请求完成后执行(无论成功或异常)
- 按拦截器顺序的逆序执行
- 适合做清理工作、日志记录等执行顺序:
`
HTTP Request
↓
Filter Chain (按 order 顺序执行)
↓
Route Matching
↓
Interceptor.preHandle (按 order 顺序执行)
↓
Controller Method
↓
Interceptor.postHandle (按 order 顺序执行)
↓
Write Response
↓
Interceptor.afterCompletion (按 order 逆序执行)
↓
HTTP Response
`🛠️ CLI 工具
使用
spring-moon-cli 快速创建项目:`bash
安装 CLI
npm install -g spring-moon-cli创建新项目
spring-moon create my-app进入项目目录
cd my-app安装依赖
npm install构建项目
npm run build运行项目
npm start
`📖 API 文档
$3
-
@Component(name?) - 通用组件
- @Controller(path?) - 控制器
- @Service(name?) - 服务
- @Mapper(name?) - 数据访问层映射器(推荐)
- @Repository(name?) - 数据访问层(已废弃,请使用 @Mapper)
- @Configuration(name?) - 配置类
- @Filter(options?) - HTTP 过滤器
- @Interceptor(options?) - 处理器拦截器
- @Injectable(token?) - 可注入组件
- @Inject(token) - 依赖注入
- @Autowired - 自动装配$3
-
Container - 依赖注入容器
- Module - 模块管理
- ApplicationContext - 应用上下文
- TransactionManager` - 事务管理器欢迎贡献代码!请查看 贡献指南。
MIT License - 查看 LICENSE 文件了解详情。
- Gitee 仓库
- 问题反馈
- 更新日志
- Spring Boot 文档 (灵感来源)