最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot中注解參數(shù)校驗(yàn)的實(shí)戰(zhàn)指南

 更新時間:2026年01月21日 09:22:07   作者:悟空碼字  
這篇文章主要為大家詳細(xì)介紹了SpringBoot中注解參數(shù)校驗(yàn)的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以了解下

一、參數(shù)校驗(yàn):程序員的“防杠精神器”

假如你的API像個熱情的飯店服務(wù)員,用戶說“隨便來點(diǎn)吃的”,你就真給他上了盤空氣——這可不妙!參數(shù)校驗(yàn)就像是那個會耐心問“要辣的還是不辣的?要牛肉還是雞肉?”的細(xì)心服務(wù)員,確保不鬧出“我要咖啡你卻給我上了杯洗腳水”的尷尬。

SpringBoot的注解校驗(yàn)就像給你的方法參數(shù)請了個私人保鏢,專門攔截那些不靠譜的輸入。沒有它?用戶傳個null過來,你的程序可能就會表演“當(dāng)場崩潰”的絕活。

二、詳細(xì)步驟:給代碼戴上“緊箍咒”

第1步:先來點(diǎn)“開胃菜”——添加依賴

<!-- pom.xml里加入這個,就像泡面加鹵蛋,標(biāo)配! -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

第2步:創(chuàng)建個“相親簡歷”DTO類

import javax.validation.constraints.*;
import java.util.Date;
import java.util.List;

/**
 * 用戶注冊DTO - 比相親網(wǎng)站的個人資料要求還嚴(yán)格
 */
public class UserRegisterDTO {
    
    @NotBlank(message = "用戶名不能為空,難道您是無名氏?")
    @Size(min = 2, max = 20, message = "用戶名長度在2-20之間,太短沒存在感,太長記不住")
    private String username;
    
    @Email(message = "郵箱格式不對,這可不是在寫情書,隨便寫寫就行")
    private String email;
    
    @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$", 
             message = "密碼至少8位,包含字母和數(shù)字,別再用123456了!")
    private String password;
    
    @Min(value = 18, message = "未滿18歲?小朋友先去寫作業(yè)")
    @Max(value = 120, message = "超過120歲?您是老神仙吧")
    private Integer age;
    
    @NotNull(message = "手機(jī)號必須填,不然外賣到了找誰?")
    private String phone;
    
    @AssertTrue(message = "必須接受協(xié)議,雖然可能沒人看")
    private Boolean acceptedAgreement;
    
    @Future(message = "預(yù)約時間必須是未來,時光機(jī)還沒發(fā)明呢")
    private Date appointmentTime;
    
    @Size(min = 1, max = 3, message = "最多選3個愛好,您是想成為全能超人嗎?")
    private List<String> hobbies;
    
    // 此處省略getter和setter,但它們確實(shí)存在,我發(fā)誓!
    // 用Lombok的@Data也行,但今天咱們保持純潔的Java關(guān)系
    
    // 自定義校驗(yàn)注解示例
    @ValidGender
    private String gender;
}

第3步:自定義校驗(yàn)注解——打造專屬“安檢儀”

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * 性別校驗(yàn)注解 - 咱們思想很開放,但數(shù)據(jù)要規(guī)范
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = GenderValidator.class)
public @interface ValidGender {
    String message() default "性別必須是男、女或保密,您這是來自火星嗎?";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

/**
 * 性別校驗(yàn)器 - 嚴(yán)肅的判官
 */
public class GenderValidator implements ConstraintValidator<ValidGender, String> {
    private static final Set<String> VALID_GENDERS = 
        new HashSet<>(Arrays.asList("男", "女", "保密"));
    
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true; // 用@NotNull管非空,咱們只管格式
        }
        return VALID_GENDERS.contains(value);
    }
}

第4步:控制器里使用——給API裝上“安檢門”

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

@RestController
@RequestMapping("/api/users")
@Validated // 這個注解讓方法參數(shù)校驗(yàn)生效,就像給方法吃了“嚴(yán)格丸”
public class UserController {
    
