design.md 3.2 KB

Context

mjava 基座 (com.malk) 作为内部多业务脚手架,业务模块 (mjava-guangming / mjava-shunfeng 等) 靠继承基座获得标准能力。当前三块可观测性空白必须由基座一次性补齐,避免每个业务自建。

关键约束:Spring Boot 2.2.13.RELEASE + Java 1.8,不能引入仅支持 SB 2.7+ 或 Java 11+ 的库。

Goals / Non-Goals

Goals

  • 零破坏:业务模块不用改任何代码或配置(除非要自定义)
  • 默认安全:生产环境 Swagger 不开、actuator 只开 health/info
  • 一次接入:三件套在基座统一做,业务自动继承

Non-Goals

  • 不给每个 Controller 加 @Tag/@Operation 注解(让文档自动按 Spring 注解生成即可)
  • 不接外部 APM / Skywalking(超出脚手架范围)
  • 不做分布式 traceId(与上游服务协议对接是业务侧事情;基座只做进程内 MDC)
  • 不加自定义 HealthIndicator(除非后续有真实需求)

Decisions

D1:Swagger 选 springdoc,不用 springfox

  • 理由:springfox 3.0.0 对 Spring Boot 2.2 有已知的 ExpandedParameterBuilderPlugin NullPointer 告警,且社区已事实停维。springdoc-openapi 1.6.x 与 SB 2.2 完全兼容,是官方推荐替代。
  • 替代:继续用 springfox —— 拒绝,告警影响启动日志清洁度,未来升级 SB 还要重做。
  • 具体版本springdoc-openapi-ui:1.6.15(兼容 SB 2.2 的末版系列)

D2:TraceId 用 Servlet Filter + MDC,不用 Spring Interceptor

  • 理由:Filter 比 Interceptor 更早生效(在 Spring MVC 之前),静态资源、异常也能覆盖;MDC API 简单无依赖
  • 线程池透传AsyncTaskExecutor 通过 TaskDecorator 在提交前复制 MDC,避免 @Async 子任务丢 traceId

D3:健康检查默认只开 health/info

  • 理由:env/beans/configprops 泄漏敏感配置(数据库密码路径、appSecret 等),默认必须关闭
  • 后续:如需要 Prometheus 指标再单开 management.endpoints.web.exposure.include=health,info,prometheus + micrometer 依赖

D4:logback pattern 用 [%X{traceId:-}](默认空字符串)

  • 理由:非 HTTP 调用(定时任务、启动阶段)不走 filter,traceId 会不存在;用 {:-} 防止打印 null
  • 格式%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-}] %-5level - [%method,%line] - %msg%n

Risks / Trade-offs

  • [风险] springdoc 引入后 /v3/api-docs 默认开放 → 通过 springdoc.api-docs.enabled: ${swagger.enable:false} 绑定同一开关
  • [风险] actuator 路径撞上业务 /api/actuator/* → 极低概率;如真撞可加 management.endpoints.web.base-path: /mgmt
  • [风险] TaskDecorator 与已有 AsyncConfig 冲突 → 审读 mjava/core/AsyncConfig.java 现有配置后再追加,不删既有逻辑
  • [代价] 启动类路径增大 ~5 MB → 接受,对 jar 体积影响可忽略

Migration Plan

  1. 基座 pom 加依赖
  2. 写 3 个 Java 类 + 1 个 logback 修改 + 3 个 yml 行
  3. 本地启动 mjava-mcli 或 guangming 冒烟:访问 /api/actuator/health/api/swagger-ui.html、查看日志是否带 traceId
  4. 业务模块升级基座版本号后重启即生效,不需要额外改动