购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.2 Spring Boot Validate参数校验

在接口开发的过程中,一个非常重要的原则就是不信任任何的输入,开发者根本不知道传递的是什么参数,因此需要对入参进行参数的校验,否则极有可能引发系统故障,或者造成业务数据的错误。

3.2.1 传统的if…else校验

以前,开发者经常在Controller中对参数进行if…else判断,如果参数不符合要求,就提示用户参数错误,流程不再进行下去,类似下面的代码:

package com.springboot.demo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController1 {

   /**
    * 保存新的用户
    * @param user
    */
    @PostMapping("/save")
    public void saveUser(@RequestBody User user) {
       if (user.getAge() > 120) {
          throw new IllegalArgumentException("最大年龄小于120");
       }
       if (user.getAge() < 1) {
          throw new IllegalArgumentException("最小年龄大于1");
       }
       if (user.getUserName() == null) {
          throw new IllegalArgumentException("用户名不能为空");
       }
       if (user.getUserName().length() > 10) {
          throw new IllegalArgumentException("用户名长度不能超过10");
       }
       if(user.getPassword()==null){
          throw new IllegalArgumentException("密码不能为空");
       }
       //saveTheUser
   }
}

以上代码中对应的User实体类的代码如下:

package com.springboot.demo;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
@Data
public class User {
    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false, unique = true)
    private String userName;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private int age;
}

Controller中的if代码能够满足参数校验功能的需要,但是代码逻辑非常“丑陋”,没有一点优雅、复用性可言。Spring Boot中是怎么处理的呢?

3.2.2 实战:现代的Spring Boot Validate校验

在Spring Boot项目中,可以使用Spring Boot Validate进行参数的校验,开发人员只需要简单地标记注解就能完成参数的校验。下面演示Spring Boot的参数校验。

(1)在pom.xml中添加校验的依赖如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

(2)首先新建包com.springboot.demo,再新建一个类UserController2用于参数校验,执行新建用户的保存方法。

package com.springboot.demo;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;

@RestController
public class UserController2 {

   /**
    * 保存新的用户
    * @param user
    */
    @PostMapping("/save")
    public void saveUser(@Valid @RequestBody User user) {
        //saveTheUser
    }
}

(3)在包com.springboot.demo中新建User实体类并在其中配置校验,代码如下:

package com.springboot.demo;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;

@Entity
@Data
public class User {
   @Id
   @GeneratedValue
   private long id;

   @NotBlank
   @Length(max = 10, message = "用户名长度不能超过10")
   @Column(nullable = false, unique = true)
   private String userName;

   @NotBlank(message = "密码不能为空")
   @Column(nullable = false)
   private String password;

   @Max(value = 120, message = "最大年龄小于120")
   @Min(value = 1, message = "最小年龄大于1")
   @Column(nullable = false)
   private int age;
}

(4)在UserController2的方法中给要校验的参数标记上@Valid注解,再使用如@Not- Blank、@Min和@Max注解并且加上提示信息就能完成参数的校验。

(5)为了系统的完整性,在Spring Boot项目中增加系统异常的处理,需要给用户返回统一的结果并在结果中提示入参的具体错误。在包com.springboot.demo中新建ValidateCommonHandler异常处理类,代码如下:

package com.springboot.demo;

import org.springframework.http.*;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.Response
EntityExceptionHandler;

public class ValidateCommonHandler extends ResponseEntityExceptionHandler {

   @Override
   protected ResponseEntity<Object> handleMethodArgumentNotValid(
           MethodArgumentNotValidException ex,
             HttpHeaders headers, HttpStatus status,
           WebRequest request) {
       ResponeVo vo = new ResponeVo();
       vo.setCode(500);
       for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
           String defaultMessage = fieldError.getDefaultMessage();
           vo.setMessage(defaultMessage);
           Object value = fieldError.getRejectedValue();
           vo.setData(value);
           break;
       }
       return new ResponseEntity(vo, HttpStatus.OK);
   }
}

新建一个ValidateCommonHandler类继承自ResponseEntityExceptionHandler接口,并且重写该接口的handleMethodArgumentNotValid()方法,ResponseEntityExceptionHandler是统一处理所有经过Valid注解的接口,此处统一返回类ResponeVo的信息,用这个类和前端进行Restful交互,只要出现校验命中的就会执行此方法,并且携带具体的错误信息。

(6)在包com.springboot.demo中新建统一返回实体信息类ResponeVo:

package com.springboot.demo;
import lombok.Data;
@Data
public class ResponeVo {
    private int code;
    private String message;
    private Object data;
}

上述代码中,code返回一个标识码,message字段用于返回校验的信息,data返回具体的数据。

3.2.3 Validate校验常用的注解

Spring Boot Validate的参数校验依赖于注解,可以对不同类型的参数配置相应的注解校验,常用的注解如表3.1所示。

表3.1 Validate注解 8PCTotH9FXwsUUxRHg3Cp5kkDRQs4v+fcwY0Tph/KWn65aYfJyqU4GeQaqoGrOpV

058-1
点击中间区域
呼出菜单
上一章
目录
下一章
×

打开