在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();
}
}关键注意事项
依赖确保:SpringBoot默认集成Jackson(
spring-boot-starter-web已包含),无需额外引入;JSON场景优先级:全局配置 > 字段注解,若全局配置了
SNAKE_CASE,字段注解@JsonProperty可覆盖全局规则;返回值控制:若配置了
SNAKE_CASE,后端返回给前端的JSON字段会自动转为下划线(如userName→user_name),若需返回小驼峰,可:全局配置改用
LowerCamelCaseStrategy;个别字段用
@JsonProperty("userName")指定返回名称;单独配置反序列化策略(进阶):
@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%的下划线↔小驼峰适配场景,根据实际传参方式选择即可。