成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

還在用 if 硬剛參數(shù)校驗(yàn)?這波操作土到掉渣!SpringBoot 高階玩法直接封神

開(kāi)發(fā) 前端
使用 Spring Validation,我們可以大大減少重復(fù)的 if 語(yǔ)句,讓代碼更加簡(jiǎn)潔明了,校驗(yàn)邏輯和業(yè)務(wù)邏輯分離,提高代碼的可維護(hù)性和可復(fù)用性。自定義校驗(yàn)功能更是讓我們能夠應(yīng)對(duì)各種復(fù)雜的業(yè)務(wù)需求,打造專屬的校驗(yàn)規(guī)則。全局異常處理則讓錯(cuò)誤處理更加統(tǒng)一、規(guī)范,提升整個(gè)系統(tǒng)的健壯性。

兄弟們,有一個(gè)現(xiàn)象特別有意思:新手寫代碼的時(shí)候,特別喜歡用 if 語(yǔ)句來(lái)做參數(shù)校驗(yàn),一頓操作猛如虎,代碼寫得像瀑布。老手呢,雖然知道這樣不好,但有時(shí)候?yàn)榱粟s進(jìn)度,也不得不繼續(xù)用這種 “土方法”。咱就是說(shuō),難道就沒(méi)有更優(yōu)雅、更高效的辦法嗎?當(dāng)然有啦!今天咱就來(lái)聊聊 Spring Boot 里那些能讓參數(shù)校驗(yàn)直接 “封神” 的高階玩法。

一、傳統(tǒng)參數(shù)校驗(yàn):土味十足的 “體力活”

先說(shuō)說(shuō)大家最熟悉的傳統(tǒng)參數(shù)校驗(yàn)吧。假設(shè)咱們有一個(gè)用戶注冊(cè)的接口,需要校驗(yàn)用戶名、手機(jī)號(hào)、郵箱等參數(shù)。按照傳統(tǒng)做法,那就是在方法里瘋狂寫 if 語(yǔ)句:

public User register(String username, String phone, String email) {
    if (username == null || username.trim().length() < 3 || username.trim().length() > 20) {
        throw new IllegalArgumentException("用戶名長(zhǎng)度必須在3到20之間");
    }
    if (phone == null || !phone.matches("^1[3-9]\\d{9}$")) {
        throw new IllegalArgumentException("手機(jī)號(hào)格式不正確");
    }
    if (email == null || !email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
        throw new IllegalArgumentException("郵箱格式不正確");
    }
    // 接下來(lái)是業(yè)務(wù)邏輯
    User user = new User();
    user.setUsername(username);
    user.setPhone(phone);
    user.setEmail(email);
    return userService.save(user);
}

這樣的代碼看起來(lái)是不是特別 “樸實(shí)無(wú)華”?但問(wèn)題可不少。首先,代碼冗余度極高,每個(gè)參數(shù)都要寫好幾行校驗(yàn)邏輯,要是參數(shù)多一點(diǎn),整個(gè)方法就變得又長(zhǎng)又臭,跟裹腳布似的。其次,維護(hù)起來(lái)特別麻煩,要是哪天需求變了,比如用戶名長(zhǎng)度限制改了,你得在所有用到這個(gè)校驗(yàn)的地方都改一遍,稍有不慎就會(huì)漏掉,埋下 bug 的隱患。而且,這種校驗(yàn)邏輯和業(yè)務(wù)邏輯混在一起,顯得特別混亂,就像把菜湯和米飯攪在一起吃,看著就鬧心。

