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

SpringBoot參數(shù)驗證10個技巧值得收藏

 更新時間:2023年08月05日 14:56:15   作者:Yan-英杰  
Spring Boot提供了內(nèi)置的驗證注解,可以幫助簡單、快速地對輸入字段進行驗證,例如檢查 null 或空字段、強制執(zhí)行長度限制、使用正則表達式驗證模式以及驗證電子郵件地址,那么在Spring Boot應(yīng)用中如何做好參數(shù)校驗工作呢,本文提供了10個小技巧感興趣的朋友一起看看吧

前言

參數(shù)驗證很重要,是平時開發(fā)環(huán)節(jié)中不可少的一部分,但是我想很多后端同事會偷懶,干脆不錯,這樣很可能給系統(tǒng)的穩(wěn)定性和安全性帶來嚴重的危害。那么在Spring Boot應(yīng)用中如何做好參數(shù)校驗工作呢,本文提供了10個小技巧,你知道幾個呢?

1.使用驗證注解

Spring Boot提供了內(nèi)置的驗證注解,可以幫助簡單、快速地對輸入字段進行驗證,例如檢查 null 或空字段、強制執(zhí)行長度限制、使用正則表達式驗證模式以及驗證電子郵件地址。

一些最常用的驗證注釋包括:

  • @NotNull:指定字段不能為空。
  • @NotEmpty:指定列表字段不能為空。
  • @NotBlank:指定字符串字段不得為空或僅包含空格。
  • @Min@Max:指定數(shù)字字段的最小值和最大值。
  • @Pattern:指定字符串字段必須匹配的正則表達式模式。
  • @Email:指定字符串字段必須是有效的電子郵件地址。

具體用法參考下面例子:

public class User {
    @NotNull
    private Long id;
    @NotBlank
    @Size(min = 2, max = 50)
    private String firstName;
    @NotBlank
    @Size(min = 2, max = 50)
    private String lastName;
    @Email
    private String email;
    @NotNull
    @Min(18)
    @Max(99)
    private Integer age;
    @NotEmpty
    private List<String> hobbies;
    @Pattern(regexp = "[A-Z]{2}\d{4}")
    private String employeeId;

2 使用自定義驗證注解

雖然 Spring Boot 的內(nèi)置驗證注釋很有用,但它們可能無法涵蓋所有情況。如果有特殊參數(shù)驗證的場景,可以使用 Spring 的 JSR 303 驗證框架創(chuàng)建自定義驗證注釋。自定義注解可以讓你的的驗證邏輯更具可重用性和可維護性。

假設(shè)我們有一個應(yīng)用程序,用戶可以在其中創(chuàng)建帖子。每個帖子都應(yīng)該有一個標題和一個正文,并且標題在所有帖子中應(yīng)該是唯一的。雖然 Spring Boot 提供了用于檢查字段是否為空的內(nèi)置驗證注釋,但它沒有提供用于檢查唯一性的內(nèi)置驗證注釋。在這種情況下,我們可以創(chuàng)建一個自定義驗證注解來處理這種情況。

首先,我們創(chuàng)建自定義約束注解UniqueTitle

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueTitleValidator.class)
public @interface UniqueTitle {
    String message() default "Title must be unique";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

接下來,我們創(chuàng)建一個PostRepository接口,目的是從數(shù)據(jù)庫中檢索帖子:

public interface PostRepository extends JpaRepository<Post, Long> {
    Post findByTitle(String title);
}

然后我們需要定義驗證器類UniqueTitleValidator,如下所示:

@Component
public class UniqueTitleValidator implements ConstraintValidator<UniqueTitle, String> {
    @Autowired
    private PostRepository postRepository;
    @Override
    public boolean isValid(String title, ConstraintValidatorContext context) {
        if (title == null) {
            return true;
        }
        return Objects.isNull(postRepository.findByTitle(title));
    }
}

UniqueTitleValidator實現(xiàn)了ConstraintValidator接口,它有兩個泛型類型:第一個是自定義注解UniqueTitle,第二個是正在驗證的字段類型(在本例中為String). 我們還自動裝配了PostRepository類以從數(shù)據(jù)庫中檢索帖子。

isValid()方法通過查詢PostRepository來檢查title是否為 null 或者它是否是唯一的。如果title為 null 或唯一,則驗證成功,并返回 true。

定義了自定義驗證注釋和驗證器類后,我們現(xiàn)在可以使用它來驗證 Spring Boot 應(yīng)用程序中的帖子標題:

public class Post {
    @UniqueTitle
    private String title;
    @NotNull
    private String body;
}

我們已將@UniqueTitle注釋應(yīng)用于Post類中的title變量。驗證此字段時,這將觸發(fā)UniqueTitleValidator類中定義的驗證邏輯。

3 在服務(wù)器端驗證

除了前端或者客戶端做了驗證意外,服務(wù)器端驗證輸入是至關(guān)重要的。它可以確保在處理或存儲任何惡意或格式錯誤的數(shù)據(jù)之前將其捕獲,這對于應(yīng)用程序的安全性和穩(wěn)定性至關(guān)重要。

假設(shè)我們有一個允許用戶創(chuàng)建新帳戶的REST端點。端點需要一個包含用戶用戶名和密碼的 JSON 請求體。為確保輸入有效,我們可以創(chuàng)建一個 DTO(數(shù)據(jù)傳輸對象)類并將驗證注釋應(yīng)用于其字段:

public class UserDTO {
    @NotBlank
    private String username;
    @NotBlank
    private String password;
}

我們使用@NotBlank注解來確保usernamepassword字段不為空或 null。

接下來,我們可以創(chuàng)建一個控制器方法來處理 HTTP POST 請求并在創(chuàng)建新用戶之前驗證輸入:

@RestController
@RequestMapping("/users")
@Validated
public class UserController {
    @Autowired
    private UserService userService;
    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO userDto) {
        userService.createUser(userDto);
        return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully");
    }
}

