欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Boot中使用JSR-303實現(xiàn)請求參數(shù)校驗

 更新時間:2023年10月26日 16:07:35   作者:Miaow.Y.Hu  
這篇文章主要介紹了Spring Boot中使用JSR-303實現(xiàn)請求參數(shù)校驗,JSR-303校驗我們一般都是對Java的實體類對象進行校驗,主要檢驗JSR-303是Java中的一個規(guī)范,用于實現(xiàn)請求參數(shù)校驗在我們的實體類對象的屬性上,感興趣的朋友跟隨小編一起看看吧

JSR-303是Java中的一個規(guī)范,用于實現(xiàn)請求參數(shù)校驗。它定義了一組注解,可以應(yīng)用于JavaBean的字段上,用于驗證輸入?yún)?shù)的合法性。下面是一些常用的JSR-303注解及其介紹:

@NotNull:用于驗證字段值不能為null。
@NotEmpty:用于驗證字符串字段不能為空。
@NotBlank:用于驗證字符串字段不能為空,并且長度必須大于0。
@Min:用于驗證數(shù)字字段的最小值。
@Max:用于驗證數(shù)字字段的最大值。
@Size:用于驗證字符串、集合或數(shù)組字段的長度或大小。
@Pattern:用于驗證字符串字段是否匹配指定的正則表達式。
@Email:用于驗證字符串字段是否符合Email格式。
@Range:用于驗證數(shù)字字段的取值范圍。
@Valid:用于嵌套驗證,可以對對象中的字段進行遞歸驗證。
其他如下圖所示:

通過在JavaBean的字段上添加這些注解,可以在接收請求參數(shù)時進行自動校驗。如果校驗失敗,可以通過異常處理機制來處理校驗錯誤。

需要注意的是,JSR-303只提供了基本的驗證注解,如果需要更復(fù)雜的校驗邏輯,可以自定義注解或使用第三方庫,如Hibernate Validator等。
Hibernate Validator附加的constraint:

至于我們?yōu)樯妒褂肑SR-303來校驗我們的參數(shù),主要是為了解決我們在實際開發(fā)過程中,前后端的參數(shù)校驗導(dǎo)致的問題。比如:

  • 我們依靠前端框架解決參數(shù)校驗,但是缺少服務(wù)器的參數(shù)校驗,這種情況常見于需要同時進行開發(fā)前后端的時候,雖然程序的正常使用不會有問題,到那時開發(fā)者會忽略非正常的操作,比如繞過前端程序,直接模擬客戶端請求,這樣就繞過了我們對前端預(yù)設(shè)的各種限制,直擊我們后端的數(shù)據(jù)訪問接口,進而使得我們的后端系統(tǒng)存在嚴重的安全隱患。
  • 大量的利用if/else語句嵌套實現(xiàn),使得我們的校驗邏輯晦澀難懂,并不利于我們對整個系統(tǒng)的維護。

JSR的定義標準

驗證觸發(fā)時機:

  • JSR-303校驗標準定義了兩個觸發(fā)校驗的時機:
    • 在對象被持久化之前(例如,保存到數(shù)據(jù)庫之前)。
    • 在對象被修改之后(例如,更新數(shù)據(jù)庫中的記錄后)。
  • 校驗約束注解:JSR-303標準提供了一組注解,可以用于對Java對象的屬性進行校驗。這些注解包括但不限于@NotNull、@NotEmpty@Min、@Max@Size、@Pattern、@Email 等。開發(fā)人員可以根據(jù)需求選擇適當?shù)淖⒔鈦矶x校驗規(guī)則。
  • 校驗組:JSR-303允許將校驗規(guī)則分組,以便在特定情況下選擇性地執(zhí)行校驗。開發(fā)人員可以為每個校驗注解指定一個或多個校驗組,然后在校驗時選擇要執(zhí)行的校驗組。
  • 嵌套校驗:JSR-303允許對復(fù)雜對象進行嵌套校驗,即在校驗一個對象時,也會對其關(guān)聯(lián)的其他對象進行校驗。這樣可以確保整個對象圖的完整性和合法性。
  • 自定義校驗:JSR-303還允許開發(fā)人員定義自己的校驗注解和校驗器,以滿足特定的校驗需求。通過實現(xiàn) ConstraintValidator 接口來自定義校驗器,并在自定義注解中使用該校驗器。
  • 校驗結(jié)果:JSR-303校驗結(jié)果以校驗異常的形式返回。當校驗失敗時,會拋出 ConstraintViolationException 異常,其中包含了校驗失敗的詳細信息,例如校驗失敗的屬性、校驗失敗的值、校驗錯誤消息等。