    /**
     * 注冊用戶 - 參數(shù)校驗(yàn)比丈母娘挑女婿還嚴(yán)格
     */
    @PostMapping("/register")
    public Result register(@RequestBody @Valid UserRegisterDTO userDTO) {
        // 如果參數(shù)校驗(yàn)失敗,根本走不到這里
        // 就像考試不及格,進(jìn)不了下一輪面試
        return Result.success("注冊成功,恭喜通過嚴(yán)格審查!");
    }
    
    /**
     * 方法參數(shù)校驗(yàn) - 連路徑變量都不放過
     */
    @GetMapping("/{id}")
    public Result getUser(
            @PathVariable @Min(value = 1, message = "ID必須大于0,您這是要找空氣用戶嗎?") Long id,
            @RequestParam @NotBlank(message = "令牌不能為空,您這是想蒙混過關(guān)?") String token) {
        return Result.success("找到了用戶ID: " + id);
    }
    
    /**
     * 分組校驗(yàn) - 根據(jù)不同場景使用不同規(guī)則
     * 就像上班穿正裝,在家穿睡衣,場合要分清
     */
    @PostMapping("/update")
    public Result updateUser(@RequestBody @Validated(UserUpdateGroup.class) UserUpdateDTO dto) {
        return Result.success("更新成功");
    }
}

// 分組接口定義
interface UserUpdateGroup {}
interface UserCreateGroup {}

第5步:全局異常處理——優(yōu)雅的“救火隊(duì)員”

import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.validation.FieldError;

/**
 * 全局異常處理器 - 專業(yè)收拾校驗(yàn)失敗的爛攤子
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    /**
     * 處理參數(shù)校驗(yàn)異常 - 把技術(shù)語言翻譯成人話
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidationException(MethodArgumentNotValidException ex) {
        // 收集所有錯誤信息,就像收集考試錯題
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        
        return Result.error(400, "參數(shù)校驗(yàn)失敗", errors)
                    .setMessage("您提交的數(shù)據(jù)有點(diǎn)小問題,請檢查后再試哦~");
    }
    
    /**
     * 處理ConstraintViolationException - 方法參數(shù)校驗(yàn)失敗
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result handleConstraintViolationException(ConstraintViolationException ex) {
        List<String> errors = ex.getConstraintViolations().stream()
                .map(violation -> violation.getMessage())
                .collect(Collectors.toList());
        
        return Result.error(400, "參數(shù)不合法", errors);
    }
}

/**
 * 統(tǒng)一返回結(jié)果 - 給前端一個標(biāo)準(zhǔn)的“成績單”
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
    private Integer code;
    private String message;
    private T data;
    private Long timestamp = System.currentTimeMillis();
    
    public static <T> Result<T> success(T data) {
        return new Result<>(200, "成功", data);
    }
    
    public static <T> Result<T> error(Integer code, String message, T data) {
        return new Result<>(code, message, data);
    }
    
    public Result<T> setMessage(String message) {
        this.message = message;
        return this;
    }
}

第6步:進(jìn)階玩法——嵌套校驗(yàn)和集合校驗(yàn)

/**
 * 訂單DTO - 俄羅斯套娃式的校驗(yàn)
 */
public class OrderDTO {
    @NotNull(message = "訂單信息不能為空")
    @Valid // 這個注解讓嵌套校驗(yàn)生效,就像班主任檢查每個學(xué)生的作業(yè)
    private UserDTO user;
    
    @Valid // 集合也要逐個校驗(yàn),一個都別想逃
    private List<@Valid OrderItemDTO> items;
    
    @Valid
    private AddressDTO address;
}

/**
 * 地址DTO - 精確到門牌號
 */
public class AddressDTO {
    @NotBlank(message = "省份不能空,您這是要寄到外太空?")
    private String province;
    
    @NotBlank(message = "城市不能空")
    private String city;
    
    @Size(min = 5, max = 100, message = "詳細(xì)地址5-100字,說清楚點(diǎn),快遞員會感謝您")
    private String detail;
}

三、測試一下:看看“保鏢”工作認(rèn)不認(rèn)真