我們使用 Spring 的@Validated注解來啟用方法級驗證,我們還將@Valid注釋應(yīng)用于userDto參數(shù)以觸發(fā)驗證過程。

4 提供有意義的錯誤信息

當驗證失敗時,必須提供清晰簡潔的錯誤消息來描述出了什么問題以及如何修復(fù)它。

這是一個示例,如果我們有一個允許用戶創(chuàng)建新用戶的RESTful API。我們要確保姓名和電子郵件地址字段不為空,年齡在 18 到 99 歲之間,除了這些字段,如果用戶嘗試使用重復(fù)的“用戶名”創(chuàng)建帳戶,我們還會提供明確的錯誤消息或“電子郵件”。

為此,我們可以定義一個帶有必要驗證注釋的模型類 User,如下所示:

public class User {
    @NotBlank(message = "用戶名不能為空")
    private String name;
    @NotBlank(message = "Email不能為空")
    @Email(message = "無效的Emaild地址")
    private String email;
    @NotNull(message = "年齡不能為空")
    @Min(value = 18, message = "年齡必須大于18")
    @Max(value = 99, message = "年齡必須小于99")
    private Integer age;
}

我們使用 message屬性為每個驗證注釋提供了自定義錯誤消息。

接下來,在我們的 Spring 控制器中,我們可以處理表單提交并使用@Valid注釋驗證用戶輸入:

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;
    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody User user, BindingResult result) {
        if (result.hasErrors()) {
            List<String> errorMessages = result.getAllErrors().stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.toList());
            return ResponseEntity.badRequest().body(errorMessages.toString());
        }
        // save the user to the database using UserService
        userService.saveUser(user);
        return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully");
    }
}

我們使用@Valid注釋來觸發(fā)User對象的驗證,并使用BindingResult對象來捕獲任何驗證錯誤。

5 將 i18n 用于錯誤消息

如果你的應(yīng)用程序支持多種語言,則必須使用國際化 (i18n) 以用戶首選語言顯示錯誤消息。