接下來我們將圍繞我們在Spring Boot的實體類中,使用JSR-303校驗。值得注意的是,JSR-303校驗我們一般都是對Java的實體類對象進行校驗,主要檢驗在我們的實體類對象的屬性上。

還是利用我們==>上一篇 <===的相關(guān)依賴文件,這篇我就不在重復(fù)導(dǎo)入相關(guān)依賴文件了。本篇著重文件主要正在User類和UserController,所用的依賴pom.xml文件和application.properties均與上篇一樣,就不在重復(fù)描述了。

PS: 你可以看到我在依賴中均采用了lombok,但是我卻并未使用這個玩意,原因在于,我使用了lombok

@ApiModel(description = "用戶實體")
public class User {
    @ApiModelProperty("用戶編號")
    private Long id;
    @NotNull //校驗定義的字段不能為空
    @Size(min = 2, max = 5)
    @ApiModelProperty("用戶姓名")
    private String name;
    @NotNull
    @Max(100)
    @Min(10)
    @ApiModelProperty("用戶年齡")
    private Integer age;
    @NotNull
    @Email
    @ApiModelProperty("用戶郵箱")
    private String email;
    public User(Long id, String name, Integer age, String email) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.email = email;
    }
    public User() {
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", email='" + email + '\'' +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(age, user.age) && Objects.equals(email, user.email);
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, name, age, email);
    }
}
@Api(tags = "用戶管理")
@RestController
@RequestMapping(value = "/users")     // 通過這里配置使下面的映射都在/users下
public class UserController {
    // 創(chuàng)建線程安全的Map,模擬users信息的存儲
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
    @GetMapping("/")
    @ApiOperation(value = "獲取用戶列表")
    public List<User> getUserList() {
        List<User> r = new ArrayList<>(users.values());
        return r;
    }
    @PostMapping("/")
    @ApiOperation(value = "創(chuàng)建用戶", notes = "根據(jù)User對象創(chuàng)建用戶")
    public String postUser(@Valid @RequestBody User user) {
        users.put(user.getId(), user);
        return "success";
    }
    @GetMapping("/{id}")
    @ApiOperation(value = "獲取用戶詳細信息", notes = "根據(jù)url的id來獲取用戶詳細信息")
    public User getUser(@PathVariable Long id) {
        return users.get(id);
    }
    @PutMapping("/{id}")
    @ApiImplicitParam(paramType = "path", dataType = "Long", name = "id", value = "用戶編號", required = true, example = "1")
    @ApiOperation(value = "更新用戶詳細信息", notes = "根據(jù)url的id來指定更新對象,并根據(jù)傳過來的user信息來更新用戶詳細信息")
    public String putUser(@PathVariable Long id, @RequestBody User user) {
        User u = users.get(id);
        u.setName(user.getName());
        u.setAge(user.getAge());
        users.put(id, u);
        return "success";
    }
    @DeleteMapping("/{id}")
    @ApiOperation(value = "刪除用戶", notes = "根據(jù)url的id來指定刪除對象")
    public String deleteUser(@PathVariable Long id) {
        users.remove(id);
        return "success";
    }
}

接下來啟動項目,當然啟動類還是需要加:
@EnableSwagger2Doc這個注解

之后,我們可以通過使用相關(guān)工具比如Postman等測試工具發(fā)起,也可以使用curl發(fā)起,比如:

curl -X POST \
  http://localhost:8080/users/ \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: 114db0f0-bdce-4ba5-baf6-01e5104a68a3' \
  -H 'cache-control: no-cache' \
  -d '{
    "name": "abcdefg",
    "age": 8,
    "email": "aaaa"
}'

得到相關(guān)信息:

{
    "timestamp": "2019-10-05T06:24:30.518+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Size.user.name",
                "Size.name",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.name",
                        "name"
                    ],
                    "arguments": null,
                    "defaultMessage": "name",
                    "code": "name"
                },
                5,
                2
            ],
            "defaultMessage": "個數(shù)必須在2和5之間",
            "objectName": "user",
            "field": "name",
            "rejectedValue": "abcdefg",
            "bindingFailure": false,
            "code": "Size"
        },
        {
            "codes": [
                "Min.user.age",
                "Min.age",
                "Min.java.lang.Integer",
                "Min"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.age",
                        "age"
                    ],
                    "arguments": null,
                    "defaultMessage": "age",
                    "code": "age"
                },
                10
            ],
            "defaultMessage": "最小不能小于10",
            "objectName": "user",
            "field": "age",
            "rejectedValue": 8,
            "bindingFailure": false,
            "code": "Min"
        },
        {
            "codes": [
                "Email.user.email",
                "Email.email",
                "Email.java.lang.String",
                "Email"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.email",
                        "email"
                    ],
                    "arguments": null,
                    "defaultMessage": "email",
                    "code": "email"
                },
                [],
                {
                    "defaultMessage": ".*",
                    "codes": [
                        ".*"
                    ],
                    "arguments": null
                }
            ],
            "defaultMessage": "不是一個合法的電子郵件地址",
            "objectName": "user",
            "field": "email",
            "rejectedValue": "aaaa",
            "bindingFailure": false,
            "code": "Email"
        }
    ],
    "message": "Validation failed for object='user'. Error count: 3",
    "path": "/users/"
}

