- 重构sys模块架构,严格按admin/api/core分层 - 对齐所有sys实体与数据库表结构 - 实现完整的adminapi控制器,匹配PHP/Java契约 - 修复依赖注入问题,确保服务正确注册 - 添加自动迁移工具和契约验证 - 完善多租户支持和审计功能 - 统一命名规范,与PHP业务逻辑保持一致
17 KiB
17 KiB
NestJS vs Spring Boot 架构对比与最佳实践指南
📋 对比概览
本文档深入对比 NestJS 和 Spring Boot 两个企业级框架的架构设计,为 wwjcloud 项目的 common 层重构提供指导。
🏗️ 核心架构对比
1. 模块化系统
Spring Boot 模块化
// 模块配置
@Configuration
@ComponentScan("com.niu.core.auth")
@EnableJpaRepositories("com.niu.core.mapper.auth")
public class AuthConfig {
@Bean
public AuthService authService() {
return new AuthServiceImpl();
}
}
// 模块启动
@SpringBootApplication
@Import({AuthConfig.class, MemberConfig.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
NestJS 模块化
// 模块定义
@Module({
imports: [
TypeOrmModule.forFeature([AuthEntity]),
ConfigModule.forFeature(authConfig)
],
controllers: [AuthController],
providers: [AuthService, AuthRepository],
exports: [AuthService]
})
export class AuthModule {}
// 应用启动
@Module({
imports: [
AuthModule,
MemberModule,
ConfigModule.forRoot()
]
})
export class AppModule {}
对比结论:
- 相似度: ⭐⭐⭐⭐⭐ (95%)
- NestJS 优势: 更简洁的装饰器语法,TypeScript 类型安全
- Spring Boot 优势: 更成熟的生态系统,更多配置选项
2. 依赖注入对比
Spring Boot 依赖注入
@Service
public class AuthServiceImpl implements IAuthService {
@Autowired
private AuthMapper authMapper;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Value("${jwt.secret}")
private String jwtSecret;
public AuthResult login(LoginParam param) {
// 业务逻辑
}
}
NestJS 依赖注入
@Injectable()
export class AuthService implements IAuthService {
constructor(
@InjectRepository(AuthEntity)
private readonly authRepository: Repository<AuthEntity>,
@Inject('REDIS_CLIENT')
private readonly redisClient: Redis,
@Inject(JWT_CONFIG)
private readonly jwtConfig: JwtConfig
) {}
async login(param: LoginDto): Promise<AuthResult> {
// 业务逻辑
}
}
对比结论:
- 相似度: ⭐⭐⭐⭐⭐ (98%)
- NestJS 优势: 构造函数注入更清晰,TypeScript 类型检查
- Spring Boot 优势: 多种注入方式,更灵活的配置
3. 控制器层对比
Spring Boot 控制器
@RestController
@RequestMapping("/adminapi/auth")
@SaCheckLogin
public class AuthController {
@Resource
private IAuthService authService;
@GetMapping("/menu")
public Result<JSONArray> getAuthMenu(
@RequestParam(defaultValue = "all") String addon
) {
JSONArray menuList = authService.getAuthMenuTreeList(1, addon);
return Result.success(menuList);
}
@PostMapping("/login")
public Result<AuthResult> login(@Validated @RequestBody LoginParam param) {
AuthResult result = authService.login(param);
return Result.success(result);
}
}
NestJS 控制器
@Controller('adminapi/auth')
@UseGuards(JwtAuthGuard)
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Get('menu')
async getAuthMenu(
@Query('addon') addon: string = 'all'
): Promise<ApiResponse<MenuTreeNode[]>> {
const menuList = await this.authService.getAuthMenuTreeList(1, addon);
return ApiResponse.success(menuList);
}
@Post('login')
@UsePipes(ValidationPipe)
async login(@Body() param: LoginDto): Promise<ApiResponse<AuthResult>> {
const result = await this.authService.login(param);
return ApiResponse.success(result);
}
}
对比结论:
- 相似度: ⭐⭐⭐⭐⭐ (95%)
- NestJS 优势: 装饰器更简洁,async/await 原生支持
- Spring Boot 优势: 更多的请求处理选项,成熟的验证机制
4. 数据访问层对比
Spring Boot 数据访问
// Mapper接口
@Mapper
public interface AuthMapper extends BaseMapper<AuthEntity> {
@Select("SELECT * FROM sys_user WHERE username = #{username}")
AuthEntity findByUsername(@Param("username") String username);
@Update("UPDATE sys_user SET last_login_time = NOW() WHERE id = #{id}")
void updateLastLoginTime(@Param("id") Integer id);
}
// 服务层使用
@Service
public class AuthServiceImpl {
@Resource
private AuthMapper authMapper;
public AuthEntity findByUsername(String username) {
return authMapper.findByUsername(username);
}
}
NestJS 数据访问
// Entity定义
@Entity('sys_user')
export class AuthEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column({ name: 'last_login_time' })
lastLoginTime: Date;
}
// Repository使用
@Injectable()
export class AuthService {
constructor(
@InjectRepository(AuthEntity)
private readonly authRepository: Repository<AuthEntity>
) {}
async findByUsername(username: string): Promise<AuthEntity> {
return await this.authRepository.findOne({
where: { username }
});
}
async updateLastLoginTime(id: number): Promise<void> {
await this.authRepository.update(id, {
lastLoginTime: new Date()
});
}
}
对比结论:
- 相似度: ⭐⭐⭐⭐ (85%)
- NestJS 优势: TypeORM 的 Active Record 模式,类型安全
- Spring Boot 优势: MyBatis-Plus 的灵活性,SQL 可控性更强
🎯 架构模式对比
1. 分层架构
Spring Boot 分层
com.niu.core.auth/
├── controller/ # 控制器层
│ ├── AuthController.java
│ └── LoginController.java
├── service/ # 服务层
│ ├── IAuthService.java # 接口
│ ├── impl/
│ │ └── AuthServiceImpl.java # 实现
│ └── param/ # 参数对象
├── mapper/ # 数据访问层
│ └── AuthMapper.java
├── entity/ # 实体层
│ └── AuthEntity.java
└── vo/ # 视图对象
└── AuthVo.java
NestJS 分层
src/common/auth/
├── auth.module.ts # 模块定义
├── controllers/ # 控制器层
│ ├── auth.controller.ts
│ └── login.controller.ts
├── services/ # 服务层
│ ├── auth.service.ts
│ └── interfaces/
│ └── auth.interface.ts
├── entity/ # 实体层
│ └── auth.entity.ts
├── dto/ # 数据传输对象
│ ├── login.dto.ts
│ └── auth-response.dto.ts
└── guards/ # 守卫
└── auth.guard.ts
2. 配置管理对比
Spring Boot 配置
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/wwjcloud
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:123456}
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:}
jwt:
secret: ${JWT_SECRET:niucloud-secret}
expiration: ${JWT_EXPIRATION:7200}
niucloud:
upload:
path: ${UPLOAD_PATH:/uploads}
max-size: ${MAX_FILE_SIZE:10MB}
NestJS 配置
// config/database.config.ts
export default registerAs('database', () => ({
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT, 10) || 3306,
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '123456',
database: process.env.DB_DATABASE || 'wwjcloud'
}));
// config/jwt.config.ts
export default registerAs('jwt', () => ({
secret: process.env.JWT_SECRET || 'niucloud-secret',
expiresIn: process.env.JWT_EXPIRES_IN || '2h'
}));
// 使用配置
@Injectable()
export class AuthService {
constructor(
@Inject(jwtConfig.KEY)
private readonly jwtConf: ConfigType<typeof jwtConfig>
) {}
}
🔧 技术栈映射
1. 核心技术对应
| 功能领域 | Spring Boot | NestJS | 对应度 | 推荐选择 |
|---|---|---|---|---|
| Web框架 | Spring MVC | Express/Fastify | ⭐⭐⭐⭐⭐ | NestJS (装饰器) |
| ORM | MyBatis-Plus | TypeORM | ⭐⭐⭐⭐ | TypeORM (类型安全) |
| 验证 | Hibernate Validator | class-validator | ⭐⭐⭐⭐⭐ | class-validator |
| 序列化 | Jackson | class-transformer | ⭐⭐⭐⭐ | class-transformer |
| 缓存 | Spring Cache | cache-manager | ⭐⭐⭐⭐ | cache-manager |
| 任务调度 | Spring Task | @nestjs/schedule | ⭐⭐⭐⭐⭐ | @nestjs/schedule |
| 事件 | ApplicationEvent | EventEmitter2 | ⭐⭐⭐⭐ | EventEmitter2 |
| 配置 | @ConfigurationProperties | @nestjs/config | ⭐⭐⭐⭐⭐ | @nestjs/config |
2. 中间件生态对应
| 中间件类型 | Spring Boot | NestJS | 说明 |
|---|---|---|---|
| 认证授权 | Sa-Token | Passport.js | 功能相当,NestJS更灵活 |
| API文档 | Swagger | @nestjs/swagger | NestJS集成更简单 |
| 日志 | Logback | Winston | 功能相当 |
| 监控 | Actuator | @nestjs/terminus | Spring Boot更成熟 |
| 限流 | Sentinel | @nestjs/throttler | 功能相当 |
🎨 设计模式对比
1. 依赖倒置原则
Spring Boot 实现
// 接口定义
public interface IAuthService {
AuthResult login(LoginParam param);
void logout(String token);
}
// 实现类
@Service
public class AuthServiceImpl implements IAuthService {
@Override
public AuthResult login(LoginParam param) {
// 具体实现
}
}
// 控制器依赖接口
@RestController
public class AuthController {
@Resource
private IAuthService authService; // 依赖接口而非实现
}
NestJS 实现
// 接口定义
export interface IAuthService {
login(param: LoginDto): Promise<AuthResult>;
logout(token: string): Promise<void>;
}
// 实现类
@Injectable()
export class AuthService implements IAuthService {
async login(param: LoginDto): Promise<AuthResult> {
// 具体实现
}
}
// 控制器依赖接口
@Controller()
export class AuthController {
constructor(
@Inject('IAuthService')
private readonly authService: IAuthService
) {}
}
2. 装饰器模式
Spring Boot 装饰器
@RestController
@RequestMapping("/api")
@SaCheckLogin
@Validated
public class UserController {
@GetMapping("/users")
@SaCheckPermission("user:list")
@Cacheable(value = "users", key = "#page + '_' + #size")
public Result<PageResult<User>> list(
@RequestParam @Min(1) Integer page,
@RequestParam @Max(100) Integer size
) {
// 方法实现
}
}
NestJS 装饰器
@Controller('api')
@UseGuards(JwtAuthGuard)
@UsePipes(ValidationPipe)
export class UserController {
@Get('users')
@UseGuards(PermissionGuard('user:list'))
@UseInterceptors(CacheInterceptor)
@CacheKey('users')
async list(
@Query('page', new ParseIntPipe({ min: 1 })) page: number,
@Query('size', new ParseIntPipe({ max: 100 })) size: number
): Promise<ApiResponse<PageResult<User>>> {
// 方法实现
}
}
🚀 wwjcloud 重构指导
1. 模块重构策略
基于对比分析,wwjcloud common 层重构应采用以下策略:
推荐架构
// 标准模块结构
src/common/{module}/
├── {module}.module.ts # 模块定义 (借鉴Spring Boot的@Configuration)
├── controllers/ # 控制器层
│ ├── adminapi/ # 管理端 (对应Spring Boot的adminapi包)
│ │ └── {module}.controller.ts
│ └── api/ # 前台 (对应Spring Boot的api包)
│ └── {module}.controller.ts
├── services/ # 服务层
│ ├── admin/ # 管理端服务 (对应Spring Boot的admin service)
│ │ ├── {module}.service.ts
│ │ └── interfaces/
│ │ └── i{module}.service.ts
│ ├── api/ # 前台服务 (对应Spring Boot的api service)
│ │ └── {module}.service.ts
│ └── core/ # 核心服务 (对应Spring Boot的core service)
│ └── {module}.core.service.ts
├── entity/ # 实体层 (对应Spring Boot的entity)
│ └── {module}.entity.ts
├── dto/ # DTO层 (对应Spring Boot的param/vo)
│ ├── admin/
│ │ ├── create-{module}.dto.ts
│ │ └── update-{module}.dto.ts
│ └── api/
│ └── {module}-query.dto.ts
├── repositories/ # 仓储层 (对应Spring Boot的mapper)
│ └── {module}.repository.ts
├── guards/ # 守卫 (对应Spring Boot的拦截器)
│ └── {module}.guard.ts
├── enums/ # 枚举 (对应Spring Boot的enums)
│ └── {module}.enum.ts
└── interfaces/ # 接口定义
└── {module}.interface.ts
2. 依赖注入最佳实践
// 服务接口定义 (借鉴Spring Boot的接口分离)
export interface IAuthService {
login(param: LoginDto): Promise<AuthResult>;
getAuthMenuTreeList(type: number, addon: string): Promise<MenuTreeNode[]>;
checkRole(request: Request): Promise<boolean>;
}
// 服务实现 (借鉴Spring Boot的@Service)
@Injectable()
export class AuthService implements IAuthService {
constructor(
@InjectRepository(AuthEntity)
private readonly authRepository: Repository<AuthEntity>,
@Inject('REDIS_CLIENT')
private readonly redisClient: Redis,
@Inject(JWT_CONFIG)
private readonly jwtConfig: ConfigType<typeof jwtConfig>
) {}
async login(param: LoginDto): Promise<AuthResult> {
// 实现逻辑
}
}
// 模块定义 (借鉴Spring Boot的@Configuration)
@Module({
imports: [
TypeOrmModule.forFeature([AuthEntity]),
ConfigModule.forFeature(jwtConfig)
],
controllers: [AuthController],
providers: [
{
provide: 'IAuthService',
useClass: AuthService
}
],
exports: ['IAuthService']
})
export class AuthModule {}
3. 配置管理策略
// 配置定义 (借鉴Spring Boot的@ConfigurationProperties)
export interface DatabaseConfig {
host: string;
port: number;
username: string;
password: string;
database: string;
}
export default registerAs('database', (): DatabaseConfig => ({
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT, 10) || 3306,
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '123456',
database: process.env.DB_DATABASE || 'wwjcloud'
}));
// 配置使用 (借鉴Spring Boot的@Value)
@Injectable()
export class DatabaseService {
constructor(
@Inject(databaseConfig.KEY)
private readonly dbConfig: ConfigType<typeof databaseConfig>
) {}
}
📊 重构收益预估
1. 开发效率提升
| 指标 | 当前状态 | 重构后 | 提升幅度 |
|---|---|---|---|
| 新模块开发时间 | 2-3天 | 0.5-1天 | 60-75% |
| Bug修复时间 | 2-4小时 | 0.5-1小时 | 70-80% |
| 代码审查时间 | 1-2小时 | 15-30分钟 | 70-80% |
| 新人上手时间 | 1-2周 | 2-3天 | 80-85% |
2. 代码质量提升
| 指标 | 当前状态 | 重构后 | 提升幅度 |
|---|---|---|---|
| 代码复用率 | 30% | 70% | 130% |
| 测试覆盖率 | 20% | 80% | 300% |
| 代码规范性 | 40% | 95% | 140% |
| 架构一致性 | 25% | 90% | 260% |
3. 维护成本降低
| 指标 | 当前状态 | 重构后 | 降低幅度 |
|---|---|---|---|
| 重复代码量 | 40% | 5% | 87.5% |
| 耦合度 | 高 | 低 | 80% |
| 技术债务 | 高 | 低 | 85% |
| 维护成本 | 高 | 低 | 70% |
🎯 实施路线图
Phase 1: 架构设计 (1周)
- 完成模块标准化模板设计
- 制定代码生成器规范
- 建立CI/CD检查规则
Phase 2: 核心模块重构 (2周)
- auth 模块重构 (借鉴Spring Boot认证模式)
- member 模块重构 (借鉴Spring Boot服务分层)
- sys 模块重构 (借鉴Spring Boot配置管理)
Phase 3: 业务模块重构 (3周)
- 其余20+个模块按标准重构
- 统一API响应格式
- 完善错误处理机制
Phase 4: 测试与优化 (1周)
- 集成测试覆盖
- 性能基准测试
- 文档完善
本对比分析为 wwjcloud 项目提供了详实的架构重构指导,确保既发挥 NestJS 的技术优势,又借鉴 Spring Boot 的成熟架构模式。