// 測試Controller - 專門搗亂看系統(tǒng)反應(yīng)
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    void testRegisterWithInvalidData() throws Exception {
        String invalidUserJson = """
        {
            "username": "A",  // 太短了!
            "email": "not-an-email",  // 這不是郵箱
            "password": "123",  // 太弱了
            "age": 10,  // 未成年!
            "phone": null,  // 空值
            "acceptedAgreement": false,  // 不同意協(xié)議
            "appointmentTime": "2020-01-01",  // 過去的時間
            "hobbies": ["吃飯", "睡覺", "打豆豆", "刷手機(jī)", "發(fā)呆"]  // 愛好太多
        }
        """;
        
        mockMvc.perform(MockMvcRequestBuilders.post("/api/users/register")
                .contentType(MediaType.APPLICATION_JSON)
                .content(invalidUserJson))
                .andExpect(status().isBadRequest())  // 應(yīng)該返回400
                .andExpect(jsonPath("$.code").value(400))
                .andExpect(jsonPath("$.data").exists())  // 錯誤詳情
                .andDo(print());  // 打印響應(yīng),看看“保鏢”怎么懟你
    }
}

四、性能優(yōu)化小貼士

/**
 * 校驗(yàn)配置 - 讓校驗(yàn)既嚴(yán)格又高效
 */
@Configuration
public class ValidationConfig {
    
    @Bean
    public Validator validator() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        
        // 可以在這里配置一些自定義設(shè)置
        // 比如緩存校驗(yàn)器,避免重復(fù)創(chuàng)建
        
        return validator;
    }
    
    /**
     * 快速失敗模式 - 發(fā)現(xiàn)一個錯誤就立即返回
     * 就像考試發(fā)現(xiàn)第一題錯了就交卷(不建議真人嘗試)
     */
    @Bean
    public Validator fastFailValidator() {
        return Validation.byDefaultProvider()
                .configure()
                .addProperty("hibernate.validator.fail_fast", "true")
                .buildValidatorFactory()
                .getValidator();
    }
}

總結(jié):參數(shù)校驗(yàn)的“人生哲理”

為什么需要參數(shù)校驗(yàn)?

  • 防止GIGO(垃圾進(jìn),垃圾出)——輸入決定輸出質(zhì)量
  • 安全第一:很多安全漏洞都源于不可信的輸入
  • 用戶體驗(yàn):早發(fā)現(xiàn)錯誤,早提示用戶,別讓用戶猜謎

注解校驗(yàn)的優(yōu)點(diǎn):

  • 聲明式:像貼標(biāo)簽一樣簡單,告別一堆if-else
  • 集中管理:規(guī)則在實(shí)體類上一目了然
  • 易于維護(hù):改注解就能改規(guī)則,不用翻業(yè)務(wù)代碼
  • 豐富內(nèi)置:Spring提供了幾十種注解,總有一款適合你

最佳實(shí)踐建議:

  • 在DTO層做校驗(yàn),保持業(yè)務(wù)層純潔
  • 錯誤消息要友好,說人話,別甩技術(shù)術(shù)語
  • 區(qū)分必填和非必填字段,別要求用戶填宇宙
  • 復(fù)雜邏輯用自定義校驗(yàn)器,別硬塞到一個注解里
  • 記得處理異常,給前端統(tǒng)一的錯誤格式

總結(jié): 參數(shù)校驗(yàn)就像給你的代碼請了個:

  • 門衛(wèi)大爺:不合格的一律不讓進(jìn)
  • 語文老師:檢查格式對不對,內(nèi)容全不全
  • 健身教練:嚴(yán)格要求,不容馬虎
  • 相聲演員:出錯時還能用幽默的方式告訴你

嚴(yán)謹(jǐn)?shù)某绦騿T對待輸入就像貓奴對待貓主子,既要有愛,也要有規(guī)矩! 你的API會因?yàn)榱己玫膮?shù)校驗(yàn)而變得更加健壯、安全、用戶友好。