以下是在 Spring Boot 應(yīng)用程序中使用 i18n 處理錯誤消息的示例

首先,在資源目錄下創(chuàng)建一個包含默認錯誤消息的messages.properties文件

# messages.properties
user.name.required=Name is required.
user.email.invalid=Invalid email format.
user.age.invalid=Age must be a number between 18 and 99.

接下來,為每種支持的語言創(chuàng)建一個messages_xx.properties文件,例如,中文的messages_zh_CN.properties

user.name.required=名稱不能為空.
user.email.invalid=無效的email格式.
user.age.invalid=年齡必須在18到99歲之間.

然后,更新您的驗證注釋以使用本地化的錯誤消息

public class User {
    @NotNull(message = "{user.id.required}")
    private Long id;
    @NotBlank(message = "{user.name.required}")
    private String name;
    @Email(message = "{user.email.invalid}")
    private String email;
    @NotNull(message = "{user.age.required}")
    @Min(value = 18, message = "{user.age.invalid}")
    @Max(value = 99, message = "{user.age.invalid}")
    private Integer age;
}

最后,在 Spring 配置文件中配置MessageSource bean以加載i18n消息文件

@Configuration
public class AppConfig {
    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
    @Bean
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean();
        validatorFactoryBean.setValidationMessageSource(messageSource());
        return validatorFactoryBean;
    }
}

現(xiàn)在,當發(fā)生驗證錯誤時,錯誤消息將根據(jù)隨請求發(fā)送的“Accept-Language”標頭以用戶的首選語言顯示。

6 使用分組驗證

驗證組是 Spring Boot 驗證框架的一個強大功能,允許您根據(jù)其他輸入值或應(yīng)用程序狀態(tài)應(yīng)用條件驗證規(guī)則。

現(xiàn)在有一個包含三個字段的User類的情況下:firstName、lastNameemail。我們要確保如果email字段為空,則firstNamelastName字段必須非空。否則,所有三個字段都應(yīng)該正常驗證。

為此,我們將定義兩個驗證組:EmailNotEmptyDefault。EmailNotEmpty組將包含當email字段不為空時的驗證規(guī)則,而Default組將包含所有三個字段的正常驗證規(guī)則。

創(chuàng)建帶有驗證組的User

public class User {
    @NotBlank(groups = Default.class)
    private String firstName;
    @NotBlank(groups = Default.class)
    private String lastName;
    @Email(groups = EmailNotEmpty.class)
    private String email;
    // getters and setters omitted for brevity
    public interface EmailNotEmpty {}
    public interface Default {}
}

請注意,我們在User類中定義了兩個接口,EmailNotEmptyDefault。這些將作為我們的驗證組。

接下來,我們更新Controller使用這些驗證組

@RestController
@RequestMapping("/users")
@Validated
public class UserController {
    public ResponseEntity<String> createUser(
            @Validated({org.example.model.ex6.User.EmailNotEmpty.class}) @RequestBody User userWithEmail,
            @Validated({User.Default.class}) @RequestBody User userWithoutEmail)
    {
        // Create the user and return a success response
    }
}
  • 我們已將@Validated注釋添加到我們的控制器,表明我們想要使用驗證組。我們還更新了createUser方法,將兩個User對象作為輸入,一個在email字段不為空時使用,另一個在它為空時使用。
  • @Validated注釋用于指定將哪個驗證組應(yīng)用于每個User對象。對于userWithEmail參數(shù),我們指定了EmailNotEmpty組,而對于userWithoutEmail參數(shù),我們指定了Default組。

進行這些更改后,現(xiàn)在將根據(jù)“電子郵件”字段是否為空對“用戶”類進行不同的驗證。如果為空,則firstNamelastName字段必須非空。否則,所有三個字段都將正常驗證。

7 對復(fù)雜邏輯使用跨域驗證

如果需要驗證跨多個字段的復(fù)雜輸入規(guī)則,可以使用跨字段驗證來保持驗證邏輯的組織性和可維護性??缱侄悟炞C可確保所有輸入值均有效且彼此一致,從而防止出現(xiàn)意外行為。

