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);
}
相关推荐
LucianaiB19 分钟前
我用豆包工作 Seed-2.1-pro,复刻了 QQ 时代爆红的魔术图片
后端
码事漫谈24 分钟前
智谱 ZCode 静默上传 Git 历史:48 小时信任危机复盘
后端
SL_staff24 分钟前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
掘金码甲哥1 小时前
当对话模型遇上向量模型,vllm production stack 又该如何应对?
后端
传奇开心果编程1 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff1 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈
IT_陈寒1 小时前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
滕州市燕猫虎计算机科技工作室个体工商户1 小时前
IDEA:Command line is too long
java·ide·intellij-idea
光影少年1 小时前
Express 中间件原理
后端·node.js·express
步行cgn2 小时前
Spring p 命名空间注入详解
java·前端·spring