1. 程式人生 > 程式設計 >Spring中使用JSR303請求約束判空的實現

Spring中使用JSR303請求約束判空的實現

1. 適用場景

有時候我們在表單裡提交一系列引數,到後臺封裝成一個物件,要對物件的屬性做各種欄位值的約束; 這時候,當然可以if-else一個一個的判斷,有更簡潔的做法,就是使用 JSR303+spring的validation:

2. 使用方法步驟(分3步)

  • 實體類加欄位約束註解
  • Controller類中@Valid標註啟用(@Validated也相容@Valid)
  • BindingResult獲取報錯資訊

2.1 實體類加欄位約束註解

如我們要收集前端表單的欄位資料到Person實體中:

對需要約束的欄位進行註解標註;

示例:

2.1.1 Person.java

package com.niewj.demo.model;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.*;
import java.util.List;

@Data
public class Person {
  @Length(min = 4,max = 10)
  @NotNull(message = "name不能為空")
  private String name;

  @Min(0)
  @Max(40)
  @NotNull(message = "age不能為空")
  private Integer age;

  @NotBlank
  @NotBlank
  @URL(message = "logo必須是URL格式")
  private String logo;

  @NotEmpty(message = "hobbies不能為空")
  private List<String> hobbies;

  @Email
  @NotNull(message = "email不能為空!")
  private String mail;
}

@NotNull 約束欄位不可為空;

@NotEmpty 約束集合/map等不能為空不能為0元素

@Email 約束是 email格式

@URL 約束必須是url的格式

message屬性可以修改預設錯誤說明

2.2 Controller類中@Valid標註啟用(@Validated相容@Valid)

2.2.1 HelloController.java

package com.niewj.demo.controller;

import com.google.gson.Gson;
import com.niewj.demo.common.Result;
import com.niewj.demo.model.Person;
import com.niewj.demo.service.TestService1;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * test
 *
 * @author niewj
 * @since 2020/11/16 15:22
 */
@Controller
public class HelloController {

  /**
   * @param person
   * @param bindingResult
   * @return
   */
  @PostMapping("/test")
  @ResponseBody
  public Result doSth(@Valid @RequestBody Person person,BindingResult bindingResult) {
    Map<String,String> map = new HashMap<>();
    if (bindingResult.hasErrors()) {
      bindingResult.getFieldErrors().stream().forEach(fe-> map.put(fe.getField(),fe.getDefaultMessage()));
      System.out.println(bindingResult.getFieldError().getDefaultMessage());
      return Result.withErrorParamData(map);
    }

    return Result.withSuccessData(person);
  }
}

@RequestBody可以將body中的請求流資訊(Request.getInputStream)通過HttpMessageConverter自動轉換為目標java型別:

  • 如果前端 Content-Type為application/json,就使用 JSON訊息轉換器 幫你轉為JSON物件;
  • 如果前端 Content-Type為application/xml,就使用 XML訊息轉換器 幫你轉為xml;
  • 如果前端 Content-Type為text/plain,就是用 String訊息轉換器 幫你轉成 String; (只有型別為String時才可以轉換)

2.2.2 Result.java:

package com.niewj.demo.common;

import lombok.Data;

import java.io.Serializable;
import java.util.Map;

/**
 * 返回結果模板封裝
 *
 * @author niewj
 * @since 2020/12/17 18:05
 */
@Data
public class Result<T> implements Serializable {
  private int code;
  private String msg;
  private T data;

  public Result(int code,String msg,T data) {
    this(code,msg);
    this.data = data;
  }

  public Result(int code,String msg) {
    this.msg = msg;
    this.code = code;
  }

  public static <T> Result<T> withData(ResponseEnum responseCode,T data) {
    Result<T> re = new Result(responseCode.getCode(),responseCode.getMsg());
    re.data = data;
    return re;
  }

  public static Result<String> withSuccessNoData() {
    Result re = new Result(ResponseEnum.SUCCESS.getCode(),ResponseEnum.SUCCESS.getMsg());
    re.data = "";
    return re;
  }

  public static <T> Result<T> withSuccessData(T data) {
    Result re = new Result(ResponseEnum.SUCCESS.getCode(),ResponseEnum.SUCCESS.getMsg());
    re.data = data;
    return re;
  }

  public static Result<Map<String,String>> withErrorParamData(Map<String,String> data) {
    Result re = new Result(ResponseEnum.BAD_REQUEST.getCode(),ResponseEnum.BAD_REQUEST.getMsg());
    re.data = data;
    return re;
  }
}

2.2.3 ResponseEnum.java

package com.niewj.demo.common;

/**
 * 通用響應碼
 */
public enum ResponseEnum {

  SUCCESS(200,"成功"),BAD_REQUEST(400,"請求引數不合規");

  /**
   * 錯誤碼
   */
  private Integer code;
  /**
   * 錯誤資訊
   */
  private String msg;

  ResponseEnum(Integer code,String msg) {
    this.code = code;
    this.msg = msg;
  }

  public String getMsg() {
    return msg;
  }

  public Integer getCode() {
    return code;
  }
}

2.3 BindingResult獲取報錯資訊

  • BindingResult用來收集約束欄位的錯誤資訊,可通過 bindingResult.hasErrors()的 true來過濾錯誤資訊;
  • bindingResult.getFieldErrors() 會返回 List<FieldError>;
  • FieldError 得到欄位名: getField(); 得到錯誤資訊: getDefaultMessage()

3. 呼叫測試:

http://localhost:8888/test

3.1 請求用例1: 欄位為空

header: Content-Type: application/json

{
  "name": "1"
}

響應:

{
  "code": 400,"msg": "請求引數不合規","data": {
    "mail": "email不能為空!","hobbies": "hobbies不能為空","name": "長度需要在4和10之間","logo": "不能為空","age": "age不能為空"
  }
}

3.2 請求用例2: list無元素/email/url格式不對

header: Content-Type: application/json

{
  "name": "1234","hobbies": [],"mail": "niewj","logo": "niewj.com"
}

響應:

{
  "code": 400,"data": {
    "mail": "不是一個合法的電子郵件地址","logo": "logo必須是URL格式","age": "age不能為空"
  }
}

3.3 請求用例3: 完整欄位資訊

header: Content-Type: application/json

{
  "name": "1234","hobbies": ["running"],"mail": "[email protected]","logo": "http://niewj.com","age": 40
}

響應:

{
  "code": 200,"msg": "成功","data": {
    "name": "1234","age": 40,"hobbies": [
      "running"
    ],"mail": "[email protected]"
  }
}

到此這篇關於Spring中使用JSR303請求約束判空的實現的文章就介紹到這了,更多相關Spring JSR303請求約束判空內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!