Asone 开发者文档Asone 开发者文档
  • 项目架构
  • 技术栈
  • 目录结构
  • 本地启动
  • 新增功能
  • 开发规范
  • 数据库
  • 图表语法
  • 部署
  • 文档同步规则
  • 相关文档
  • 项目架构
  • 技术栈
  • 目录结构
  • 本地启动
  • 新增功能
  • 开发规范
  • 数据库
  • 图表语法
  • 部署
  • 文档同步规则
  • 相关文档
  • 开发规范
    • 后端规范
    • 前端规范
    • 提交与代码质量

后端规范

依赖注入与分层

  • 使用构造器注入(@AllArgsConstructor + private final),字段上不打 @Autowired;单构造器不需要 @Autowired 注解。
  • Controller 只做参数绑定、权限声明与调用编排;业务逻辑与事务边界在 service/;数据访问在 mapper/。
  • Controller 统一 @RequestMapping("/api/..."),返回业务对象,由 GlobalResponseBodyAdvice 包 Result;异常交给 GlobalExceptionHandler。
  • 分页统一 MyBatis-Plus Page / IPage,禁止手写 limit 拼 SQL。
  • 业务模块之间不互相依赖,跨域能力下沉 asone-server-system。

禁用 record

本项目不允许使用 Java record(顶层、嵌套、局部都不行),值对象统一用 Lombok 普通类:

图 1 · 值对象选型
record 场景改成的普通类
需要被 Jackson 反序列化的 DTO@Data @NoArgsConstructor @AllArgsConstructor
不可变值对象(无归一化逻辑)@Getter @ToString @EqualsAndHashCode @AllArgsConstructor + private final 字段
不可变值对象(构造时校验 / 归一化)同上,但手写全参构造器完成归一化,不用 @AllArgsConstructor
只读的内部结果载体@Getter @AllArgsConstructor + private final 字段
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor
public class ApprovalOutcome {

    /** 业务动作是否执行成功 */
    private final boolean approved;

    /** 未成功时的原因 */
    private final String reason;

    public static ApprovalOutcome succeeded() {
        return new ApprovalOutcome(true, null);
    }
}

配套注意:

  • record 头部的 @param 注释要拆成字段级 Javadoc,@param 放在类上编译器不认。
  • boolean 字段经 Lombok 生成的 getter 是 isXxx() 而非 getXxx(),改调用点时注意。
  • 派生方法保留业务命名,不硬套 get 前缀,例如 approverIds()、usable()。
  • 自查(命中即不合规):
grep -rnE '(^|\s)record\s+[A-Za-z_]' --include='*.java' asone-server/*/src

禁止过期 API

过期写法应写
javax.servlet.*、javax.validation.*、javax.persistence.*jakarta.* 同名包
WebSecurityConfigurerAdapter、authorizeRequests()、antMatchers()SecurityFilterChain Bean + authorizeHttpRequests() + requestMatchers()
新的出站调用用 RestTemplateRestClient(同步)/ WebClient(异步、流式)
springfox 与 @Api、@ApiOperationspringdoc-openapi 与 @Tag、@Operation
MyBatis-Plus PaginationInterceptor、SqlInjectorMybatisPlusInterceptor + PaginationInnerInterceptor
java.util.Date、Calendar、SimpleDateFormatjava.time(LocalDateTime、DateTimeFormatter)
字段或 setter 上 @Autowired构造器注入
finalize()、Thread.stop/suspend/resume()AutoCloseable + try-with-resources、interrupt()

编译期自查:

cd asone-server && mvn -q -DskipTests -Dmaven.compiler.showDeprecation=true compile
cd asone-server && mvn versions:display-dependency-updates

上游确实未提供替代 API 时(如 xxl-job-core 个别兼容接口),只在调用处保留并加一行「上游未提供替代写法」说明,不扩散到新代码。

接口与安全约定

  • 读接口 hasAuthority('xxx:read'),写接口 xxx:manage 并叠加 @authenticationType.isSession(authentication)。
  • 写操作必须 @OperationLog,summaryTemplate 用 SpEL 生成可读描述。
  • 开放给 API Key 的接口显式加 @ApiKeyAllowed,免鉴权路径改 security.permit-all-paths 配置,不用注解绕过。
  • 接口文案国际化:新文案进 messages*.properties,后端优先读 X-Locale。

数据库操作约束

排查问题、验证数据、探索库表结构时对数据库只允许只读查询。任何增、改、删、结构变更默认禁止,只有用户在当前对话中明确授权并确认后才可执行。

  • 允许:SELECT、SHOW、DESC、information_schema、只读 EXPLAIN、SET SESSION TRANSACTION READ ONLY。
  • 禁止:DML、DDL、GRANT/REVOKE/FLUSH/KILL、CALL 不确定是否只读的例程、通过事务「先写后回滚」试探行为、清理测试脏数据或「顺手改一下」。
  • 迁移 / 初始化 / 数据修复脚本可以写进文件供人工评审,但不由开发者或调试链路自动执行。
  • 表结构唯一来源是全量 DDL,见数据库。
  • 发现现有代码或测试在调试链路里隐式写库,主动报告,不掩盖。

其他约束

  • 注释只描述当前功能与作用,就地改写受影响注释;不写「新增 / 修改 / 优化后 / 2026-xx-xx」这类流水账,版本演进交给 git log。
  • 注释与代码不一致且无法判断原意时,按当前实现重写。
  • 上线顺序注意:DDL 必须先于依赖它列的后端版本上线,否则查询因缺列失败。
下一页
前端规范