【學習筆記】後端表單驗證JSR303

概況

在處理後端的業務邏輯是經常會涉及表單數據的提交請求,咱們不只在前端對數據進行驗證,並且在後端也須要對數據進行驗證,以此來保證數據的完整性,然後端對於表單數據的驗證使用的最多的莫過於JSR303。前端

你能get到的知識點?

一、表單驗證的使用
二、因爲表單驗證引發的異常捕獲
在這裏插入圖片描述java

一、引入依賴

使用JSR303,咱們須要引入依賴,通常來講咱們只須要引入javax.validation便可,可是對於一些javax.validation沒法驗證的(例如URL)咱們就須要引入hibernate來進行驗證了。json

<dependency>
     <groupId>javax.validation</groupId>
     <artifactId>validation-api</artifactId>
     <version>2.0.1.Final</version>
 </dependency>
 <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>6.0.18.Final</version>
     <scope>compile</scope>
 </dependency>

二、自定義驗證規則

自定義驗證規則,最方便的莫過於使用註解的方式對咱們的bean進行驗證,而且能夠返回咱們本身定義的返回消息。後端

JSR註釋:api

  • @NotNull –驗證帶註釋的屬性值不爲 null
  • @AssertTrue –驗證帶註釋的屬性值爲 true
  • @Size –驗證帶註釋的屬性值的大小介於屬性 min和 max之間;能夠應用於 String, Collection, Map和數組屬性
  • @Min – v驗證帶註釋的屬性的值不小於 value屬性
  • @Max –驗證帶註釋的屬性的值不大於 value屬性
  • @Email –驗證帶註釋的屬性是有效的電子郵件地址
    一些註釋接受其餘屬性,可是message屬性是全部這些屬性共有的。這是一般在相應屬性的值未經過驗證時呈現的消息。

在JSR中能夠找到一些其餘註釋:數組

  • @NotEmpty –驗證屬性不爲null或爲空;能夠應用於 String, Collection, Map或 Array值
  • @NotBlank –只能應用於文本值,並驗證該屬性不是null仍是空格
  • @Positive和 @PositiveOrZero –適用於數值並驗證其嚴格爲正,或包含0的正數
  • @Negative和 @NegativeOrZero –適用於數字值並驗證其嚴格爲負數,或包含0的負數
  • @Past和 @PastOrPresent –驗證日期值是過去仍是如今(包括如今);能夠應用於日期類型,包括Java 8中添加的日期類型
  • @Future和@FutureOrPresent –驗證日期值是未來的日期仍是未來的日期(包括如今)
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 品牌id
	 */
	@TableId
	private Long brandId;
	/**
	 * 品牌名
	 */
	@NotEmpty(message = "品牌名不能爲空")
	private String name;
	/**
	 * 品牌logo地址
	 */
	@URL(message = "必須是一個合法的地址")
	private String logo;
	/**
	 * 介紹
	 */
	@NotEmpty(message = "介紹不能爲空")
	private String descript;
	/**
	 * 顯示狀態[0-不顯示;1-顯示]
	 */
	private Integer showStatus;
	/**
	 * 檢索首字母
	 */
	@NotEmpty(message = "檢索首字母不能爲空")
	@Pattern(regexp = "/^[a-zA-Z]$/",message = "檢索必須是一個字母")
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull(message = "排序不能爲空")
	@Min(value = 0,message = "排序的數必須大於等於零")
	private Integer sort;

}

三、校驗捕獲異常錯誤

第一種:controller捕獲

在對bean進行驗證後,咱們須要捕獲咱們的驗證結果。app

  1. @Valid:首先使用@Valid 爲驗證級聯標記屬性、方法參數或方法返回類型。也就是說咱們使用這個註解後驗證才生效。
  2. BindingResult:在驗證的bean後緊跟BindingResult,用於獲取咱們的驗證結果,使用result.hasErrors()判斷是否有異常,使用 result.getFieldErrors()獲取驗證後的詳細數據
  3. R:咱們經常使用JSon數據來進行先後端的數據發送與接收,這裏同理,該R爲自定的類,若是你不想寫自定義的消息類,你能夠直接用JSONObject進行數據的保存。
/**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
        Map<String,String> map = new LinkedHashMap<>();
        if (result.hasErrors()){
            result.getFieldErrors().forEach(item ->{
                String message = item.getDefaultMessage();
                String field = item.getField();
                map.put(field, message);
            });
            return R.error(400,"數據不合法").put("data",map);
        }else {
            brandService.save(brand);
            return R.ok();
        }
    }

第二種:統一異常捕獲

全部的controller製做廠的邏輯處理,咱們則須要使用一個統一的controller進行全部異常的捕獲測試

一、正常的控制器處理正常的邏輯
    /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand){
            brandService.save(brand);
            return R.ok();
    }
    
二、編寫一個controllerAdvice進行異常統一處理

@RestControllerAdvice("com.lomtom.mall.product.controller")
public class ExceptionController {

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleValidException(MethodArgumentNotValidException e){
        BindingResult result = e.getBindingResult();
        Map<String,String> map = new LinkedHashMap<>();
        result.getFieldErrors().forEach(item -> {
            String message = item.getDefaultMessage();
            String field = item.getField();
            map.put(field, message);
        });
        return R.error(400, "數據不合法").put("data", map);
    }
}

第三種:統一處理配合枚舉

與第二種同理,只是新增枚舉統一管理異常的狀態碼與消息提醒,翻遍代碼的修改與查看this

一、編寫枚舉
public enum ExceptionEnum {
    DATA_EXCEPTION(400,"數據不合法");

    private Integer code;
    private String message;

    ExceptionEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }


    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
二、與第二種惟一不一樣的是全部的狀態碼與消息提示交給枚舉
return R.error(ExceptionEnum.DATA_EXCEPTION.getCode(), ExceptionEnum.DATA_EXCEPTION.getMessage()).put("data", map);

四、測試

發送請求獲取返回,全部的返回結果都同樣,只是實現的方式稍有不一樣而已。hibernate

{
    "msg": "數據不合法",
    "code": 400,
    "data": {
        "name": "品牌名不能爲空",
        "descript": "介紹不能爲空",
        "sort": "排序不能爲空",
        "firstLetter": "檢索首字母不能爲空"
    }
}

關注公衆號:博奧思園
仍是那句話:你的支持是我前進的最大動力

相關文章
相關標籤/搜索