MST

星途 面试题库

面试题:Java实现RESTful API中的数据验证与异常处理

在Java实现RESTful API过程中,当客户端发送的数据不符合预期格式或业务规则时,如何进行有效的数据验证并抛出合适的异常。同时,如何在全局统一处理这些异常,向客户端返回友好且符合RESTful规范的错误信息,结合具体框架(如Spring Boot)说明实现思路与关键代码。
21.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 数据验证并抛出异常

1.1 使用Spring Boot Validation进行数据验证

在Spring Boot中,可以使用JSR-380(Bean Validation 2.0)规范相关的依赖,如hibernate-validator。假设定义一个简单的用户注册接口,接收的用户信息封装在User类中。

  1. 引入依赖pom.xml中添加以下依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  1. 定义数据模型并添加验证注解
import javax.validation.constraints.NotBlank;

public class User {
    @NotBlank(message = "用户名不能为空")
    private String username;
    @NotBlank(message = "密码不能为空")
    private String password;

    // 省略getter和setter方法
}
  1. 在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 自定义业务规则验证并抛出异常

除了使用标准的验证注解,还可以根据业务规则自定义验证逻辑。例如,验证用户名是否唯一。

  1. 自定义验证逻辑
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", "用户名已存在");
        }
    }
}
  1. 在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时处理客户端发送的不符合预期的数据,并返回友好的错误信息。