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

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

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

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

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

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

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

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

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

JSR的定義標(biāo)準(zhǔn)

驗(yàn)證觸發(fā)時(shí)機(jī):

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

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

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

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

@ApiModel(description = "用戶實(shí)體")
public class User {
    @ApiModelProperty("用戶編號")
    private Long id;
    @NotNull //校驗(yàn)定義的字段不能為空
    @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 = "獲取用戶詳細(xì)信息", notes = "根據(jù)url的id來獲取用戶詳細(xì)信息")
    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 = "更新用戶詳細(xì)信息", notes = "根據(jù)url的id來指定更新對象,并根據(jù)傳過來的user信息來更新用戶詳細(xì)信息")
    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";
    }
}

接下來啟動(dòng)項(xiàng)目,當(dāng)然啟動(dòng)類還是需要加:
@EnableSwagger2Doc這個(gè)注解

之后,我們可以通過使用相關(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": "個(gè)數(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": "不是一個(gè)合法的電子郵件地址",
            "objectName": "user",
            "field": "email",
            "rejectedValue": "aaaa",
            "bindingFailure": false,
            "code": "Email"
        }
    ],
    "message": "Validation failed for object='user'. Error count: 3",
    "path": "/users/"
}

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

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

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

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

我們可以看到校驗(yàn)的部分限制。

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

相關(guān)文章

  • Java在線打開word文檔并強(qiáng)制留痕的方法

    Java在線打開word文檔并強(qiáng)制留痕的方法

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

    Spring注解之@Conditional使用解析

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