再?gòu)拇a的可復(fù)用性來(lái)說(shuō),如果你在多個(gè)地方都需要校驗(yàn)手機(jī)號(hào),難道每次都要把那段正則表達(dá)式和 if 語(yǔ)句復(fù)制粘貼一遍嗎?這也太 low 了吧,完全不符合咱們程序員 “DRY(Don't Repeat Yourself)” 的原則。而且,這種土味校驗(yàn)方法對(duì)于復(fù)雜的業(yè)務(wù)場(chǎng)景根本招架不住,比如需要多個(gè)參數(shù)之間相互校驗(yàn),或者需要結(jié)合數(shù)據(jù)庫(kù)查詢來(lái)做校驗(yàn),這時(shí)候 if 語(yǔ)句就顯得力不從心了,就像讓一個(gè)小學(xué)生去解高考數(shù)學(xué)題,根本搞不定。

二、Spring Validation:參數(shù)校驗(yàn)的 “正規(guī)軍”

好在 Spring 框架為我們提供了一套強(qiáng)大的參數(shù)校驗(yàn)機(jī)制 ——Spring Validation,它就像是參數(shù)校驗(yàn)領(lǐng)域的 “正規(guī)軍”,讓我們告別土味的 if 語(yǔ)句,走向優(yōu)雅開(kāi)發(fā)的道路。

(一)基本用法:注解加持,簡(jiǎn)潔高效

Spring Validation 主要通過(guò)一系列的注解來(lái)實(shí)現(xiàn)參數(shù)校驗(yàn),這些注解可以直接加在方法的參數(shù)上,或者加在實(shí)體類的字段上。咱們先來(lái)看一個(gè)簡(jiǎn)單的例子,還是以用戶注冊(cè)為例,這次我們用實(shí)體類來(lái)接收參數(shù):

public class UserRegisterForm {
    @NotBlank(message = "用戶名不能為空")
    @Size(min = 3, max = 20, message = "用戶名長(zhǎng)度必須在3到20之間")
    private String username;
    @NotBlank(message = "手機(jī)號(hào)不能為空")
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手機(jī)號(hào)格式不正確")
    private String phone;
    @NotBlank(message = "郵箱不能為空")
    @Email(message = "郵箱格式不正確")
    private String email;
    // 省略 getter 和 setter 方法
}

然后在控制器的方法里,加上 @Valid 注解來(lái)開(kāi)啟參數(shù)校驗(yàn):

@PostMapping("/register")
public ResponseEntity<?> register(@Valid @RequestBody UserRegisterForm form, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        List<String> errorMessages = bindingResult.getAllErrors().stream()
               .map(ObjectError::getDefaultMessage)
               .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(errorMessages);
    }
    // 業(yè)務(wù)邏輯
    User user = new User();
    user.setUsername(form.getUsername());
    user.setPhone(form.getPhone());
    user.setEmail(form.getEmail());
    userService.save(user);
    return ResponseEntity.ok().build();
}

你看,這樣一來(lái),代碼是不是清爽多了?原來(lái)需要好幾行 if 語(yǔ)句才能完成的校驗(yàn),現(xiàn)在只需要在實(shí)體類的字段上加上對(duì)應(yīng)的注解就行了,校驗(yàn)邏輯和業(yè)務(wù)邏輯也分開(kāi)了,再也不用像以前那樣 “糾纏不清”。而且這些注解都是 Spring 自帶的,常用的校驗(yàn)場(chǎng)景基本都能覆蓋,比如 @NotNull 用于非空校驗(yàn),@Min 和 @Max 用于數(shù)值范圍校驗(yàn),@Email 專門用于郵箱格式校驗(yàn),簡(jiǎn)直不要太方便。

(二)分組校驗(yàn):不同場(chǎng)景,精準(zhǔn)校驗(yàn)

在實(shí)際開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到這樣的情況:同一個(gè)實(shí)體類在不同的業(yè)務(wù)場(chǎng)景下,需要校驗(yàn)的參數(shù)不一樣。比如用戶注冊(cè)時(shí),需要校驗(yàn)所有的必填字段,而用戶修改個(gè)人信息時(shí),可能有些字段是允許為空的。這時(shí)候,分組校驗(yàn)就派上用場(chǎng)了。

Spring Validation 支持分組校驗(yàn),我們可以通過(guò)定義不同的分組接口,來(lái)指定不同場(chǎng)景下需要校驗(yàn)的字段。首先,定義一個(gè)分組接口:

public interface RegisterGroup {
}
public interface UpdateGroup {
}

然后在實(shí)體類的字段上指定分組:

public class UserForm {
    @NotBlank(message = "用戶名不能為空", groups = {RegisterGroup.class})
    private String username;
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手機(jī)號(hào)格式不正確", groups = {RegisterGroup.class, UpdateGroup.class})
    private String phone;
    @Email(message = "郵箱格式不正確", groups = {UpdateGroup.class})
    private String email;
    // 省略 getter 和 setter 方法
}

在控制器方法中,指定需要校驗(yàn)的分組:

@PostMapping("/register")
public ResponseEntity<?> register(@Validated(RegisterGroup.class) @RequestBody UserForm form, BindingResult bindingResult) {
    // 注冊(cè)場(chǎng)景的校驗(yàn)和業(yè)務(wù)邏輯
}
@PutMapping("/update")
public ResponseEntity<?> update(@Validated(UpdateGroup.class) @RequestBody UserForm form, BindingResult bindingResult) {
    // 更新場(chǎng)景的校驗(yàn)和業(yè)務(wù)邏輯
}

