Skip to content

请求参数去空格使用指南

📖 概述

@TrimParam 是一个用于自动去除字符串参数空格的注解,支持字段级别和方法参数级别的字符串去空格处理。通过 AOP 切面自动拦截请求,对标记的字段和参数进行空格处理,提升数据质量和用户体验。

✨ 核心特性

🎯 灵活应用

  • 字段级别:在对象字段上添加注解,适用于 @RequestBody 参数
  • 参数级别:在 Controller 方法参数上添加注解,适用于 @RequestParam@PathVariable
  • 嵌套支持:支持嵌套对象和集合中的字符串字段处理
  • 全局配置:支持全局模式,无需逐个添加注解

🔧 处理类型

  • 前后空格:去除字符串前后的空白字符(默认)
  • 前置空格:只去除字符串前面的空白字符
  • 后置空格:只去除字符串后面的空白字符
  • 所有空格:去除字符串中所有的空白字符

🛡️ 安全特性

  • 空值处理:支持将空字符串转换为 null
  • 排除机制:支持排除特定字段和参数
  • 性能优化:智能判断,避免不必要的处理

🚀 快速开始

基础用法

1. 字段级别使用

java
@Data
public class UserDto {
    
    @TrimParam
    private String username; // 自动去除前后空格
    
    @TrimParam(type = TrimParam.TrimType.ALL)
    private String phoneNumber; // 去除所有空格
    
    @TrimParam(emptyToNull = true)
    private String email; // 去除空格并将空字符串转为null
    
    private String password; // 不处理
}

2. 参数级别使用

java
@RestController
@RequestMapping("/api/user")
public class UserController {
    
    @GetMapping("/search")
    public Result<List<User>> searchUsers(
            @TrimParam @RequestParam String keyword, // 自动去除前后空格
            @TrimParam(type = TrimParam.TrimType.ALL) @RequestParam String phone,
            @RequestParam Integer page) {
        // keyword 和 phone 会自动去除空格
        return userService.searchUsers(keyword, phone, page);
    }
    
    @GetMapping("/{id}")
    public Result<User> getUser(
            @TrimParam @PathVariable String id) { // 路径参数也支持
        return userService.getUserById(id);
    }
    
    @PostMapping("/create")
    public Result<User> createUser(@RequestBody UserDto userDto) {
        // UserDto 中标记了 @TrimParam 的字段会自动处理
        return userService.createUser(userDto);
    }
}

📋 注解属性详解

核心属性

属性类型默认值说明
enabledbooleantrue是否启用去空格功能
typeTrimTypeBOTH去空格类型
emptyToNullbooleanfalse是否将空字符串转换为null

去空格类型 (TrimType)

类型说明示例
BOTH去除前后空格(默认)" hello ""hello"
LEADING只去除前面空格" hello ""hello "
TRAILING只去除后面空格" hello "" hello"
ALL去除所有空格" h e l l o ""hello"

⚙️ 全局配置

配置文件

yaml
# application.yml
wueasy:
  trim-string:
    enabled: true                    # 全局开关
    global-enabled: false            # 是否启用全局模式
    global-type: BOTH               # 全局默认去空格类型
    global-empty-to-null: false     # 全局默认是否空字符串转null
    global-process-params: true     # 是否处理请求参数
    global-process-fields: true     # 是否处理请求体字段
    global-exclude-fields:          # 排除的字段名
      - password
      - token
    global-exclude-params:          # 排除的参数名
      - timestamp
      - signature

💡 实用示例

1. 用户注册表单处理

java
@Data
public class UserRegisterDto {
    
    @TrimParam // 用户名去除前后空格
    @NotBlank(message = "用户名不能为空")
    private String username;
    
    @TrimParam(emptyToNull = true) // 邮箱去空格,空字符串转null
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @TrimParam(type = TrimParam.TrimType.ALL) // 手机号去除所有空格
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phoneNumber;
    
    @TrimParam // 真实姓名去除前后空格
    private String realName;
    
    // 密码不处理空格,保持原样
    @NotBlank(message = "密码不能为空")
    private String password;
    
    @TrimParam(emptyToNull = true) // 地址去空格,可为空
    private String address;
}

@PostMapping("/register")
public ResultVo<User> register(@Valid @RequestBody UserRegisterDto dto) {
    // dto 中的字符串字段会自动处理空格
    return userService.register(dto);
}

2. 搜索接口参数处理

java
@GetMapping("/search")
public ResultVo<PageInfo<Product>> searchProducts(
        @TrimParam @RequestParam(required = false) String keyword, // 关键词去空格
        @TrimParam @RequestParam(required = false) String category, // 分类去空格
        @TrimParam(type = TrimParam.TrimType.ALL) @RequestParam(required = false) String code, // 商品编码去所有空格
        @RequestParam(defaultValue = "1") Integer page,
        @RequestParam(defaultValue = "10") Integer size) {
    
    SearchCriteria criteria = SearchCriteria.builder()
            .keyword(keyword)
            .category(category)
            .code(code)
            .page(page)
            .size(size)
            .build();
            
    return productService.searchProducts(criteria);
}

