你是一个资深的java专家,请在开发中遵循如下规则: - 严格遵循 **SOLID、DRY、KISS、YAGNI** 原则 - 遵循 **OWASP 安全最佳实践**(如输入验证、SQL注入防护) - 采用 **分层架构设计**,确保职责分离 - 代码变更需通过 **单元测试覆盖**(测试覆盖率 ≥ 80%) --- ## 二、技术栈规范 ### 技术栈要求 - **框架**:JavaFx 22 + Spring Boot 3.x + Java 21 - **依赖**: - 核心:Spring Data JPA, Lombok - 数据库:MySQL Driver、MsSQL Driver - 其他:controlsfx --- ## 三、应用逻辑设计规范 ### 1. 分层架构原则 | 层级 | 职责 | 约束条件 | |----------------|------------------------|----------------------------------------------------------| | **Controller** | 处理 fxml 请求与响应,定义 API 接口 | - 禁止直接操作数据库
- 必须通过 Service 层调用 | | **Service** | 业务逻辑实现,事务管理,数据校验 | - 必须通过 Repository 访问数据库
- 返回 DTO 而非实体类(除非必要) | | **Repository** | 数据持久化操作,定义数据库查询逻辑 | - 必须继承 `MyRepository`
- 使用 `@EntityGraph` 避免 N+1 查询问题 | | **Entity** | 数据库表结构映射对象 | - 仅用于数据库交互
- 禁止直接返回给前端(需通过 DTO 转换) | | **Tasker** | 运行的任务 | - | | **ViewModel** | 界面数据模型 | - | | **.fxml** | UI 界面逻辑 | - 位于 /resources/ui/ | --- ## 四、核心代码规范 ### 1. 实体类(Entity)规范 ```java @Entity @Data // Lombok 注解 @Table(name = "USER") // 数据表名,默认为大写的类名 public class User { @Id @Column(name = "ID", nullable = false) // 字段名大写 @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "USERNAME") // 字段名大写 @Size(min = 3, max = 50) private String username; // 关联关系使用懒加载 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "DEPARTMENT_ID") // 关联关系,字段名大写 private Department department; } ``` ### 2. 数据访问层(Repository)规范 ```java public interface UserRepository extends MyRepository { // 命名查询 Optional findByUsername(String username); // 自定义 JPQL 查询 @Query("SELECT u FROM User u JOIN FETCH u.department WHERE u.id = :id") @EntityGraph(attributePaths = {"department"}) Optional findUserWithDepartment(@Param("id") Long id); } ``` ### 3. 服务层(Service)规范 ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Transactional public ApiResponse createUser(UserDTO dto) { // 业务逻辑实现 User user = User.builder().username(dto.getUsername()).build(); User savedUser = userRepository.save(user); return ApiResponse.success(UserDTO.fromEntity(savedUser)); } } ``` ### 4. 控制器(Controller)规范 ```java @Lazy @Scope("prototype") // 单例 @Component @FxmlPath("/ui/employee/employee.fxml") // FXML 文件路径 public class EmployeeWindowController extends AbstEntityController{ public BorderPane root; public TabPane tabPane; public Tab baseInfoTab; public Tab rolesTab; public Tab loginHistoryTab; public Tab authBindTab; @Autowired private EmployeeService employeeService; @Override public void onShown(WindowEvent windowEvent) { super.onShown(windowEvent); getTitle().bind(viewModel.getName().map(name -> "[" + viewModel.getId().get() + "] " + name + " 员工详情")); } @Override protected void registerTabSkins() { registerTabSkin(baseInfoTab, tab -> new EmployeeTabSkinBase(this)); registerTabSkin(rolesTab, tab -> new EmployeeTabSkinRole(this)); registerTabSkin(loginHistoryTab, tab -> new EmployeeTabSkinLoginHistory(this)); } @Override public EmployeeService getViewModelService() { return employeeService; } } ``` --- ## 五、Tab 界面控制 ```java public class EmployeeTabSkinBase extends AbstEmployeeBasedTabSkin implements TabSkin { public EmployeeTabSkinBase(EmployeeWindowController controller) { super(controller); } @Override public Tab getTab() { return controller.baseInfoTab; } @Override public void initializeTab() { } } @FxmlPath("/ui/employee/employee-login-history.fxml") public class EmployeeTabSkinLoginHistory extends AbstEmployeeTableTabSkin implements TabSkin { public TableColumn idColumn; public TableColumn ipColumn; public TableColumn macColumn; public TableColumn loginTimeColumn; public TableColumn activeTimeColumn; private EmployeeLoginHistoryService loginHistoryService; public EmployeeTabSkinLoginHistory(EmployeeWindowController controller) { super(controller); } EmployeeLoginHistoryService getLoginHistoryService() { if (loginHistoryService == null) { loginHistoryService = getBean(EmployeeLoginHistoryService.class); } return loginHistoryService; } @Override protected EmployeeLoginHistoryService getViewModelService() { return getLoginHistoryService(); } @Override public Tab getTab() { return controller.loginHistoryTab; } @Override public void initializeTab() { super.initializeTab(); idColumn.setCellValueFactory(param -> param.getValue().getId()); ipColumn.setCellValueFactory(param -> param.getValue().getIp()); macColumn.setCellValueFactory(param -> param.getValue().getMac()); loginTimeColumn.setCellValueFactory(param -> param.getValue().getLoginTime()); loginTimeColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); activeTimeColumn.setCellValueFactory(param -> param.getValue().getActiveTime()); activeTimeColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); Platform.runLater(() -> { getTableView().getSortOrder().add(activeTimeColumn); }); } } ``` --- ## 六、全局异常处理规范 ```java ``` ### 2. 全局异常处理器(GlobalExceptionHandler) ```java @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity> handleEntityNotFound(EntityNotFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND) .body(ApiResponse.error(ex.getMessage())); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity> handleValidationErrors(MethodArgumentNotValidException ex) { String errorMessage = ex.getBindingResult() .getFieldErrors() .stream() .map(error -> error.getField() + ": " + error.getDefaultMessage()) .collect(Collectors.joining(", ")); return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage)); } } ``` --- ## 七、安全与性能规范 1. 输入校验: 2. **事务管理**: - `@Transactional` 注解仅标注在 Service 方法上 - 避免在循环中频繁提交事务 3. **性能优化**: - 使用 `@EntityGraph` 预加载关联关系 - 避免在循环中执行数据库查询(批量操作优先) --- ## 八、代码风格规范 1. **命名规范**: - 类名:`UpperCamelCase`(如 `UserServiceImpl`) - 方法/变量名:`lowerCamelCase`(如 `saveUser`) - 常量:`UPPER_SNAKE_CASE`(如 `MAX_LOGIN_ATTEMPTS`) 2. **注释规范**: - 方法必须添加注释且方法级注释使用 Javadoc 格式 - 计划待完成的任务需要添加 `// TODO` 标记 - 存在潜在缺陷的逻辑需要添加 `// FIXME` 标记 3. **代码格式化**: - 使用 IntelliJ IDEA 默认的 Spring Boot 风格 - 禁止手动修改代码缩进(依赖 IDE 自动格式化) --- ## 九、部署规范 1. **部署规范**: - 生产环境需禁用 `@EnableAutoConfiguration` 的默认配置 - 敏感信息通过 `application.properties` 外部化配置 - 使用 `Spring Profiles` 管理环境差异(如 `dev`, `prod`) --- ## 十、扩展性设计规范 1. **接口优先**: - 服务层接口(`UserService`)与实现(`UserServiceImpl`)分离 2. **扩展点预留**: - 关键业务逻辑需提供 `Strategy` 或 `Template` 模式支持扩展 3. **日志规范**: - 使用 `SLF4J` 记录日志(禁止直接使用 `System.out.println`) - 核心操作需记录 `INFO` 级别日志,异常记录 `ERROR` 级别 ```