其中返回名稱的各參數(shù)含義如下:

timestamp:請求時間
status:HTTP返回的狀態(tài)碼,這里返回400,即:請求無效、錯誤的請求,通常參數(shù)校驗不通過均為400
error:HTTP返回的錯誤描述,這里對應(yīng)的就是400狀態(tài)的錯誤描述:Bad Request
errors:具體錯誤原因,是一個數(shù)組類型;因為錯誤校驗可能存在多個字段的錯誤,比如這里因為定義了兩個參數(shù)不能為Null,所以存在兩條錯誤記錄信息
message:概要錯誤消息,返回內(nèi)容中很容易可以知道,這里的錯誤原因是對user對象的校驗失敗,其中錯誤數(shù)量為2,而具體的錯誤信息就定義在上面的errors數(shù)組中
path:請求路徑

從errors數(shù)組中各個錯誤明細,知道各個字段的defaultMessage,可以看到很清晰的錯誤描述。

瀏覽器訪問:
http://localhost:8080/swagger-ui.html

我們可以看到校驗的部分限制。

到此這篇關(guān)于Spring Boot中使用JSR-303實現(xiàn)請求參數(shù)校驗的文章就介紹到這了,更多相關(guān)springboot JSR-303請求參數(shù)校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring的異常處理@ExceptionHandler注解解析

    Spring的異常處理@ExceptionHandler注解解析

    這篇文章主要介紹了Spring的異常處理@ExceptionHandler注解解析,當一個Controller中有方法加了@ExceptionHandler之后,這個Controller其他方法中沒有捕獲的異常就會以參數(shù)的形式傳入加了@ExceptionHandler注解的那個方法中,需要的朋友可以參考下
    2023-12-12
  • Java+Swing實現(xiàn)醫(yī)院管理系統(tǒng)的完整代碼

    Java+Swing實現(xiàn)醫(yī)院管理系統(tǒng)的完整代碼

    這篇文章主要介紹了Java+Swing實現(xiàn)醫(yī)院管理系統(tǒng)的完整代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • Springboot整合分頁插件PageHelper步驟解析

    Springboot整合分頁插件PageHelper步驟解析

    這篇文章主要介紹了Springboot整合分頁插件PageHelper步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • Java ClassCastException異常解決方案

    Java ClassCastException異常解決方案

    這篇文章主要介紹了Java ClassCastException異常解決方案,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java類加載基本過程詳細介紹

    Java類加載基本過程詳細介紹

    這篇文章主要介紹了Java類加載基本過程詳細介紹的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • java聯(lián)系人管理系統(tǒng)簡單設(shè)計

    java聯(lián)系人管理系統(tǒng)簡單設(shè)計

    這篇文章主要為大家詳細介紹了java聯(lián)系人管理系統(tǒng)簡單設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Java Selenium實現(xiàn)多窗口切換的示例代碼

    Java Selenium實現(xiàn)多窗口切換的示例代碼

    這篇文章主要介紹了Java Selenium實現(xiàn)多窗口切換的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 詳解Java實現(xiàn)拓撲排序算法

    詳解Java實現(xiàn)拓撲排序算法

    拓撲排序,很多人都可能聽說但是不了解的一種算法?;蛟S很多人只知道它是圖論的一種排序,至于干什么的不清楚。又或許很多人可能還會認為它是一種啥排序。而實質(zhì)上它是對有向圖的頂點排成一個線性序列
    2021-06-06
  • Java在線打開word文檔并強制留痕的方法

    Java在線打開word文檔并強制留痕的方法

    在本篇文章里小編給讀者們分享的是關(guān)于Java在線打開word文檔并強制留痕的方法,對此有需要的朋友們可以學(xué)習(xí)下。
    2020-01-01
  • Spring注解之@Conditional使用解析

    Spring注解之@Conditional使用解析

    這篇文章主要介紹了Spring注解之@Conditional使用解析,@Conditional注解可以說是SpringBoot的條件注解,表示組件只有在所有指定條件都匹配時才有資格注冊,條件是可以在 bean 定義注冊之前??以編程方式確定的任何狀態(tài),需要的朋友可以參考下
    2024-01-01

最新評論