假設(shè)我們有一個表單,用戶可以在其中輸入任務(wù)的開始日期和結(jié)束日期,并且我們希望確保結(jié)束日期不早于開始日期。我們可以使用跨域驗證來實現(xiàn)這一點。

首先,我們定義一個自定義驗證注解EndDateAfterStartDate

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EndDateAfterStartDateValidator.class)
public @interface EndDateAfterStartDate {
    String message() default "End date must be after start date";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

然后,我們創(chuàng)建驗證器EndDateAfterStartDateValidator

public class EndDateAfterStartDateValidator implements ConstraintValidator<EndDateAfterStartDate, TaskForm> {
    @Override
    public boolean isValid(TaskForm taskForm, ConstraintValidatorContext context) {
        if (taskForm.getStartDate() == null || taskForm.getEndDate() == null) {
            return true;
        }
        return taskForm.getEndDate().isAfter(taskForm.getStartDate());
    }
}

最后,我們將EndDateAfterStartDate注釋應(yīng)用于我們的表單對象TaskForm

@EndDateAfterStartDate
public class TaskForm {
    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate startDate;
    @NotNull
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate endDate;
}

現(xiàn)在,當用戶提交表單時,驗證框架將自動檢查結(jié)束日期是否晚于開始日期,如果不是,則提供有意義的錯誤消息。

8 對驗證錯誤使用異常處理

可以使用異常處理ExceptionHandler來統(tǒng)一捕獲和處理驗證錯誤。

以下是如何在 Spring Boot 中使用異常處理來處理驗證錯誤的示例:

@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers, HttpStatus status,
                                                                  WebRequest request) {
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", LocalDateTime.now());
        body.put("status", status.value());
        // Get all errors
        List<String> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(x -> x.getDefaultMessage())
                .collect(Collectors.toList());
        body.put("errors", errors);
        return new ResponseEntity<>(body, headers, status);
    }
}

在這里,我們創(chuàng)建了一個用@RestControllerAdvice注解的RestExceptionHandler類來處理我們的 REST API 拋出的異常。然后我們創(chuàng)建一個用@ExceptionHandler注解的方法來處理在驗證失敗時拋出的MethodArgumentNotValidException。

在處理程序方法中,我們創(chuàng)建了一個Map對象來保存錯誤響應(yīng)的詳細信息,包括時間戳、HTTP 狀態(tài)代碼和錯誤消息列表。我們使用MethodArgumentNotValidException對象的getBindingResult()方法獲取所有驗證錯誤并將它們添加到錯誤消息列表中。

最后,我們返回一個包含錯誤響應(yīng)詳細信息的ResponseEntity對象,包括作為響應(yīng)主體的錯誤消息列表、HTTP 標頭和 HTTP 狀態(tài)代碼。

有了這個異常處理代碼,我們的 REST API 拋出的任何驗證錯誤都將被捕獲并以結(jié)構(gòu)化和有意義的格式返回給用戶,從而更容易理解和解決問題。

9 測試你的驗證邏輯

需要為你的驗證邏輯編寫單元測試,以幫助確保它正常工作。

@DataJpaTest
public class UserValidationTest {
    @Autowired
    private TestEntityManager entityManager;
    @Autowired
    private Validator validator;
    @Test
    public void testValidation() {
        User user = new User();
        user.setFirstName("John");
        user.setLastName("Doe");
        user.setEmail("invalid email");
        Set<ConstraintViolation<User>> violations = validator.validate(user);
        assertEquals(1, violations.size());
        assertEquals("must be a well-formed email address", violations.iterator().next().getMessage());
    }
}

我們使用 JUnit 5 編寫一個測試來驗證具有無效電子郵件地址的“用戶”對象。然后我們使用Validator接口來驗證User對象并檢查是否返回了預(yù)期的驗證錯誤。

10 考慮客戶端驗證

