Web 开发
Web 开发基础模块:跨域(CORS)、全局异常与统一响应封装、Query 参数转换器与 Tomcat 服务器增强的自动配置。
continew-starter-web 是 ContiNew Starter 提供的 Web 开发基础模块,为 Spring Boot Web 应用提供常用能力的自动配置与最佳实践,主要包含以下内容。
- 跨域支持:通过配置快速启用和定制跨域过滤器
CorsFilter; - 统一响应处理:内置响应数据封装、全局异常处理、异常别名与国际化,无第三方响应组件依赖;
- Query 参数转换器:
Date、LocalDate、LocalTime、LocalDateTime、BaseEnum类型参数自动转换; - 服务器增强:基于 Tomcat 服务器,支持全局禁用不安全的 HTTP 请求方法。
链路追踪(Trace)是独立模块 continew-starter-trace,不在本模块中,详见 Trace 链路追踪。
引入依赖
<dependency>
<groupId>top.continew.starter</groupId>
<artifactId>continew-starter-web</artifactId>
</dependency>跨域配置
前后端分离开发时,跨域是避不开的配置。模块提供了跨域过滤器自动配置(CorsAutoConfiguration),配置项对应类为 top.continew.starter.web.autoconfigure.cors.CorsProperties,默认不启用。
continew-starter:
web:
cors:
# 是否启用跨域配置(默认:false)
enabled: true
# 允许跨域的域名(Ant 风格通配符模式,与 allowed-origins 互斥,配置后仅本项生效)
allowed-origin-patterns:
- https://*.example.com
# 允许跨域的域名(默认:*)
allowed-origins: '*'
# 允许跨域的请求方式(默认:*)
allowed-methods: '*'
# 允许跨域的请求头(默认:*)
allowed-headers: '*'
# 允许跨域的响应头
exposed-headers: '*'当需要携带 Cookie 等凭据信息时,CORS 规范不允许 allowed-origins 与 allow-credentials 同时为 *,此时推荐使用 allowed-origin-patterns(如 https://*.example.com)进行精确匹配。自动配置会在 allowed-origin-patterns 不含 *、或 allowed-origins 为具体域名时自动开启 allowCredentials;预检请求缓存时间(maxAge)固定为 1800 秒。
统一响应处理
统一响应处理由本模块内置实现,包含响应数据封装、全局异常处理、异常别名与国际化。3.0 起不再依赖 Graceful Response,默认响应类为 top.continew.starter.web.model.R,可通过 GlobalResponseFactory 替换。
启用统一响应处理
统一响应处理不参与自动配置扫描,必须通过 @EnableGlobalResponse 显式启用。
@EnableGlobalResponse
@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}全局配置
配置项对应类为 top.continew.starter.web.autoconfigure.response.GlobalResponseProperties。模块已内置一套默认值(见 continew-starter-web/src/main/resources/default-response.yml),常用配置如下。
continew-starter:
web:
response:
# 是否开启国际化(默认:false)
i18n: false
# 失败时的 HTTP 状态码(默认:200,建议业务状态码与通信状态码区分)
default-http-status-code-on-error: 200
# 成功响应码(默认:0)
default-success-code: 0
# 成功提示(默认:ok)
default-success-msg: ok
# 失败响应码(默认:1)
default-error-code: 1
# 失败提示(默认:error)
default-error-msg: error
# 参数校验失败响应码(默认取 default-error-code)
default-validate-error-code:
# 是否打印异常日志(默认:false)
print-exception-in-global-advice: false
# 是否将原生异常错误信息填充到响应信息中(默认:false)
origin-exception-using-detail-message: false
# 例外包路径(支持数字、* 和 ** 通配符匹配),该包路径下的 Controller 将被忽略处理
exclude-packages:
- io.swagger.**
- org.springdoc.**
- org.springframework.boot.actuate.*响应结构
响应类 top.continew.starter.web.model.R 的结构如下。
{
"code": "0",
"msg": "ok",
"success": true,
"timestamp": 1691453288000,
"data": {}
}success 由响应码与 default-success-code 比较得出,timestamp 取序列化时刻。控制器直接返回 R 时不会被二次包装。
自定义响应结构
响应对象的创建、识别与信息改写都通过 GlobalResponseFactory 完成。需要不同字段结构时,声明一个该接口的 Bean 即可,无需修改 Starter 代码。
@Bean
public GlobalResponseFactory globalResponseFactory() {
return new GlobalResponseFactory() {
@Override
public Object newSuccess(Object data) {
return new CustomResponse(200, data, null);
}
@Override
public Object newFailure(String code, String msg) {
return new CustomResponse(code, null, msg);
}
@Override
public boolean isResponse(Object body) {
return body instanceof CustomResponse;
}
@Override
public String getCode(Object body) {
return String.valueOf(((CustomResponse) body).getStatus());
}
@Override
public void setMessage(Object body, String message) {
((CustomResponse) body).setMessage(message);
}
};
}自定义响应用于包装控制器返回值时,应与控制器声明的返回类型是不同的类(例如自定义 CustomResponse),避免 JSON 序列化引擎按控制器的泛型声明做强制类型转换。
排除统一封装
文件下载等场景需要直接返回原始数据时,在接口方法、控制器类或返回类型上添加 @ExcludeFromGlobalResponse 注解即可排除统一封装。
@ExcludeFromGlobalResponse
@GetMapping("/download")
public void download(HttpServletResponse response) {
// 直接输出文件流
}也可以通过 exclude-packages、exclude-urls、exclude-return-types 按包路径、请求 URL 或返回类型批量排除。返回 ResponseEntity、文件流等非 JSON 响应同样不会被包装。
异常别名
需要把第三方异常映射为固定响应码时,可使用配置方式:
continew-starter:
web:
response:
exception-alias-config-map:
"[java.lang.IllegalStateException]":
code: 4001
msg: 状态异常
http-status-code: 418也可以在异常类上标注 @ExceptionAliasFor,并通过 ExceptionAliasRegister 注册:
@ExceptionAliasFor(aliasFor = IllegalStateAliasException.class, code = "4001", msg = "状态异常")
public class IllegalStateAliasException extends RuntimeException {
}@Bean
public ExceptionAliasRegister exceptionAliasRegister() {
return new ExceptionAliasRegister().doRegisterExceptionAlias(IllegalStateAliasException.class);
}aliasFor 指定该别名配置生效的异常类型(可列多个,注册后这些类型及其子类生效),需要把自定义异常自身也列进去。
业务方自定义的 @RestControllerAdvice 处理器优先于全局异常处理器,二者不会产生重复包装。注意 Starter 的全局异常处理器为 @Order(200)(约束校验处理器为 @Order(190)),业务方 advice 需声明小于对应值的 @Order 才会优先;未声明 @Order 时按 LOWEST_PRECEDENCE 处理,会被 Starter 的处理器抢先。
国际化
国际化沿用 Spring Boot 的标准方案,Starter 不自建 MessageSource,只读取应用已有的 MessageSource Bean。开启 i18n 后,仅当响应信息为空或等于默认成功/失败提示(如 ok、error)时,才按 code 查找并替换;参数校验的字段级提示与异常明细信息不会被覆盖,未匹配到消息时保留原信息。
spring:
messages:
# 消息文件基名,同时也是参数校验消息的基名
basename: i18n/messages
encoding: UTF-8
continew-starter:
web:
response:
i18n: true0=操作成功
1=服务器异常,请联系管理员语言环境由应用配置的 LocaleResolver 决定,默认使用 AcceptHeaderLocaleResolver(读取 Accept-Language)。参数校验消息、业务异常消息同样通过该 MessageSource 与 LocaleContextHolder 解析,不需要 Starter 额外适配。
Query 参数转换器
默认情况下,Spring MVC 无法直接转换 Query 中的日期类型参数,需要使用 @DateTimeFormat 注解。
模块内置了 Query 参数转换器(WebMvcAutoConfiguration#addFormatters),可自动转换以下类型。
java.util.Date(经 HutoolDateUtil.parse解析,支持多种常见日期格式)LocalDateTime(默认格式yyyy-MM-dd HH:mm:ss)LocalDate(默认格式yyyy-MM-dd)LocalTime(默认格式HH:mm:ss)BaseEnum(枚举参数自动按编码值匹配)
如果默认格式无法满足要求,仍可使用 @DateTimeFormat 注解指定格式。
Tomcat 服务器增强
模块使用 Spring Boot 默认的 Tomcat 服务器(依赖 spring-boot-starter-webmvc),并做了两项增强。
全局禁用不安全的 HTTP 方法
配置项对应类为 top.continew.starter.web.autoconfigure.server.ServerExtensionProperties(配置前缀为 server.extension,非 continew-starter 前缀)。
server:
extension:
# 是否启用(默认:true)
enabled: true
# 不允许的请求方式(默认禁用 CONNECT、TRACE、TRACK)
disallowed-methods:
- CONNECT
- TRACE
- TRACKTomcat 线程池默认配置
模块内置了 Tomcat 的部分默认配置(见 continew-starter-web/src/main/resources/default-server.yml),可按需在 application.yml 中覆盖。
server:
tomcat:
# HTTP POST 请求内容大小上限(-1 不限制)
max-http-form-post-size: -1
threads:
# 最大工作线程数
max: 256「全局禁用不安全的 HTTP 方法」由 Servlet 过滤器(DisallowedMethodsFilter)实现,不依赖具体容器,Tomcat、Jetty 等 Servlet 容器均生效。
核心依赖
| 依赖 | 描述 |
|---|---|
top.continew.starter:continew-starter-json-jackson | JSON 模块(Jackson) |
top.continew.starter:continew-starter-api-doc | API 文档模块 |
org.springframework.boot:spring-boot-starter-webmvc | Spring MVC Web 开发能力(内置 Tomcat 服务器) |