spring boot 全局异常处理捕获参数缺失异常,核心在于利用 @restcontrolleradvice 配合 @exceptionhandler 拦截 methodargumentnotvalidexception。当请求体(json)中的字段违反 @validated 或 @valid 约束时,框架会自动抛出该异常,通过自定义处理器提取错误信息并返回统一格式即可。

如何区分表单提交与JSON提交的参数校验异常
表单提交(application/x-www-form-urlencoded)和 JSON 提交(application/json)在参数缺失时的异常类型不同。表单提交通常抛出 BindException 或 MissingServletRequestParameterException,而 JSON 提交则抛出 MethodArgumentNotValidException。因此,全局异常处理器需要分别针对这两种情况编写不同的处理逻辑,以确保能准确捕获并返回相应的错误提示。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<map object>> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<string object> body = new HashMap();
body.put("status", 400);
body.put("message", "参数校验失败");
// 提取第一个字段的错误信息作为示例
FieldError fieldError = ex.getBindingResult().getFieldErrors().stream()
.findFirst()
.orElse(null);
if (fieldError != null) {
body.put("field", fieldError.getField());
body.put("rejectedValue", fieldError.getRejectedValue());
body.put("errorMessage", fieldError.getDefaultMessage());
}
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
}
@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseEntity<map object>> handleMissingParam(
MissingServletRequestParameterException ex) {
Map<string object> body = new HashMap();
body.put("status", 400);
body.put("message", "缺少必需参数");
body.put("parameterName", ex.getParameterName());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
}
}</string></map></string></map>
上述代码展示了如何处理两种常见的参数缺失异常。对于 JSON 请求,MethodArgumentNotValidException 包含了详细的字段校验结果;对于 URL 查询参数或路径变量缺失,MissingServletRequestParameterException 则直接提供了缺失参数的名称。开发者可以根据实际需求调整返回的 ResponseEntity 结构。
如何自定义校验注解以提供更具体的错误提示
除了使用标准的 JSR-380 注解(如 @NotNull、@Size),Spring Boot 允许开发者创建自定义校验注解,以便在参数缺失或不符合特定业务规则时提供更具语义化的错误提示。例如,可以定义一个 @NotEmptyList 注解来确保列表不为空,或者定义一个 @ValidPhone 注解来验证手机号格式。这些自定义注解可以与全局异常处理器无缝配合,提升 API 的错误反馈质量。

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = NotEmptyListValidator.class)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmptyList {
String message() default "列表不能为空";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
public class NotEmptyListValidator implements ConstraintValidator<notemptylist list>> {
@Override
public boolean isValid(List> value, ConstraintValidatorContext context) {
if (value == null) {
return true; // 如果为null,由@NotNull负责校验
}
return !value.isEmpty();
}
}</notemptylist>
在 Controller 中使用自定义注解:
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/api")
public class MyController {
@PostMapping("/items")
public String addItems(@Valid @RequestBody ItemRequest request) {
return "Success";
}
}
class ItemRequest {
@NotEmptyList
private List<string> items;
// getters and setters
}</string>
当 items 列表为空时,将触发 MethodArgumentNotValidException,并由全局异常处理器返回“列表不能为空”的提示信息。这种方式使得错误提示更加贴近业务场景,提升了用户体验。
基于程序中某个输入、条件或结果的具体问题:当JSON中缺少嵌套对象字段时如何处理
在实际开发中,经常遇到 JSON 请求中包含嵌套对象的情况。如果嵌套对象的字段缺失,MethodArgumentNotValidException 仍然会被抛出,但错误信息的路径会包含父对象字段名。例如,如果请求体是 {"user": {}} ,而 User 类中有 @NotBlank 标注的 name 字段,那么错误信息将指向 user.name。全局异常处理器可以通过解析 FieldError 的 getField() 方法来获取完整的路径,从而提供更精确的错误定位。











