中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot如何通過自定義注解實現參數校驗

發布時間:2022-12-27 17:31:30 來源:億速云 閱讀:191 作者:iii 欄目:開發技術

今天小編給大家分享一下SpringBoot如何通過自定義注解實現參數校驗的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

1. 為什么要進行參數校驗

在后端進行工作時,需要接收前端傳來的數據去數據庫查詢,但是如果有些數據過于離譜,我們就可以直接把它pass掉,不讓這種垃圾數據接觸數據庫,減小數據庫的壓力。

有時候會有不安分的人通過一些垃圾數據攻擊咱們的程序,讓咱們的服務器或數據庫崩潰,這種攻擊雖然低級但不得不防,就像QQ進行登錄請求時,它們向后端發送 賬號=123,密碼=123 的數據,一秒鐘還發1w次,這很明顯就是找事的好吧,什么人類的手速能達到1秒1萬次?

解決方法是:一方面我們可以通過Redis記錄ip/賬號的方式拒絕一部分請求,例如1s中同一個ip/賬號最多請求100次。另一方面就是進行數據校驗pass一部分數據,這100里又多少次是垃圾數據。這樣就可以盡量減小服務器數據庫的壓力。

2. 如何實現參數校驗

實現參數校驗說實話方式還挺多,個人使用過直接在Controller代碼里面寫、AOP+自定義注解、ConstraintValidator。本篇博客講的是ConstraintValidator實現。

直接在Controller代碼里面寫,說實話,寫起來是簡單,但是臃腫,耦合性高,最主要是,不夠優雅。

AOP實現有難度,代碼繁瑣,顯得邏輯雜亂。

所以我建議使用ConstraintValidator

在這里先提供一個工具類進行參數校驗,提供了對于手機號、郵箱、驗證碼、密碼、身份證號的驗證方法,可以直接copy來用。等下進行參數校驗時我使用的就是這個類里的校驗方法。

/**
 * @description : 驗證手機號、身份證號、密碼、驗證碼、郵箱的工具類
 * @author : 小何
 */
public class VerifyUtils {
    /**
     * 手機號正則
     */
    public static final String PHONE_REGEX = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";

    /**
     * 郵箱正則
     */
    public static final String EMAIL_REGEX = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";

    /**
     * 密碼正則。4~32位的字母、數字、下劃線
     */
    public static final String PASSWORD_REGEX = "^\\w{4,32}$";

    /**
     * 驗證碼正則, 6位數字或字母
     */
    public static final String VERIFY_CODE_REGEX = "^[a-zA-Z\\d]{6}$";

    /**
     * 身份證號正則
     */
    public static final String ID_CARD_NUMBER_REGEX_18 = "^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
    public static final String ID_CARD_NUMBER_REGEX_15 = "^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{2}$";


    /**
     * 手機號是否合法
     * @param phone 要校驗的手機號
     * @return true:符合,false:不符合
     */
    public static boolean isPhoneLegal(String phone){
        return match(phone, PHONE_REGEX);
    }
    /**
     * 是否是無效郵箱格式
     * @param email 要校驗的郵箱
     * @return true:符合,false:不符合
     */
    public static boolean isEmailLegal(String email){
        return match(email, EMAIL_REGEX);
    }

    /**
     * 是否是無效驗證碼格式
     * @param code 要校驗的驗證碼
     * @return true:符合,false:不符合
     */
    public static boolean isCodeLegal(String code){
        return match(code, VERIFY_CODE_REGEX);
    }

    // 校驗是否不符合正則格式
    private static boolean match(String str, String regex){
        if (str == null || "".equals(str)) {
            return false;
        }
        return str.matches(regex);
    }

    /**
     * 驗證身份證號是否合法
     * @param idCard 身份證號
     * @return true: 合法;    false:不合法
     */
    public static boolean isIdCardLegal(String idCard) {
        if (idCard.length() == 18) {
            return match(idCard, ID_CARD_NUMBER_REGEX_18);
        } else {
            return match(idCard, ID_CARD_NUMBER_REGEX_15);
        }
    }
}

使用案例:

public static void main(String[] args) {
    String phone = "15039469595";
    boolean phoneLegal = VerifyUtils.isPhoneLegal(phone);
    System.out.println(phoneLegal);
}

3. 注解實現參數校驗

首先導入依賴:

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

導入依賴后可以嘗試使用一下它自帶的參數校驗注解:@NotNull 非空校驗

先來說一下這注解實現參數校驗的使用步驟。

在平時寫的demo中,本人比較喜歡對接口另外定義vo來接收數據,例如前端傳的數據是user對象里的username和password,我們的user里有很多字段,如果單純使用user就太浪費了,而且如果直接在實體類上進行自定義注解會對實體類造成代碼污染。所以個人認為定義vo類是很有必要的。

以下是我的登錄接口:

@PostMapping("/login")
public String login(@RequestBody @Validated LoginVo user) {

    return "user:" + user.toString();
}

以下是我登錄接口的vo類:

@Data
public class LoginVo {
    // 郵箱
    @NotNull(message = "郵箱不能為空")
    private String email;
    // 密碼
    private String password;
}

大家可能注意到我多寫了兩個注解:@Validated@NotNull(message = “郵箱不能為空”)

