如何通过Java Bean Validation确保quantity仅接受数值输入?
问题与解决方案
问题背景
我有一个用于接收请求体的Java类ItemForReorderRequest,代码如下:
public class ItemForReorderRequest { private String itemNo; @DecimalMax(value = "100", message = "Reorder quantity must be less than or equal to 100") private Double quantity; }
合法请求体示例:
{ "itemNo": "000006510", "quantity": 100.0 }
需求是验证quantity字段仅接受数值输入,但当向该字段传入字符串时,系统抛出An unexpected application error has occurred通用异常,错误栈包含com.fasterxml.jackson.core.JsonParser相关内容。
问题根源
Jackson在反序列化JSON请求体时,遇到类型不匹配(字符串转Double)直接抛出解析异常,此时Bean Validation(如@DecimalMax)的校验逻辑还未触发,导致返回的是系统级通用错误而非参数校验错误。
解决方案
1. 配置Jackson禁用字符串转数值,开启严格类型检查
修改Jackson配置,禁止将字符串自动转换为数值,同时开启严格的类型校验,让Jackson在类型不匹配时抛出明确的解析错误:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); // 禁用字符串自动转为数值的特性 objectMapper.disable(DeserializationFeature.ACCEPT_STRING_FOR_NUMBER); // 开启严格类型检查,遇到无效类型直接抛出异常 objectMapper.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); return objectMapper; } }
2. 全局捕获Jackson解析异常,返回友好响应
通过Spring的全局异常处理器,捕获Jackson的解析异常,返回自定义的400错误提示:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(JsonParseException.class) public ResponseEntity<Map<String, String>> handleJsonParseError(JsonParseException ex) { Map<String, String> errorResp = new HashMap<>(); errorResp.put("code", "INVALID_PARAM_TYPE"); errorResp.put("message", "quantity字段必须为数值类型"); return ResponseEntity.badRequest().body(errorResp); } // 保留Bean Validation异常的处理逻辑,处理@DecimalMax等校验规则 @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()) ); return ResponseEntity.badRequest().body(errors); } }
3. 确保Controller参数校验生效
在接收请求的Controller方法中,给请求体参数添加@Valid注解,触发Bean Validation的校验逻辑:
@PostMapping("/items/reorder") public ResponseEntity<Void> submitReorder(@Valid @RequestBody ItemForReorderRequest request) { // 执行业务逻辑 return ResponseEntity.ok().build(); }
经过以上配置,当quantity传入字符串时,系统会返回明确的400错误和友好提示,而非通用系统异常;同时@DecimalMax的校验规则也能正常触发。
内容的提问来源于stack exchange,提问作者G.D. Nipuna
相关产品推荐
相关产品推荐

