1. 程式人生 > 程式設計 >SpringBoot + validation 介面引數校驗的思路詳解

SpringBoot + validation 介面引數校驗的思路詳解

有引數傳遞的地方都少不了引數校驗。在web開發中,前端的引數校驗是為了使用者體驗,後端的引數校驗是為了安全。試想一下,如果在controller層中沒有經過任何校驗的引數通過service層、dao層一路來到了資料庫就可能導致嚴重的後果,最好的結果是查不出資料,嚴重一點就是報錯,如果這些沒有被校驗的引數中包含了惡意程式碼,那就可能導致更嚴重的後果。

實踐

一、引入依賴

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

二、使用校驗

在controller層的引數校驗可以分為兩種場景:

單個引數校驗
實體類引數校驗

2.1 單引數校驗

/**
 * 引數校驗測試 控制類
 * @author oyc
 */
@RestController
@RequestMapping("user")
@Validated
public class RequestParamsValidatedController {
 
 private Logger logger = LoggerFactory.getLogger(this.getClass());
 
 @GetMapping
 public User test(@NotNull(message = "姓名不能為空") String name,@NotNull(message = "年齡不能為空") @Max(value = 99,message = "不能大於200歲") Integer age) {
  logger.info("name:" + name + " -age:" + age);
  return new User(name,age);
 }
}

2.2實體類引數校驗

/**
 * 引數校驗測試 控制類
 * @author oyc
 */
@RestController
@RequestMapping("user")
@Validated
public class RequestParamsValidatedController {
 
 private Logger logger = LoggerFactory.getLogger(this.getClass());
 
 @PostMapping
 public User save(@Validated User user) {
  logger.info(user.toString());
  return user;
 }
}
package com.oycbest.springbootvalidated.vo;
 
 
import javax.validation.constraints.*;
import java.io.Serializable;
 
/**
 * 使用者實體類
 * @author oyc
 */
public class User implements Serializable {
 private String userId;
 
 @NotNull(message = "使用者名稱不能為空")
 private String userName;
 
 @NotNull(message = "年齡不能為空")
 @Max(value = 100,message = "年齡不能大於100歲")
 private int age;
 
 @NotNull(message = "郵箱不能為空")
 @Email(message = "郵箱格式不正確")
 private String email;
 
 @NotNull(message = "電話號碼不能為空")
 private String phoneNumber;
 
 public User(@NotNull(message = "使用者名稱不能為空") String userName,int age) {
  this.userName = userName;
  this.age = age;
 }
 
 public User() {
 }
 
 public User(String userId,@NotNull(message = "使用者名稱不能為空") String userName,int age,String email,String phoneNumber) {
  this.userId = userId;
  this.userName = userName;
  this.age = age;
  this.email = email;
  this.phoneNumber = phoneNumber;
 }
 
 public String getUserId() {
  return userId;
 }
 
 public void setUserId(String userId) {
  this.userId = userId;
 }
 
 public String getUserName() {
  return userName;
 }
 
 public void setUserName(String userName) {
  this.userName = userName;
 }
 
 public int getAge() {
  return age;
 }
 
 public void setAge(int age) {
  this.age = age;
 }
 
 public String getEmail() {
  return email;
 }
 
 public void setEmail(String email) {
  this.email = email;
 }
 
 public String getPhoneNumber() {
  return phoneNumber;
 }
 
 public void setPhoneNumber(String phoneNumber) {
  this.phoneNumber = phoneNumber;
 }
 
 @Override
 public String toString() {
  return "User{" +
    "userId='" + userId + '\'' +
    ",userName='" + userName + '\'' +
    ",age=" + age +
    ",email='" + email + '\'' +
    ",phoneNumber='" + phoneNumber + '\'' +
    '}';
 }
}

2.3 定義統一異常處理

package com.oycbest.springbootvalidated.exception;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
 
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.List;
import java.util.Set;
 
/**
 * 全域性異常處理
 *
 * @author oyc
 */
@ControllerAdvice
@Component
public class GlobalExceptionHandler {
 private Logger logger = LoggerFactory.getLogger(this.getClass());
 
 @Bean
 public MethodValidationPostProcessor methodValidationPostProcessor() {
  return new MethodValidationPostProcessor();
 }
 
 @ExceptionHandler
 @ResponseBody
 @ResponseStatus(HttpStatus.BAD_REQUEST)
 public String handle(ValidationException exception) {
  logger.error("請求異常:" + exception.getMessage());
  if (exception instanceof ConstraintViolationException) {
   ConstraintViolationException exs = (ConstraintViolationException) exception;
 
   Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
   for (ConstraintViolation<?> item : violations) {
    //列印驗證不通過的資訊
    logger.error("請求異常:" + item.getMessage());
   }
  }
  return "請求異常: " + exception.getMessage();
 }
 
 @ResponseBody
 @ExceptionHandler(value = BindException.class)
 public String bindException(Exception e) {
  if (e instanceof BindException) {
   BindException exs = (BindException) e;
   List<FieldError> fieldErrors = exs.getFieldErrors();
   for (FieldError item : fieldErrors) {
    logger.error("請求異常:" + item.getDefaultMessage());
   }
  }
  logger.error("資料繫結異常:" + e.getMessage());
  return "資料繫結異常";
 }
 
 @ResponseBody
 @ExceptionHandler(value = Exception.class)
 public String defaultException(Exception e) {
  logger.error("請求異常:" + e.getMessage());
  return "請求異常 " + e.getMessage();
 }
 
}

三、約束性註解(簡單)說明

註解

功能

@AssertFalse

可以為null,如果不為null的話必須為false

@AssertTrue

可以為null,如果不為null的話必須為true

@DecimalMax

設定不能超過最大值

@DecimalMin

設定不能超過最小值

@Digits

設定必須是數字且數字整數的位數和小數的位數必須在指定範圍內

@Future

日期必須在當前日期的未來

@Past

日期必須在當前日期的過去

@Max

最大不得超過此最大值

@Min

最大不得小於此最小值

@NotNull

不能為null,可以是空

@Null

必須為null

@Pattern

必須滿足指定的正則表示式

@Size

集合、陣列、map等的size()值必須在指定範圍內

@Email

必須是email格式

@Length

長度必須在指定範圍內

@NotBlank

字串不能為null,字串trim()後也不能等於“”

@NotEmpty

不能為null,集合、陣列、map等size()不能為0;字串trim()後可以等於“”

@Range

值必須在指定範圍內

@URL

必須是一個URL

到此這篇關於SpringBoot + validation 介面引數校驗的文章就介紹到這了,更多相關SpringBoot + validation 介面引數校驗內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!