Spring Boot中@RequestParam与@NotNull生效顺序及自定义返回需求
问题描述
我有一段Spring Boot接口代码:
@PostMapping("/search/get_search_tips") public String get_search_tips( @RequestParam("keywords") @NotNull String keyWords) { return templateService.getSearchTips(keyWords).toJSONString(); }
当缺失keywords参数时,Spring会返回默认的400错误:
{ "timestamp": "2023-02-01T10:09:16.283+00:00", "status": 400, "error": "Bad Request", "path": "/template/search/get_search_tips" }
我已经编写了适配@NotNull的全局异常处理器,修改代码为:
@PostMapping("/search/get_search_tips") public String get_search_tips( @RequestParam("keywords",required = false) @NotNull String keyWords) { return templateService.getSearchTips(keyWords).toJSONString(); }
此时缺失keywords参数会返回自定义格式结果:
{ "code": 1080, "msg": "error param", "result": [ { "key": "keyWords", "msg": "不能为null" } ] }
现在需要实现:请求参数keywords映射到方法参数keyWords,同时返回上述自定义结果,但不想编写@RequestParam("keywords",required = false) @NotNull这样的重复注解组合,该如何处理?
解决方案
方案1:使用DTO+@Validated封装参数
将请求参数封装为DTO类,通过Spring的参数绑定自动映射请求参数,同时在DTO字段上添加校验注解,简化接口方法的注解编写。
- 定义请求DTO类:
import javax.validation.constraints.NotNull; import lombok.Data; @Data public class SearchTipsRequest { @NotNull(message = "不能为null") private String keywords; // 字段名与请求参数名一致,自动映射 }
- 修改接口方法:
import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; @PostMapping("/search/get_search_tips") public String get_search_tips(@Validated SearchTipsRequest request) { return templateService.getSearchTips(request.getKeywords()).toJSONString(); }
前端传递的keywords参数会自动绑定到DTO的keywords字段,当参数缺失时,@Validated会触发@NotNull校验,全局异常处理器捕获后返回自定义结果。
方案2:自定义组合注解
把@RequestParam(required = false)和@NotNull封装成一个自定义注解,一次注解完成参数映射和非空校验。
- 定义自定义组合注解:
import javax.validation.constraints.NotNull; import org.springframework.web.bind.annotation.RequestParam; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @RequestParam(required = false) @NotNull(message = "不能为null") public @interface RequiredRequestParam { // 重写@RequestParam的value属性,用于指定请求参数名 String value() default ""; }
- 修改接口方法:
@PostMapping("/search/get_search_tips") public String get_search_tips(@RequiredRequestParam("keywords") String keyWords) { return templateService.getSearchTips(keyWords).toJSONString(); }
使用自定义注解替代原有的两个注解,既完成了请求参数keywords到方法参数keyWords的映射,又能触发非空校验,缺失参数时返回自定义结果。
方案3:全局参数解析器(进阶)
如果项目中有大量类似需求,可以自定义SpringMVC参数解析器,实现全局的参数映射与校验逻辑,完全去掉方法上的注解。核心步骤:
- 实现
HandlerMethodArgumentResolver接口,在解析参数时自动绑定请求参数并执行非空校验 - 将自定义解析器注册到SpringMVC的配置中
这种方式适合大规模统一处理的场景,但需要额外的配置和编码工作,适合对代码简洁性要求极高的场景。
内容的提问来源于stack exchange,提问作者lehaifeng000
相关产品推荐
相关产品推荐