3. 嵌套对象处理

java
@Data
public class OrderDto {
    
    @TrimParam
    private String orderNo; // 订单号去空格
    
    @Valid
    private CustomerInfo customer; // 嵌套对象
    
    @Valid
    private List<OrderItem> items; // 集合中的对象
}

@Data
public class CustomerInfo {
    
    @TrimParam
    private String name; // 客户姓名去空格
    
    @TrimParam(type = TrimParam.TrimType.ALL)
    private String phone; // 客户电话去所有空格
    
    @TrimParam(emptyToNull = true)
    private String email; // 客户邮箱去空格,空转null
}

@Data
public class OrderItem {
    
    @TrimParam
    private String productCode; // 商品编码去空格
    
    @TrimParam(emptyToNull = true)
    private String remark; // 备注去空格,空转null
    
    private Integer quantity; // 数量不处理
}

4. 全局模式使用

yaml
# 启用全局模式
wueasy:
  trim-string:
    enabled: true
    global-enabled: true              # 启用全局模式
    global-type: BOTH                # 全局去除前后空格
    global-empty-to-null: false      # 全局不转null
    global-exclude-fields:           # 排除特定字段
      - password
      - token
      - signature
    global-exclude-params:           # 排除特定参数
      - timestamp
      - nonce
java
// 全局模式下,即使不添加注解也会处理
@Data
public class SimpleDto {
    private String name;        // 会自动去除前后空格
    private String email;       // 会自动去除前后空格
    private String password;    // 在排除列表中,不会处理
    private Integer age;        // 非字符串类型,不会处理
}

@GetMapping("/simple")
public Result<String> simpleMethod(
        @RequestParam String keyword,    // 会自动去除前后空格
        @RequestParam String timestamp,  // 在排除列表中,不会处理
        @RequestParam Integer page) {    // 非字符串类型,不会处理
    return Result.success("处理完成");
}

5. 特殊场景处理

java
@Data
public class AdvancedDto {
    
    // 禁用处理
    @TrimParam(enabled = false)
    private String rawData; // 保持原样,不处理空格
    
    // 只去除前面空格
    @TrimParam(type = TrimParam.TrimType.LEADING)
    private String leadingTrimmed;
    
    // 只去除后面空格
    @TrimParam(type = TrimParam.TrimType.TRAILING)
    private String trailingTrimmed;
    
    // 去除所有空格并转null
    @TrimParam(type = TrimParam.TrimType.ALL, emptyToNull = true)
    private String allTrimmedToNull;
    
    // 嵌套Map中的字符串也会处理
    private Map<String, Object> metadata;
}

🎯 最佳实践

1. 性能优化

java
// ✅ 推荐:只在需要的字段上使用注解
@Data
public class OptimizedDto {
    
    @TrimParam // 用户输入的字段需要处理
    private String userInput;
    
    // ❌ 避免:系统生成的字段不需要处理
    // @TrimParam
    private String systemGenerated;
    
    @TrimParam(enabled = false) // 明确禁用
    private String sensitiveData;
}

2. 安全考虑

java
@Data
public class SecurityDto {
    
    @TrimParam // 用户名可以去空格
    private String username;
    
    // ✅ 推荐:密码等敏感信息不要处理空格
    private String password;
    
    // ✅ 推荐:令牌等不要处理
    private String accessToken;
    
    @TrimParam(type = TrimParam.TrimType.ALL) // 手机号去所有空格
    private String phoneNumber;
}

3. 数据验证配合

java
@Data
public class ValidatedDto {
    
    @TrimParam
    @NotBlank(message = "用户名不能为空") // 先去空格,再验证
    @Size(min = 3, max = 20, message = "用户名长度必须在3-20之间")
    private String username;
    
    @TrimParam(emptyToNull = true)
    @Email(message = "邮箱格式不正确") // 空字符串转null后,@Email不会报错
    private String email;
    
    @TrimParam(type = TrimParam.TrimType.ALL)
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phoneNumber;
}

❗ 注意事项

性能影响

  • 字符串处理在每次请求时执行,大量字符串字段时注意性能
  • 建议只在用户输入的字段上使用,避免对系统生成的字段处理
  • 全局模式会影响所有字符串字段,谨慎使用

数据完整性

  • 某些场景下空格可能有业务意义,需要谨慎处理
  • 密码、令牌等敏感信息建议不要处理空格
  • 格式化的数据(如JSON、XML)不建议处理

类型兼容性

  • 只处理 String 类型的字段和参数
  • 支持嵌套对象、集合、Map 中的字符串
  • null 值不会被处理

异常处理

  • 处理异常会被捕获并记录日志,返回原始值
  • 建议在开发环境启用调试日志
  • 可通过配置调整异常处理策略

💡 提示:建议在开发环境中充分测试去空格效果,确保不会影响业务逻辑后再部署到生产环境。