對,使用注解進行參數校驗就分為兩步:

  • 在需要進行校驗的字段上加對應校驗方式,如@NotNull

  • 在需要進行校驗的接口參數前加@Validated,告訴Spring,這個類你給我看一下,里面有的字段加了校驗注解,符合要求就放行,不符合要求就報錯。

如圖所示:

SpringBoot如何通過自定義注解實現參數校驗

SpringBoot如何通過自定義注解實現參數校驗

使用postman發起請求,故意使得郵箱為空:

SpringBoot如何通過自定義注解實現參數校驗

會發現報錯:

Resolved [org.springframework.web.bind.MethodArgumentNotValidException: 
Validation failed for argument [0] in public java.lang.String com.example.demo.controller.UserController.login(com.example.demo.domain.vo.LoginVo): 
[Field error in object 'loginVo' on field 'email': rejected value [null]; codes [NotNull.loginVo.email,NotNull.email,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [loginVo.email,email]; arguments []; 
default message [email]]; 
default message [郵箱不能為空]] ]

出現這個異常:MethodArgumentNotValidException,我們就可以在全局異常處理器中捕獲它,返回一個較為規范的信息。

4. 自定義注解實現參數校驗

學習了如何使用注解進行參數校驗,我們就可以進行接下來的工作:自定義注解。

由于需求的復雜,我們現在需要完成注冊接口,注冊時需要身份證號、電話號碼、郵箱、密碼,這些字段的注解校驗Spring并沒有幫我們實現,此時就需要DIY注解滿足需求。

如何實現自定義注解?我們先模仿,先來看看@NotNull注解里面有什么:

SpringBoot如何通過自定義注解實現參數校驗

@Target、@Retention、@Repeatable、@Documented這些常用的注解就不再解釋,

@Constraint:表示此注解是一個參數校驗的注解,validateBy指定校驗規則實現類,這里需要填實現類.class。

各個字段的含義:

  • message :數據不符合校驗規則后的報錯信息。可以是字符串也可以是文件,如果校驗字段較多,建議實現文件形式。

  • groups :指定注解使用場景,例如新增、刪除

  • payload :往往對Bean使用

以上這三個字段都是必須的,每一個使用ConstraintValidator完成參數校驗都要有這三個字段。

后面的那個List是NotNull專屬的,所以不必關心。

那么我們大可以模仿@NotNull來實現自定義注解。

第一步:實現校驗類:

需要實現一個接口:ConstraintValidator<?, ?>

# ConstraintValidator<?, ?>

第一個參數是自定義注解

第二個參數是需要進行校驗的數據的數據類型

例如想對手機號校驗,第一個參數是Phone,第二個參數是String

這個接口提供了一個方法:

boolean isValid(T value, ConstraintValidatorContext context);

第一個參數就是前端傳來的數據。我們可以對這個數據進行判斷,返回一個布爾值

public class VerifyPhone implements ConstraintValidator<Phone, String> {

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
       // 判斷手機號是否合法
        return VerifyUtils.isPhoneLegal(s);
    }
}

第二步:實現注解,這個注解的名稱需要與ConstraintValidator的第一個參數保持一致。

特別注意的是,@Constraint注解里面的validatedBy的值是第一步的Class實例。

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = {VerifyPhone.class}
)
public @interface Phone {
    boolean isRequired() default false;

    String message() default "手機號格式錯誤";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

第三步:在字段上加上相應注解。

@Data
public class RegisterVo {
    private String name;
    // 身份證號
    private String id;
    // 電話號碼
    @Phone
    private String phone;
    // 郵箱
    private String email;
    // 密碼
    private String password;
}

第四步:在參數前加上@Validated

@PutMapping("/register")
public String register(@RequestBody @Validated RegisterVo user) {
    return "user: " + user.toString();
}

這樣一來,就優雅的實現了參數校驗。別以為我們搞這么多類很麻煩,除非你想每一個controller里都這樣寫:

@PutMapping("/register")
public String register(@RequestBody @Validated RegisterVo user) {
    if (VerifyUtils.isPhoneLegal("xxx")) {
        return "手機號格式錯誤";
    }
    if (VerifyUtils.isCodeLegal("xxx")) {
        return "驗證碼格式錯誤";
    }
    if (VerifyUtils.isIdCardLegal("xxx")) {
        return "身份證格式錯誤";
    }
    if (VerifyUtils.isEmailLegal("xxx")) {
        return "郵箱格式錯誤";
    }
    return "user: " + user.toString();
}

真的很low很麻煩好嗎。

可能步驟有點繁瑣,不過也就4步,畫張圖加強一下記憶:

SpringBoot如何通過自定義注解實現參數校驗

以上就是“SpringBoot如何通過自定義注解實現參數校驗”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

同德县| 衡阳县| 黑河市| 曲阳县| 天津市| 永川市| 千阳县| 中宁县| 威海市| 通河县| 错那县| 繁峙县| 疏勒县| 安国市| 宜阳县| 宁陵县| 綦江县| 赤水市| 莎车县| 台江县| 和政县| 澄城县| 昌吉市| 龙陵县| 聂荣县| 广东省| 平潭县| 依安县| 宜兰市| 石渠县| 建始县| 江源县| 和田市| 滕州市| 昌平区| 南郑县| 鄄城县| 凉山| 太湖县| 涞水县| 武陟县|