shenhuanjie
shenhuanjie
发布于 2025-12-14 / 2 阅读
0
0

SpringBoot中前端下划线命名与后端DTO小驼峰命名的适配方案

在SpringBoot中实现前端下划线命名变量与后端DTO小驼峰命名的适配,核心是通过序列化/反序列化配置字段注解让框架自动完成命名风格转换,以下是3种主流实现方案(按推荐优先级排序):

方案1:全局配置(推荐,一劳永逸)

通过配置Jackson的全局序列化/反序列化规则,让所有DTO默认支持下划线↔小驼峰的自动转换,无需逐个字段注解。

步骤1:编写全局配置类

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {

    /**
     * 配置Jackson全局命名策略:下划线转小驼峰
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            // 设置输入(前端传参):下划线命名 → 小驼峰
            // 设置输出(后端返回):小驼峰 → 下划线(可选,根据需求关闭)
            builder.propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
            
            // 若仅需「前端下划线→后端小驼峰」,但「后端返回仍为小驼峰」,可改用:
            // builder.propertyNamingStrategy(new PropertyNamingStrategies.LowerCamelCaseStrategy());
            // 并配合反序列化专用策略(进阶场景)
        };
    }
}

步骤2:编写DTO(纯小驼峰,无需额外注解)

import lombok.Data;

@Data
public class UserDTO {
    // 前端传:user_name → 自动映射到userName
    private String userName;
    // 前端传:age_num → 自动映射到ageNum
    private Integer ageNum;
    // 前端传:create_time → 自动映射到createTime
    private String createTime;
}

步骤3:Controller接收参数

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    // 前端POST JSON:{"user_name":"张三","age_num":20,"create_time":"2025-01-01"}
    // 自动映射到UserDTO的userName/ageNum/createTime
    @PostMapping("/user")
    public String receiveUser(@RequestBody UserDTO userDTO) {
        System.out.println(userDTO.getUserName()); // 输出:张三
        System.out.println(userDTO.getAgeNum());    // 输出:20
        return "success";
    }
}

方案2:局部字段注解(适用于个别字段特殊场景)

若仅部分字段需要转换,或全局配置冲突,可通过@JsonProperty注解指定字段的下划线名称。

示例DTO:

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class UserDTO {
    // 前端传user_name → 映射到userName
    @JsonProperty("user_name")
    private String userName;
    
    // 前端传age_num → 映射到ageNum
    @JsonProperty("age_num")
    private Integer ageNum;
    
    // 无注解:前端需传createTime(小驼峰)才能映射
    private String createTime;
}

方案3:请求参数非JSON场景(如Form/Query参数)

若前端通过form-data/x-www-form-urlencoded或URL参数(Query)传递下划线参数,需结合@RequestParam或配置Spring的参数解析规则:

场景1:单个Query参数

@GetMapping("/user")
public String receiveUser(
    // 前端传:?user_name=张三 → 映射到userName
    @RequestParam("user_name") String userName,
    @RequestParam("age_num") Integer ageNum
) {
    return userName;
}

场景2:Form表单绑定DTO(需配置属性编辑器)

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.beans.PropertyEditorSupport;
import java.util.HashMap;
import java.util.Map;

@RestController
public class UserController {

    // 初始化参数绑定器:下划线→小驼峰
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                // 此处可扩展通用的下划线转小驼峰逻辑
                setValue(underscoreToCamel(text));
            }
        });
    }

    // 下划线转小驼峰工具方法
    private String underscoreToCamel(String str) {
        if (str == null || str.isEmpty()) return str;
        StringBuilder sb = new StringBuilder();
        boolean upper = false;
        for (char c : str.toCharArray()) {
            if (c == '_') {
                upper = true;
            } else {
                sb.append(upper ? Character.toUpperCase(c) : c);
                upper = false;
            }
        }
        return sb.toString();
    }

    // 前端Form提交:user_name=张三&age_num=20
    @PostMapping("/user/form")
    public String receiveForm(UserDTO userDTO) {
        return userDTO.getUserName();
    }
}

关键注意事项

  1. 依赖确保:SpringBoot默认集成Jackson(spring-boot-starter-web已包含),无需额外引入;

  2. JSON场景优先级:全局配置 > 字段注解,若全局配置了SNAKE_CASE,字段注解@JsonProperty可覆盖全局规则;

  3. 返回值控制:若配置了SNAKE_CASE,后端返回给前端的JSON字段会自动转为下划线(如userNameuser_name),若需返回小驼峰,可:

    1. 全局配置改用LowerCamelCaseStrategy

    2. 个别字段用@JsonProperty("userName")指定返回名称;

    3. 单独配置反序列化策略(进阶):

      @Bean
      public ObjectMapper objectMapper() {
          ObjectMapper objectMapper = new ObjectMapper();
          // 仅反序列化(前端→后端)用下划线转小驼峰
          objectMapper.setDeserializationConfig(objectMapper.getDeserializationConfig()
                  .with(PropertyNamingStrategies.SNAKE_CASE));
          // 序列化(后端→前端)用小驼峰
          objectMapper.setSerializationConfig(objectMapper.getSerializationConfig()
                  .with(PropertyNamingStrategies.LOWER_CAMEL_CASE));
          return objectMapper;
      }

总结

  • JSON传参:优先用「方案1全局配置」,简洁高效;

  • 个别字段特殊映射:用「方案2@JsonProperty注解」;

  • Form/Query参数:用「方案3参数绑定+工具方法」;

以上方案可覆盖99%的下划线↔小驼峰适配场景,根据实际传参方式选择即可。


评论