面试题答案
一键面试1. 数据验证并抛出异常
1.1 使用Spring Boot Validation进行数据验证
在Spring Boot中,可以使用JSR-380(Bean Validation 2.0)规范相关的依赖,如hibernate-validator
。假设定义一个简单的用户注册接口,接收的用户信息封装在User
类中。
- 引入依赖
在
pom.xml
中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 定义数据模型并添加验证注解
import javax.validation.constraints.NotBlank;
public class User {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
// 省略getter和setter方法
}
- 在Controller中使用验证
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@Validated
public class UserController {
@PostMapping("/register")
public String register(@RequestBody @Valid User user) {
// 业务逻辑处理
return "注册成功";
}
}
当客户端发送的数据不符合验证规则时,Spring会抛出MethodArgumentNotValidException
异常。
1.2 自定义业务规则验证并抛出异常
除了使用标准的验证注解,还可以根据业务规则自定义验证逻辑。例如,验证用户名是否唯一。
- 自定义验证逻辑
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
@Component
public class UserValidator implements Validator {
@Autowired
private UserService userService;
@Override
public boolean supports(Class<?> clazz) {
return User.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
User user = (User) target;
if (userService.isUsernameExists(user.getUsername())) {
errors.rejectValue("username", "username.exists", "用户名已存在");
}
}
}
- 在Controller中使用自定义验证
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@Validated
public class UserController {
@Autowired
private UserValidator userValidator;
@PostMapping("/register")
public String register(@RequestBody @Valid User user, BindingResult bindingResult) {
userValidator.validate(user, bindingResult);
if (bindingResult.hasErrors()) {
throw new UserRegistrationException(bindingResult.getFieldError().getDefaultMessage());
}
// 业务逻辑处理
return "注册成功";
}
}
这里UserRegistrationException
是自定义的异常类。
2. 全局异常处理
2.1 创建全局异常处理器
在Spring Boot中,可以通过创建一个@ControllerAdvice
注解的类来全局处理异常。
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.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach(error -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(UserRegistrationException.class)
public ResponseEntity<Map<String, String>> handleUserRegistrationException(UserRegistrationException ex) {
Map<String, String> error = new HashMap<>();
error.put("error", ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
}
这样,无论是标准验证异常还是自定义业务异常,都能被统一处理并返回符合RESTful规范的错误信息给客户端。
总结
通过Spring Boot Validation实现数据格式验证,自定义验证逻辑实现业务规则验证,并利用@ControllerAdvice
进行全局异常处理,可以有效地在Java实现RESTful API时处理客户端发送的不符合预期的数据,并返回友好的错误信息。