這樣,在注冊(cè)場(chǎng)景下,就會(huì)按照 RegisterGroup 分組來(lái)校驗(yàn),用戶名、手機(jī)號(hào)都會(huì)被校驗(yàn);而在更新場(chǎng)景下,就會(huì)按照 UpdateGroup 分組來(lái)校驗(yàn),手機(jī)號(hào)和郵箱會(huì)被校驗(yàn),用戶名允許為空(因?yàn)樵?UpdateGroup 分組中沒(méi)有對(duì)用戶名進(jìn)行校驗(yàn))。分組校驗(yàn)就像是給不同的業(yè)務(wù)場(chǎng)景定制了專屬的校驗(yàn) “套餐”,精準(zhǔn)又高效,再也不用為了不同場(chǎng)景寫不同的實(shí)體類或者重復(fù)寫校驗(yàn)邏輯了,簡(jiǎn)直是開(kāi)發(fā)中的 “貼心小棉襖”。

(三)方法級(jí)校驗(yàn):復(fù)雜邏輯,輕松搞定

雖然字段級(jí)的注解已經(jīng)能滿足大部分的校驗(yàn)需求,但對(duì)于一些復(fù)雜的校驗(yàn)邏輯,比如需要多個(gè)參數(shù)之間相互校驗(yàn),或者需要結(jié)合業(yè)務(wù)邏輯進(jìn)行校驗(yàn),這時(shí)候就需要用到方法級(jí)的校驗(yàn)了。Spring Validation 允許我們?cè)诜椒ㄉ咸砑有r?yàn)注解,或者自定義方法級(jí)的校驗(yàn)邏輯。

比如,我們有一個(gè)訂單創(chuàng)建的方法,需要校驗(yàn)訂單金額和優(yōu)惠金額的關(guān)系,優(yōu)惠金額不能超過(guò)訂單金額,而且訂單金額和優(yōu)惠金額都不能為負(fù)數(shù)。這時(shí)候,我們可以在方法上添加校驗(yàn)邏輯:

public class Order {
    private BigDecimal amount;
    private BigDecimal discount;
    // 省略 getter 和 setter 方法
    @AssertTrue(message = "優(yōu)惠金額不能超過(guò)訂單金額")
    public boolean isDiscountValid() {
        return discount == null || amount == null || discount.compareTo(amount) <= 0;
    }
    @AssertTrue(message = "訂單金額和優(yōu)惠金額不能為負(fù)數(shù)")
    public boolean isAmountNonNegative() {
        return amount == null || amount.compareTo(BigDecimal.ZERO) >= 0 && (discount == null || discount.compareTo(BigDecimal.ZERO) >= 0);
    }
}

然后在控制器方法中,對(duì)訂單對(duì)象進(jìn)行校驗(yàn):

@PostMapping("/orders")
public ResponseEntity<?> createOrder(@Valid @RequestBody Order order, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        // 處理校驗(yàn)錯(cuò)誤
    }
    // 業(yè)務(wù)邏輯
    return ResponseEntity.ok().build();
}

這樣,通過(guò)方法級(jí)的校驗(yàn),我們就可以處理復(fù)雜的參數(shù)之間的關(guān)系校驗(yàn),而不用在控制器方法里寫一堆繁瑣的 if 語(yǔ)句了。方法級(jí)校驗(yàn)就像是一把 “萬(wàn)能鑰匙”,能打開(kāi)復(fù)雜校驗(yàn)場(chǎng)景的大門,讓我們的代碼更加簡(jiǎn)潔、優(yōu)雅。

三、自定義校驗(yàn):打造專屬的校驗(yàn) “神器”

雖然 Spring 自帶的校驗(yàn)注解已經(jīng)很強(qiáng)大了,但在實(shí)際開(kāi)發(fā)中,我們難免會(huì)遇到一些特殊的校驗(yàn)需求,比如校驗(yàn)一個(gè)用戶是否存在于數(shù)據(jù)庫(kù)中,或者校驗(yàn)一個(gè)文件是否符合特定的格式。這時(shí)候,我們就需要自定義校驗(yàn)注解和校驗(yàn)器了,打造屬于自己的校驗(yàn) “神器”。

(一)自定義校驗(yàn)注解:隨心所欲,定義規(guī)則