以上就是SpringBoot中注解參數(shù)校驗(yàn)的實(shí)戰(zhàn)指南的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot注解參數(shù)校驗(yàn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實(shí)現(xiàn)常見的排序算法代碼實(shí)例

    Java實(shí)現(xiàn)常見的排序算法代碼實(shí)例

    這篇文章主要介紹了Java實(shí)現(xiàn)常見的排序算法代碼實(shí)例,按照思路實(shí)現(xiàn)了以下幾個排序算法(冒泡排序、直接插入排序、直接選擇排序、快速排序),方便日后用到,特此記錄一下,需要的朋友可以參考下
    2023-11-11
  • Spring?Cloud?Gateway?WebFlux?模式架構(gòu)場景分析

    Spring?Cloud?Gateway?WebFlux?模式架構(gòu)場景分析

    本文詳細(xì)介紹了Spring Cloud Gateway WebFlux模式的架構(gòu),包括入口類、關(guān)鍵類關(guān)系、核心組件和關(guān)鍵流程描述,Spring Cloud Gateway通過響應(yīng)式編程模型和非阻塞I/O,提供了高性能的API網(wǎng)關(guān)解決方案,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • Spring Security 密碼驗(yàn)證動態(tài)加鹽的驗(yàn)證處理方法

    Spring Security 密碼驗(yàn)證動態(tài)加鹽的驗(yàn)證處理方法

    小編最近在改造項(xiàng)目,需要將gateway整合security在一起進(jìn)行認(rèn)證和鑒權(quán),今天小編給大家分享Spring Security 密碼驗(yàn)證動態(tài)加鹽的驗(yàn)證處理方法,感興趣的朋友一起看看吧
    2021-06-06
  • Java分代垃圾回收策略原理詳解

    Java分代垃圾回收策略原理詳解

    這篇文章主要介紹了Java分代垃圾回收策略原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • Spring Boot啟動過程完全解析(一)

    Spring Boot啟動過程完全解析(一)

    這篇文章主要介紹了Spring Boot啟動過程完全解析(一),需要的朋友可以參考下
    2017-04-04
  • java后臺本地文件轉(zhuǎn)為MultipartFile類型的實(shí)現(xiàn)方式

    java后臺本地文件轉(zhuǎn)為MultipartFile類型的實(shí)現(xiàn)方式

    在Java后臺將本地文件轉(zhuǎn)換為MultipartFile類型,可以通過使用FileItemFactory創(chuàng)建FileItem,然后使用CommonsMultipartFile類構(gòu)造一個MultipartFile對象,將本地文件流轉(zhuǎn)換為MultipartFile,getMultipartFiles()和getMultipartFiles()方法
    2025-02-02
  • maven創(chuàng)建spark項(xiàng)目的pom.xml文件配置demo

    maven創(chuàng)建spark項(xiàng)目的pom.xml文件配置demo

    這篇文章主要為大家介紹了maven創(chuàng)建spark項(xiàng)目的pom.xml文件配置demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Java中常用隊(duì)列的使用解讀

    Java中常用隊(duì)列的使用解讀

    這篇文章主要介紹了Java中常用隊(duì)列的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Servlet3.0實(shí)現(xiàn)文件上傳的方法

    Servlet3.0實(shí)現(xiàn)文件上傳的方法

    本篇文章主要介紹了Servlet實(shí)現(xiàn)文件上傳的方法,所謂文件上傳就是將本地的文件發(fā)送到服務(wù)器中保存。有興趣的可以了解一下。
    2017-03-03
  • 使用Java servlet實(shí)現(xiàn)自動登錄退出功能

    使用Java servlet實(shí)現(xiàn)自動登錄退出功能

    這篇文章主要介紹了使用Java servlet實(shí)現(xiàn)自動登錄退出功能,,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11

最新評論

中宁县| 万荣县| 新乡市| 洪泽县| 南丹县| 荃湾区| 兰州市| 竹山县| 广丰县| 桦南县| 五峰| 乐业县| 繁峙县| 京山县| 嵊州市| 若尔盖县| 乐昌市| 五原县| 岳池县| 阜康市| 方正县| 阳谷县| 汽车| 阿拉善盟| 佛冈县| 崇左市| 丹江口市| 樟树市| 诸暨市| 青龙| 叶城县| 洛隆县| 高陵县| 石泉县| 温宿县| 湘潭县| 吉林省| 达日县| 铅山县| 乐业县| 达州市|