SpringBoot REST API中重写的handleMethodArgumentNotValid无法触发排查
解决SpringBoot中自定义
handleMethodArgumentNotValid不触发的问题 我来帮你排查这个问题——这种情况我之前也碰到过,大概率是几个容易忽略的细节导致的,咱们一步步来梳理:
最可能的问题:重写方法的访问修饰符不匹配
你的FundsConfirmationExceptionHandler中重写的handleMethodArgumentNotValid方法用了public修饰符,但父类ResponseEntityExceptionHandler中的该方法是protected的。虽然Java允许子类放宽访问权限,但Spring在识别异常处理器的重写方法时,对签名的一致性要求很高,这个小差异可能导致Spring无法识别你的自定义处理器。
修正方案:把方法的修饰符改成protected,和父类保持一致:
@Override protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { System.out.println("Custom handleMethodArgumentNotValid method"); FundsConfirmationError responseBody = new FundsConfirmationError( HttpStatus.BAD_REQUEST.toString(), "Input Validation Failed. Parameter.: " + ex.getParameter().getParameterName() + " Value.: " + ex.getParameter().getParameter().toString() + " " + ex.getMessage(), Severity.ERROR.toString(), Sources.LOCAL_CAF_API.toString() ); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .header("X-CAF-ResponseID", request.getHeader("X-CAF-MSGID")) .body(responseBody); }
第二个关键问题:请求方式与参数绑定未触发校验
你的控制器方法用了@GetMapping,同时指定了consumes = MediaType.APPLICATION_JSON_VALUE——这是矛盾的:GET请求通常不会携带JSON请求体,Spring无法将URL的Query参数自动绑定到FundsConfirmationRequest实体类并触发@Valid校验,自然不会抛出MethodArgumentNotValidException。
修正方案分两种情况:
- 如果是用Query参数传递参数:
确保实体类字段与Query参数名完全匹配,并且Spring能完成参数绑定。此时若参数缺失或不符合规则,@Valid会触发校验,抛出目标异常。 - 如果是用JSON请求体传递参数:
把请求方式改成@PostMapping,并给参数加上@RequestBody注解:@PostMapping( headers = {"X-CAF-MSGID", "X-AccessToken"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE ) public ResponseEntity<?> fundsConfirmation( @RequestHeader(value="X-CAF-MSGID") String messageId, @RequestHeader(value="X-AccessToken") String accessToken, @Valid @RequestBody FundsConfirmationRequest requestParams ) throws FIClientException, FIParseException { // 业务逻辑 }
其他需要排查的点
- 异常处理器扫描范围:检查
@RestControllerAdvice所在的包是否在SpringBoot的扫描范围内。如果控制器和处理器不在同一根包下,需要指定扫描路径:@RestControllerAdvice(basePackages = {"com.yourpackage.controller", "com.yourpackage.exception"}) - 优先级冲突:如果项目中有其他
@ControllerAdvice类也处理了MethodArgumentNotValidException,可以给你的处理器加上@Order(Ordered.HIGHEST_PRECEDENCE)确保它优先执行:@RestControllerAdvice @Order(Ordered.HIGHEST_PRECEDENCE) public class FundsConfirmationExceptionHandler extends ResponseEntityExceptionHandler { // ... }
内容的提问来源于stack exchange,提问作者TomBrx
相关产品推荐
相关产品推荐