首先,我們需要定義一個(gè)自定義的校驗(yàn)注解。比如,我們要校驗(yàn)一個(gè)手機(jī)號(hào)是否已經(jīng)被注冊(cè),我們可以定義一個(gè) @UniquePhone 注解:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniquePhoneValidator.class)
public @interface UniquePhone {
    String message() default "手機(jī)號(hào)已被注冊(cè)";

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

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

這里,@Target 注解指定了這個(gè)注解可以用在字段和參數(shù)上,@Retention 注解指定了注解在運(yùn)行時(shí)有效,@Constraint 注解指定了對(duì)應(yīng)的校驗(yàn)器 UniquePhoneValidator。

(二)自定義校驗(yàn)器:實(shí)現(xiàn)邏輯,精準(zhǔn)校驗(yàn)

接下來(lái),我們需要實(shí)現(xiàn)這個(gè)校驗(yàn)器 UniquePhoneValidator,它需要繼承 ConstraintValidator<UniquePhone, String> 接口,并重寫 initialize 和 isValid 方法:

public class UniquePhoneValidator implements ConstraintValidator<UniquePhone, String> {

    @Autowired
    private UserService userService;

    @Override
    public void initialize(UniquePhone constraintAnnotation) {
        // 初始化操作,這里可以獲取注解的參數(shù)等
    }

    @Override
    public boolean isValid(String phone, ConstraintValidatorContext context) {
        if (phone == null) {
            returntrue; // 如果允許為空,可以根據(jù)實(shí)際情況處理
        }
        User user = userService.findByPhone(phone);
        return user == null;
    }
}

在 isValid 方法中,我們通過(guò)調(diào)用 UserService 的 findByPhone 方法來(lái)查詢數(shù)據(jù)庫(kù),判斷該手機(jī)號(hào)是否已經(jīng)存在。如果存在,就返回 false,表示校驗(yàn)不通過(guò);如果不存在,就返回 true,表示校驗(yàn)通過(guò)。

(三)使用自定義校驗(yàn)注解

定義好自定義校驗(yàn)注解和校驗(yàn)器之后,我們就可以在實(shí)體類中使用它了:

public class UserRegisterForm {
    // 其他字段的校驗(yàn)注解
    @UniquePhone(message = "手機(jī)號(hào)已被注冊(cè)")
    private String phone;

    // 省略 getter 和 setter 方法
}

然后在控制器方法中,依然使用 @Valid 注解來(lái)開(kāi)啟校驗(yàn),就像使用 Spring 自帶的注解一樣方便。這樣,我們就實(shí)現(xiàn)了一個(gè)基于數(shù)據(jù)庫(kù)查詢的自定義校驗(yàn),滿足了特殊的業(yè)務(wù)需求。自定義校驗(yàn)注解和校驗(yàn)器的組合,讓我們可以根據(jù)自己的業(yè)務(wù)需求,靈活地定義各種復(fù)雜的校驗(yàn)規(guī)則,不再受限于 Spring 自帶的注解。這就好比我們可以自己動(dòng)手打造一把適合自己的 “倚天劍”,在參數(shù)校驗(yàn)的江湖里所向披靡。

四、全局異常處理:讓錯(cuò)誤處理更優(yōu)雅

前面我們已經(jīng)學(xué)會(huì)了如何使用 Spring Validation 來(lái)進(jìn)行參數(shù)校驗(yàn),并且通過(guò) BindingResult 來(lái)獲取校驗(yàn)錯(cuò)誤信息。但是,每次都在控制器方法里處理 bindingResult.hasErrors() 這種情況,難免會(huì)顯得代碼冗余,而且不夠優(yōu)雅。這時(shí)候,我們可以使用 Spring Boot 的全局異常處理機(jī)制,來(lái)統(tǒng)一處理參數(shù)校驗(yàn)錯(cuò)誤,讓代碼更加簡(jiǎn)潔、整潔。

首先,我們定義一個(gè)全局異常處理類,使用 @RestControllerAdvice 和 @ExceptionHandler 注解:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        List<String> errorMessages = ex.getBindingResult().getAllErrors().stream()
               .map(ObjectError::getDefaultMessage)
               .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(errorMessages);
    }

    // 其他異常處理方法
}

這樣,當(dāng)參數(shù)校驗(yàn)失敗時(shí),就會(huì)拋出 MethodArgumentNotValidException 異常,全局異常處理類會(huì)捕獲這個(gè)異常,并將校驗(yàn)錯(cuò)誤信息以統(tǒng)一的格式返回給客戶端。這樣一來(lái),我們的控制器方法就變得更加簡(jiǎn)潔了,不再需要每次都處理 bindingResult,只需要專注于業(yè)務(wù)邏輯即可。全局異常處理就像是一個(gè) “管家”,幫我們統(tǒng)一管理各種異常情況,包括參數(shù)校驗(yàn)錯(cuò)誤,讓我們的代碼更加規(guī)范、優(yōu)雅,維護(hù)起來(lái)也更加方便。

