Spring Boot控制器接收无效JSON时的异常该如何处理?
解决方案
方案1:通过JSR-380校验注解在请求入口校验(推荐)
利用Spring支持的JSR-380校验规范,在实体类的必填字段上添加校验注解,在控制器层开启校验,这样请求进入业务逻辑前就会拦截非法参数,避免空指针。
步骤1:修改Ship实体类,添加校验注解
import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonProperty; import java.io.Serializable; public class Ship implements Serializable { @JsonProperty("Name") @NotBlank(message = "Name字段不能为空,请检查JSON键名是否正确") private String name; @JsonProperty("Owner") @NotBlank(message = "Owner字段不能为空") private String owner; // 构造函数、Getter/Setter 保持不变 }
步骤2:在控制器方法中开启校验
在@RequestBody注解后添加@Valid,触发参数校验:
import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.http.ResponseEntity; import javax.servlet.http.HttpServletRequest; @PostMapping(value = "/shipdetails") public ResponseEntity acceptShip(@Valid @RequestBody Ship ship, HttpServletRequest request) { shipService.checkShip(ship); return new ResponseEntity<>(HttpStatus.OK); }
步骤3:添加全局异常处理器,统一处理校验失败
创建全局异常处理器,捕获校验失败的异常并返回友好提示:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<String> handleValidationErrors(MethodArgumentNotValidException ex) { StringBuilder errorMsg = new StringBuilder(); ex.getBindingResult().getAllErrors().forEach(error -> { errorMsg.append(error.getDefaultMessage()).append("; "); }); return new ResponseEntity<>(errorMsg.toString(), HttpStatus.BAD_REQUEST); } }
这样当JSON键名错误导致name字段为null时,校验会直接失败,返回400状态码和错误提示,不会进入服务层触发空指针。
方案2:在服务层提前做空指针判断
如果不想引入校验注解,可以在服务层的业务方法开头,先对必填字段做空指针检查,主动抛出异常:
@Service public class ShipService { Boolean checkShip(Ship ship) { // 先检查必填字段是否为空 if (ship.getName() == null || ship.getName().isBlank()) { throw new IllegalArgumentException("Name字段不能为空,请检查请求参数"); } if (ship.getName().equals("Queen Mary")) { // 业务逻辑 } // 其他逻辑省略 } }
可以在控制器中捕获这个异常,或者同样通过全局异常处理器处理,返回400错误。
方案3:配置Jackson忽略未知字段(可选)
如果希望请求中的未知字段(比如name_wrong)不影响反序列化,可以在Ship实体类上添加@JsonIgnoreProperties(ignoreUnknown = true)注解:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import java.io.Serializable; @JsonIgnoreProperties(ignoreUnknown = true) public class Ship implements Serializable { @JsonProperty("Name") private String name; @JsonProperty("Owner") private String owner; // 构造函数、Getter/Setter 保持不变 }
这个配置只是忽略未知字段,不会自动校验必填字段,建议配合方案1的校验注解一起使用,既能过滤非法字段,又能保证必填字段存在。
内容的提问来源于stack exchange,提问作者Radika Moonesinghe
相关产品推荐
相关产品推荐