客戶端驗證可以通過向用戶提供即時反饋并減少對服務(wù)器的請求數(shù)量來改善用戶體驗。但是,不應(yīng)依賴它作為驗證輸入的唯一方法??蛻舳蓑炞C很容易被繞過或操縱,因此必須在服務(wù)器端驗證輸入,以確保安全性和數(shù)據(jù)完整性。

總結(jié)

有效的驗證對于任何 Web 應(yīng)用程序的穩(wěn)定性和安全性都是必不可少的。Spring Boot 提供了一套工具和庫來簡化驗證邏輯并使其更易于維護。通過遵循本文中討論的最佳實踐,您可以確保您的驗證組件有效并提供出色的用戶體驗。

到此這篇關(guān)于SpringBoot參數(shù)驗證10個技巧的文章就介紹到這了,更多相關(guān)SpringBoot參數(shù)驗證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Spring Data JDBC實現(xiàn)DDD聚合的示例代碼

    使用Spring Data JDBC實現(xiàn)DDD聚合的示例代碼

    這篇文章主要介紹了使用Spring Data JDBC實現(xiàn)DDD聚合的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Java如何高效使用OpenCV圖像處理庫

    Java如何高效使用OpenCV圖像處理庫

    OpenCV是一個開源的計算機視覺庫,它提供了一系列豐富的圖像處理和計算機視覺算法,包括圖像讀取、顯示、濾波、特征檢測、目標跟蹤等功能,這篇文章主要給大家介紹了關(guān)于Java如何高效使用OpenCV圖像處理庫的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • 基于javaWeb 項目SSM配置要點及可能遇到的問題和解決方法

    基于javaWeb 項目SSM配置要點及可能遇到的問題和解決方法

    下面小編就為大家?guī)硪黄趈avaWeb 項目SSM配置要點及可能遇到的問題和解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Spring Security如何基于Authentication獲取用戶信息

    Spring Security如何基于Authentication獲取用戶信息

    這篇文章主要介紹了Spring Security如何基于Authentication獲取用戶信息,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下
    2020-03-03
  • IDEA遠程部署調(diào)試Java應(yīng)用程序的詳細流程

    IDEA遠程部署調(diào)試Java應(yīng)用程序的詳細流程

    這篇文章主要介紹了IDEA遠程部署調(diào)試Java應(yīng)用程序,本文通過圖文并茂的形式給大家介紹的非常詳細,需要的朋友可以參考下
    2021-10-10
  • Java 線程池詳解及實例代碼

    Java 線程池詳解及實例代碼

    這篇文章主要介紹了Java 線程池的相關(guān)資料,并符實例代碼,幫助大家學(xué)習參考,需要的朋友可以參考下
    2016-09-09
  • 我從jdk1.8升級到j(luò)dk11所遇到的坑都有這些

    我從jdk1.8升級到j(luò)dk11所遇到的坑都有這些

    這篇文章主要介紹了從jdk1.8升級到j(luò)dk11將會遇到的一些坑,本文給大家分享解決方案對大家的學(xué)習或工作具有參考借鑒價值,對jdk1.8升級到j(luò)dk11相關(guān)知識感興趣的朋友,快來看看吧
    2021-08-08
  • sonar-scanner連接sonarquebe7的sonar.java.binaries問題的解決方案

    sonar-scanner連接sonarquebe7的sonar.java.binaries問題的解決方案

    今天小編就為大家分享一篇關(guān)于sonar-scanner連接sonarquebe7的sonar.java.binaries問題的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • springboot整合mybatis的超詳細過程(配置模式+注解模式)

    springboot整合mybatis的超詳細過程(配置模式+注解模式)

    這篇文章主要介紹了springboot整合mybatis的詳細過程(配置模式+注解模式),這里我使用的是配置模式+注解模式所以需要配置全局文件,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • springboot線程池監(jiān)控的簡單實現(xiàn)

    springboot線程池監(jiān)控的簡單實現(xiàn)

    本文主要介紹了springboot線程池監(jiān)控的簡單實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論