五、總結(jié):告別土味校驗(yàn),擁抱優(yōu)雅開(kāi)發(fā)

說(shuō)了這么多,咱們來(lái)總結(jié)一下。傳統(tǒng)的 if 語(yǔ)句參數(shù)校驗(yàn)方法,雖然簡(jiǎn)單直接,但就像 “土八路” 一樣,存在代碼冗余、維護(hù)困難、可復(fù)用性差等問(wèn)題,在復(fù)雜場(chǎng)景下更是力不從心。而 Spring Boot 提供的參數(shù)校驗(yàn)機(jī)制,就像是 “正規(guī)軍”,通過(guò)各種注解、分組校驗(yàn)、方法級(jí)校驗(yàn)、自定義校驗(yàn)以及全局異常處理等高階玩法,讓參數(shù)校驗(yàn)變得簡(jiǎn)潔、高效、靈活、優(yōu)雅。

使用 Spring Validation,我們可以大大減少重復(fù)的 if 語(yǔ)句,讓代碼更加簡(jiǎn)潔明了,校驗(yàn)邏輯和業(yè)務(wù)邏輯分離,提高代碼的可維護(hù)性和可復(fù)用性。自定義校驗(yàn)功能更是讓我們能夠應(yīng)對(duì)各種復(fù)雜的業(yè)務(wù)需求,打造專屬的校驗(yàn)規(guī)則。全局異常處理則讓錯(cuò)誤處理更加統(tǒng)一、規(guī)范,提升整個(gè)系統(tǒng)的健壯性。

所以,咱程序員可不能再用那些土味的 if 語(yǔ)句硬剛參數(shù)校驗(yàn)了,趕緊擁抱 Spring Boot 的這些高階玩法吧,讓咱們的代碼也能 “封神”,變得優(yōu)雅又強(qiáng)大。

責(zé)任編輯:武曉燕 來(lái)源: 石杉的架構(gòu)筆記
相關(guān)推薦

2021-05-18 09:25:54

SpringBoot參數(shù)校驗(yàn)

2025-05-23 09:30:57

2019-09-21 21:32:34

數(shù)據(jù)庫(kù)SQL分布式

2024-12-31 09:08:32

2021-11-04 18:27:02

緩存架構(gòu)Eureka

2012-07-19 10:03:32

2023-03-16 08:23:33

2022-12-30 08:49:41

SpringBoot@Validated

2019-09-19 15:47:31

WindowsWindows 7Windows 10

2024-11-12 16:28:34

2023-02-01 10:40:01

2022-02-22 11:50:16

Python字典代碼

2023-01-16 13:45:30

微軟谷歌

2024-06-03 00:00:06

高性能數(shù)據(jù)傳輸應(yīng)用程序

2024-04-11 09:17:51

ArraysJava安全

2021-10-14 18:15:38

BeanUtils對(duì)象生成器

2020-11-20 16:24:33

Windows操作系統(tǒng)老用戶

2025-04-07 00:00:00

CaffeineJava數(shù)據(jù)存取

2021-01-03 17:14:16

ORMObjective S運(yùn)行

2015-05-14 14:27:39

撥號(hào)上網(wǎng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 51ⅴ精品国产91久久久久久 | 国产精品夜间视频香蕉 | 91精品久久久久久久久中文字幕 | 久久综合一区 | 欧美精品 在线观看 | 欧美成年黄网站色视频 | 九九热这里 | 丁香婷婷久久久综合精品国产 | 午夜欧美 | 亚洲人成人一区二区在线观看 | 在线国产小视频 | 国产高清在线精品 | 国产激情视频在线观看 | 欧美日韩专区 | 黄篇网址 | 国产精品毛片 | 91在线视频国产 | 久久国产一区二区三区 | 日韩免费在线视频 | 91av亚洲| 国产高清精品一区二区三区 | 9久久精品 | 国产成人av在线 | 精品一区二区久久久久久久网站 | 久久久久国产一区二区三区 | 亚洲欧美中文日韩在线v日本 | 性大毛片视频 | 国产精品免费在线 | 人和拘一级毛片c | 国产伦精品一区二区三区照片91 | 91在线网站 | www久久 | 国产午夜精品一区二区三区在线观看 | 91精品国产综合久久小仙女图片 | 国产欧美在线视频 | 在线观看国产视频 | 999免费网站 | 国产精品视频一区二区三区 | 久久新视频 | 国产伦精品一区二区三区四区视频 | 免费视频一区二区 |