Skip to content

DDK Web Starter ​

Web 层的默认件:统一的 ApiResponse 异常处理、以 customizer 方式参与的 Jackson 默认行为、默认关闭且可配置的跨域,并聚合 Spring MVC 与 Bean Validation 依赖。

能做什么 ​

  • 全局异常处理 BaseExceptionHandler:把异常翻译成 ApiResponse,状态码与真实原因一致,响应里不泄漏原始异常信息。

    异常状态码code
    BusinessException400业务错误码,消息按参数填充
    ConcurrentUpdateException、AggregateBusyException、DuplicateRequestException409CONCURRENT_UPDATE、AGGREGATE_BUSY、DUPLICATE_REQUEST
    SystemException500系统错误码
    BindException(含 @Valid 请求体)400VALIDATION_ERROR,消息列出每个字段
    ConstraintViolationException400VALIDATION_ERROR
    TypeMismatchException(路径变量、查询参数转换失败)400VALIDATION_ERROR,如 id: must be Long
    HttpMessageNotReadableException(坏 JSON)400MALFORMED_REQUEST
    Spring MVC 自身的 ErrorResponse(405、415、404…)沿用原状态码状态名,如 METHOD_NOT_ALLOWED
    其他未预料的异常500SYSTEM_ERROR,只返回通用文案,完整堆栈写日志
  • Jackson 默认行为:基于 Jackson 3,以 JsonMapperBuilderCustomizer 参与构建,不替换 JsonMapper Bean,spring.jackson.* 照常生效。

    • 时间序列化为 ISO-8601 字符串(Jackson 3 已内置 Java 时间类型支持);
    • 忽略请求体里的未知字段,前端多传一个字段不会打挂后端;
    • Long / long 序列化为 JSON 字符串(可关闭)。雪花 ID 超出 JavaScript 能精确表示的 2^53,数字形式在浏览器里会被静默改成另一个值。
    diff
    - {"id": 2100517430039306240}      浏览器解析为 2100517430039306200
    + {"id": "2100517430039306240"}
  • 接口文档里的错误约定:应用引入 springdoc 后自动生效(可用 ddk.web.openapi=false 关闭)。全局异常处理器返回的是 ResponseEntity,springdoc 推断不出错误响应,生成的文档里每个接口只有 200。本 starter 补上:

    • 每个接口的 400、409、500 响应,响应体是 ApiErrorResponse(失败时的 ApiResponse);接口自己声明过的响应不覆盖;
    • components.schemas.ErrorCode:全部错误码的枚举,描述里附「错误码—消息」表。来源是 CommonError 加上应用包下所有实现了 ErrorCode 的枚举,第一次生成文档时扫描;
    • 成功响应不需要处理,springdoc 会按泛型把 ApiResponse<UserResponse> 展开成带具体 data 类型的 schema。
    xml
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>   <!-- 版本由 DDK 的 BOM 管理 -->
    </dependency>
  • 跨域:默认关闭;开启后按 ddk.web.cors.* 配置。同时设置 allow-credentials=true 与 allowed-origins=* 时启动失败——那等于让任意站点带着用户凭证调用接口。

  • 依赖聚合:spring-boot-starter-webmvc、spring-boot-starter-validation、ddk-core。不再强制带上 springdoc 与 Swagger UI,需要接口文档时自行引入。

引入方式 ​

xml
<dependency>
    <groupId>com.ddk</groupId>
    <artifactId>ddk-web-starter</artifactId>
    <version>${ddk.version}</version>
</dependency>

配置项 ​

配置项类型默认值说明
ddk.web.exception-handlerbooleantrue是否注册全局异常处理器
ddk.web.jacksonbooleantrue是否应用 DDK 的 Jackson 默认行为
ddk.web.write-long-as-stringbooleantrueLong / long 是否序列化为字符串,需 ddk.web.jackson 启用
ddk.web.openapibooleantrue引入 springdoc 时,是否为接口文档补上错误响应与错误码清单
ddk.web.cors.enabledbooleanfalse是否开启跨域
ddk.web.cors.path-patternString/**生效路径
ddk.web.cors.allowed-originsList空允许的来源,支持通配模式如 https://*.acme.com
ddk.web.cors.allowed-methodsListGET, POST, PUT, PATCH, DELETE, OPTIONS允许的方法
ddk.web.cors.allowed-headersList*允许的请求头
ddk.web.cors.exposed-headersList空浏览器可读取的响应头,例如 X-Trace-Id
ddk.web.cors.allow-credentialsbooleanfalse是否允许携带凭证
ddk.web.cors.max-ageDuration1h预检结果缓存时间
yaml
ddk:
  web:
    cors:
      enabled: true
      allowed-origins: [ "https://admin.acme.com" ]
      exposed-headers: [ "X-Trace-Id" ]

装配条件与降级行为 ​

  • 自动配置类:com.ddk.web.config.WebAutoConfiguration,@ConditionalOnWebApplication(SERVLET),排在 Boot 的 JacksonAutoConfiguration 与 WebMvcAutoConfiguration 之前。
  • baseExceptionHandler:@ConditionalOnMissingBean,应用自己声明同类型 Bean 即可替换。
  • ddkCorsConfigurer:按 Bean 名判定是否已存在,应用里其他 WebMvcConfigurer(拦截器、消息转换器)不会让它消失。
  • 本 starter 不携带任何日志配置文件,日志完全由应用自己决定。
  • 本 starter 不依赖外部组件,没有「组件不可用」的降级路径。

不适用的场景 / 已知问题 ​

  1. 不支持 WebFlux,响应式栈用不上本 starter。
  2. 开启 write-long-as-string 后,计数、时间戳等 64 位整数也以字符串返回。规则按类型统一处理,不区分字段含义;前端需要按字符串解析,或在不需要时关闭。
  3. 错误码是枚举名字符串(VALIDATION_ERROR、USER_NOT_FOUND),不是数字编码。
  4. 接口文档里的错误码是整个 API 一份清单,没有细到每个接口:哪个用例会抛哪个错误码只有领域层知道,而适配层不能引用领域类型。
  5. 校验失败的消息是拼接后的字符串,没有逐字段的结构化列表。

文章以 CC BY-NC-SA 4.0 授权 · 代码片段以 MIT 授权