Java编程高频的“技术点”-03:“下划线命名”参数,后端用“驼峰命名“接收

在 Spring Boot 中,前端传递下划线命名(如 data_type)的参数,后端使用驼峰命名(如 dataType)接收是非常常见的需求。

具体的处理方式取决于请求方式参数格式

以下是几种主流且优雅的解决方案:

1. JSON 格式请求体的处理方式(最推荐)

方式一:全局配置(一劳永逸)

如果你的请求是 POST/PUT,并且以 JSON 格式(application/json)发送,Spring Boot 默认使用 Jackson 进行反序列化。你有两种方式处理:

  • 全局配置(推荐) :如果整个项目都采用这种风格,可以 在 application.ymlapplication.properties 中进行全局配置。这样所有的 JSON 字段都会自动在下划线和驼峰之间转换:
html 复制代码
spring:
  jackson:
    property-naming-strategy: SNAKE_CASE
  • 局部注解 :如果只是个别接口或类需要转换,可以在实体类的字段上添加 @JsonProperty 注解,或者在类级别使用 @JsonNaming 注解:
java 复制代码
import com.fasterxml.jackson.annotation.JsonProperty; // 注意包名不要引错
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;<websource>source_group_web_2</websource>

@Data
// 方式2a:类级别统一转换
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) 
public class EventDTO {
    private String id;
    private String name;
    
    // 方式2b:仅针对单个字段指定映射关系
    @JsonProperty("data_type") 
    private Boolean dataType;
}

2. GET 请求或表单提交的处理方式

对于非 JSON 格式的传参,Jackson 的注解会失效。这里提供两种优雅的解决方案:

方式一:自定义过滤器(Filter)

通过包装 Request,在获取参数时自动将驼峰转换为下划线去查找:

java 复制代码
@Component
public class ParameterNameConverterFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
        HttpServletResponse response, 
        FilterChain filterChain) throws ServletException, IOException {
        // 使用自定义的 Wrapper 替换原始 request
        ParameterNameRequestWrapper requestWrapper 
                = new ParameterNameRequestWrapper(request);
        filterChain.doFilter(requestWrapper, response);
    }
}


class ParameterNameRequestWrapper extends HttpServletRequestWrapper {

    public ParameterNameRequestWrapper(HttpServletRequest request) { 
        super(request);
    }
    
    @Override
    public String getParameter(String name) {
        // 优先尝试原名称,若为空则尝试转为下划线查找
        String value = super.getParameter(name);
        if (value == null) {
            // 假设引入了 Hutool 工具包进行转换
            String underlineName = StrUtil.toUnderlineCase(name); 
            return super.getParameter(underlineName);
        }
        return value;
    }
}

方式二:自定义参数解析器(ArgumentResolver)

定义一个专属注解,并在 Spring MVC 配置中注册解析器,实现业务代码零侵入:

java 复制代码
// 1. 定义注解
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface SnakeToCamel {}<websource>source_group_web_4</websource>

// 2. 编写解析器核心逻辑
public class SnakeToCamelAttributeProcessor 
    extends ServletModelAttributeMethodProcessor {

    public SnakeToCamelAttributeProcessor(boolean annotationNotRequired) {
        super(annotationNotRequired);
    }
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(SnakeToCamel.class);
    }
    @Override
    protected void bindRequestParameters(WebDataBinder binder, 
                                    NativeWebRequest request) {
        // 在这里实现下划线到驼峰的绑定逻辑...
        ServletRequest servletRequest
                 = request.getNativeRequest(ServletRequest.class);
        new SnakeToCamelRequestDataBinder(binder.getTarget()).bind(servletRequest);
    }
}

// 3. 注册到 WebMvcConfigurer
@Configuration
public class AppWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new SnakeToCamelAttributeProcessor(true));
    }
}

// 4. Controller 中使用
@GetMapping("/event")
public ResponseEntity<?> getEvent(@SnakeToCamel EventDTO eventDTO) {
    return ResponseEntity.ok(eventDTO);
}

3. "笨"办法(手动接收)

如果参数极少且不想做任何额外配置,可以直接在 Controller 方法上逐个声明并映射:

java 复制代码
@GetMapping("/event")
public ResponseEntity<EventDTO> getEvent(

        @RequestParam("id") String id,
        @RequestParam("name") String name,
        @RequestParam("data_type") Boolean dataType) {
    
    // 手动组装 DTO 对象
    EventDTO dto = new EventDTO();
    dto.setId(id);
    dto.setName(name);
    dto.setDataType(dataType);
    
    return ResponseEntity.ok(dto);
}
相关推荐
要阿尔卑斯吗1 小时前
企业级 RAG 系统的文件标签管理:三层架构与层级优化实战
后端
要阿尔卑斯吗1 小时前
Agent开发之为什么有了LangChain4j框架,我们却不能直接使用它?——桥接层设计详解
后端
用户7713970207061 小时前
从CMD到PowerShell:一个.NET开发者的命令行进化之路
后端
祎雪双十Gy1 小时前
从 DataX 的配置加载说起:我用 FastJson2 做了一个轻量级动态配置管理库
java·后端
小锋java12341 小时前
分享一套锋哥原创的SpringBoot4+Vue3宠物领养网站系统
java
Csvn3 小时前
Nginx 配置与运维管理 — 从安装到 SSL 反向代理
后端
mqcode4 小时前
若依框架做大了怎么办?多模块 Maven 拆分的完整指南
后端
用户40269244819084 小时前
CRMEB Pro 新增后台接口全链路:路由、权限、验证器、返回格式一次讲清
前端·后端
考虑考虑4 小时前
Java实现hmacsha1加密算法
java·后端·java ee
掉鱼的猫5 小时前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·spring boot