wbase-web
大约 6 分钟
wbase-web
Web 框架模块 - 提供全局异常处理、API 日志、数据脱敏、XSS 防护、Swagger 文档等能力
📦 Maven 依赖
<dependency>
<groupId>com.wzhcode.wbase</groupId>
<artifactId>wbase-web</artifactId>
<version>1.0.0</version>
</dependency>📁 目录结构
wbase-web/src/main/java/com/wzhcode/wbase/
│
├── 📂 apilog/ # API 访问日志
├── 📂 desensitize/ # 数据脱敏
├── 📂 jackson/ # Jackson 序列化配置
├── 📂 swagger/ # Swagger/OpenAPI 文档
├── 📂 web/ # Web 核心功能
└── 📂 xss/ # XSS 防护📑 目录
⚠️ 全局异常处理
位置:
com.wzhcode.wbase.web.core.handler.GlobalExceptionHandler
统一处理各类异常并返回 CommonResult:
| 异常类型 | 说明 | 错误码 |
|---|---|---|
MissingServletRequestParameterException | 📋 请求参数缺失 | 400 |
MethodArgumentTypeMismatchException | 🔄 参数类型错误 | 400 |
MethodArgumentNotValidException | ❌ 参数校验失败 | 400 |
BindException | 🔗 参数绑定异常 | 400 |
ConstraintViolationException | ✅ Validator 校验异常 | 400 |
HttpMessageNotReadableException | 📄 JSON 解析失败 | 400 |
NoHandlerFoundException | 🔍 请求地址不存在 | 404 |
HttpRequestMethodNotSupportedException | 🚫 请求方法不支持 | 405 |
AccessDeniedException | 🔐 权限不足 | 403 |
ServiceException | 💼 业务异常 | 自定义 |
FeignException | 🌐 Feign 调用异常 | 自定义 |
📝 特性说明
- 自动记录异常日志到
LogRecorder - 支持 JSON 解析错误的友好提示(未识别字段、枚举值范围)
- 忽略特定错误消息避免日志刷屏(如"无效的刷新令牌")
🛡️ XSS 防护
位置:
com.wzhcode.wbase.xss
基于 Jsoup 实现 XSS 过滤,支持两种方式:
| 方式 | 类 | 说明 |
|---|---|---|
| 🔍 Filter 过滤 | XssFilter | 过滤请求参数、Header、QueryString |
| 📄 JSON 反序列化 | XssStringJsonDeserializer | 过滤 JSON 请求体中的字符串 |
配置项
wbase:
xss:
enable: true # 是否开启,默认 true
exclude-urls: # 排除的 URL 列表
- /api/upload/**
- /api/webhook/**📝 安全规则说明
基于 Safelist.relaxed() 扩展:
- ✅ 支持
style和class属性 - ✅
<a>标签支持target属性 - ✅
<img>标签支持data:协议(base64 图片) - ❌ 移除危险的 JavaScript 协议
📝 API 访问日志
位置:
com.wzhcode.wbase.apilog
记录 API 请求的访问日志和异常日志。
配置项
wbase:
access-log:
enable: true # 是否开启,默认 false@ApiAccessLog 注解
@ApiAccessLog(
enable = true, // 是否记录
requestEnable = true, // 记录请求参数(默认 true)
responseEnable = false, // 记录响应结果(默认 false)
sanitizeKeys = {"password"}, // 脱敏字段
operateModule = "用户模块",
operateName = "用户登录",
operateType = OperateTypeEnum.OTHER
)
@PostMapping("/login")
public CommonResult<LoginVO> login(@RequestBody LoginDTO dto) {
// ...
}操作类型枚举
| 枚举值 | 说明 | 自动推断 |
|---|---|---|
GET | 查询 | GET 请求 |
CREATE | 新增 | POST 请求 |
UPDATE | 修改 | PUT 请求 |
DELETE | 删除 | DELETE 请求 |
EXPORT | 导出 | - |
IMPORT | 导入 | - |
OTHER | 其它 | - |
📝 自定义日志记录器
实现 LogRecorder 接口并注册为 Bean:
@Component
public class MyLogRecorder implements LogRecorder {
@Override
public void recordAccessLog(AccessLogInfo accessLogInfo) {
// 保存到数据库、发送到 MQ 等
}
@Override
public void recordErrorLog(ErrorLogInfo errorLogInfo) {
// 异常日志处理
}
}🔒 数据脱敏
位置:
com.wzhcode.wbase.desensitize
通过注解实现 JSON 响应数据脱敏:
内置脱敏注解
| 注解 | 说明 | 原始值 | 脱敏后 |
|---|---|---|---|
@MobileDesensitize | 📱 手机号 | 13248765917 | 132****5917 |
@EmailDesensitize | 📧 邮箱 | test@gmail.com | t****@gmail.com |
@IdCardDesensitize | 🪪 身份证 | 530321199204074611 | 530321**********11 |
@BankCardDesensitize | 💳 银行卡 | 9988002866797031 | 998800********31 |
@ChineseNameDesensitize | 👤 中文名 | 刘子豪 | 刘** |
@PasswordDesensitize | 🔑 密码 | 123456 | ****** |
@CarLicenseDesensitize | 🚗 车牌号 | 粤A66666 | 粤A6***6 |
@FixedPhoneDesensitize | ☎️ 固定电话 | 01086551122 | 0108*****22 |
自定义脱敏
public class UserVO {
@MobileDesensitize
private String mobile;
@EmailDesensitize
private String email;
// 滑动脱敏:保留前2后2,中间用*替换
@SliderDesensitize(prefixKeep = 2, suffixKeep = 2, replacer = "*")
private String customField;
// 正则脱敏
@RegexDesensitize(regex = "\\d{4}", replacer = "****")
private String regexField;
}📝 脱敏处理器扩展
- 创建自定义注解,标注
@DesensitizeBy - 实现
DesensitizationHandler接口
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@DesensitizeBy(handler = MyDesensitization.class)
public @interface MyDesensitize {
// 自定义参数
}
public class MyDesensitization implements DesensitizationHandler<MyDesensitize> {
@Override
public String desensitize(String origin, MyDesensitize annotation) {
// 自定义脱敏逻辑
return origin;
}
}📖 Swagger 文档
位置:
com.wzhcode.wbase.swagger
基于 Knife4j + SpringDoc 实现 API 文档。
配置项
wbase:
swagger:
title: API 在线文档
description: 接口文档描述
author: wzhcode
version: 1.0.0
url: https://github.com/wzhcode
email: xxx@example.com
license: Apache 2.0
license-url: https://www.apache.org/licenses/LICENSE-2.0
springdoc:
api-docs:
enabled: true # 生产环境建议关闭特性
| 特性 | 说明 |
|---|---|
| 🏷️ BaseEnum 支持 | 自动显示枚举值和描述 [1:开启; 0:关闭] |
| 📊 @EnumSchema | 指定字段关联的枚举类型 |
| 🔐 Authorization | 自动配置 Bearer Token 认证 |
| 📦 自动分组 | 扫描启动类包路径下所有接口 |
📝 枚举文档示例
// 方式一:字段类型为 BaseEnum 实现类,自动识别
public class UserVO {
private CommonStatusEnum status; // 自动显示 [1-开启,0-关闭]
}
// 方式二:使用 @EnumSchema 注解
public class QueryDTO {
@EnumSchema(CommonStatusEnum.class)
private Integer status;
}
// 方式三:实现 SwaggerDocEnum 接口
public enum MyEnum implements SwaggerDocEnum<Integer> {
A(1, "选项A"),
B(2, "选项B");
@Override
public Integer enumValue() { return code; }
@Override
public String enumDesc() { return desc; }
}⚙️ Jackson 配置
位置:
com.wzhcode.wbase.jackson
序列化规则
| 类型 | 序列化 | 反序列化 | 说明 |
|---|---|---|---|
Long | 超范围转 String | - | 解决 JS 精度丢失问题 |
LocalDateTime | 时间戳(毫秒) | 时间戳(毫秒) | 前后端统一 |
LocalDate | 标准格式 | 标准格式 | yyyy-MM-dd |
LocalTime | 标准格式 | 标准格式 | HH:mm:ss |
📝 Long 精度说明
JavaScript 最大安全整数为 2^53 - 1 = 9007199254740991
当 Long 值超出此范围时,自动序列化为字符串,避免前端精度丢失。
// 超出范围的 ID
Long id = 9007199254740992L;
// JSON 输出: "9007199254740992" (字符串)🔧 其他功能
跨域支持
自动配置 CorsFilter,允许所有来源访问:
// 已自动配置,无需额外处理
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);请求体缓存
CacheRequestBodyFilter 实现请求体可重复读取,用于:
- API 日志记录
- 签名验证
- 异常时获取请求参数
演示模式
wbase:
web:
demo: true # 开启后禁止 POST/PUT/DELETE 操作类型转换器
| 转换器 | 说明 |
|---|---|
BaseEnumConverter | Form 表单和 Query 参数的枚举转换 |
StringToLocalDateTimeConverter | 时间戳字符串转 LocalDateTime |
📝 枚举转换示例
// Controller
@GetMapping("/list")
public CommonResult<List<UserVO>> list(
@RequestParam CommonStatusEnum status // 传入 1 或 0,自动转换
) {
// ...
}🔄 自动配置
通过 Spring Boot 自动装配:
| 配置类 | 说明 | 条件 |
|---|---|---|
WBaseXssAutoConfiguration | XSS 防护 | wbase.xss.enable=true |
WBaseWebAutoConfiguration | Web 核心 | 默认开启 |
WBaseSwaggerAutoConfiguration | Swagger 文档 | springdoc.api-docs.enabled=true |
WBaseJacksonAutoConfiguration | Jackson 配置 | 默认开启 |
WBaseApiLogAutoConfiguration | API 日志 | wbase.access-log.enable=true |
📚 主要依赖
| 依赖 | 用途 | 版本管理 |
|---|---|---|
wbase-core | 基础核心模块 | ✅ |
spring-boot-starter-web | Web 框架 | ✅ |
spring-boot-starter-validation | 参数校验 | ✅ |
spring-security-core | 安全框架 | ✅ |
knife4j-openapi3-jakarta-spring-boot-starter | API 文档 | ✅ |
springdoc-openapi-starter-webmvc-ui | OpenAPI UI | 2.6.0 |
jsoup | XSS 过滤 | ✅ |
feign-core | Feign 客户端 | ✅ |
版本由
wbase-dependencies统一管理
💡 最佳实践
| 场景 | 推荐做法 |
|---|---|
| 🛡️ XSS 防护 | 默认开启,富文本接口加入 exclude-urls |
| 📝 访问日志 | 敏感接口配置 sanitizeKeys 脱敏 |
| 🔒 数据脱敏 | 响应 VO 中敏感字段添加脱敏注解 |
| 📖 API 文档 | 生产环境关闭 springdoc.api-docs.enabled=false |
| ⚠️ 异常处理 | 业务异常使用 ServiceException,自动转换为友好提示 |
| 🔄 枚举处理 | 实现 BaseEnum 接口,自动支持文档和转换 |
Made with ❤️ by wzhcode