如何使用 Spring 實現 RESTful 服務的驗證


隨著越來越多的應用程式轉向 RESTful 架構,確保客戶端和伺服器之間交換的資料有效變得越來越重要。在本文中,我們將探討如何使用 Spring 實現 RESTful 服務的驗證。

什麼是驗證?

驗證是檢查輸入或返回的資料是否有效並符合一組預定義規則的過程。這些規則可以很簡單,例如檢查欄位是否為空,也可以很複雜,例如確保信用卡號有效。

為什麼驗證很重要?

驗證出於多種原因非常重要。首先,它確保客戶端和伺服器之間交換的資料準確無誤。這對於維護資料完整性和確保應用程式按預期工作至關重要。

其次,驗證有助於防止安全漏洞。透過驗證輸入資料,我們可以防止 SQL 注入、跨站點指令碼 (XSS) 和其他可能由格式錯誤的輸入引起的攻擊。

第三,驗證有助於提供更好的使用者體驗。透過確保輸入的資料有效,我們可以向用戶提供更好的錯誤訊息和反饋,讓他們能夠糾正任何錯誤並繼續應用程式流程。

使用 Spring 實現驗證

Spring 提供了多種工具來在 RESTful 服務中實現驗證。在本節中,我們將介紹其中一些工具以及如何使用它們。

驗證註解

在 Spring 中實現驗證最簡單的方法之一是使用驗證註解。這些註解可以新增到請求物件的欄位中,並在收到請求時自動觸發驗證。

例如,假設我們有一個 RESTful 服務,它接受一個包含姓名、電子郵件和密碼的使用者物件。我們可以使用 @NotBlank 和 @Email 註解來確保這些欄位不為空,並且電子郵件格式有效。

public class User {
   @NotBlank
   private String name;

   @NotBlank
   @Email
   private String email;

   @NotBlank
   private String password;

   // Getters and setters
}

收到請求時,Spring 將自動驗證使用者物件,如果任何欄位驗證失敗,則返回錯誤響應。

自定義驗證器

雖然驗證註解功能強大,但有時我們需要更復雜的驗證規則,而這些規則僅靠註解無法實現。在這種情況下,我們可以建立自定義驗證器來實現我們自己的驗證邏輯。

要建立自定義驗證器,我們需要實現 Spring 提供的 Validator 介面。此介面有兩個方法:supports() 和 validate()。

supports() 方法檢查驗證器是否支援給定類,而 validate() 方法執行實際的驗證。

例如,假設我們有一個 RESTful 服務,它接受一個包含名稱和價格的產品物件。我們希望確保名稱不為空,並且價格大於零。我們可以建立一個自定義驗證器來實現此驗證邏輯。

public class ProductValidator implements Validator {

   @Override
   public boolean supports(Class<?> clazz) {
      return Product.class.equals(clazz);
   }

   @Override
   public void validate(Object target, Errors errors) {
      Product product = (Product) target;
      if (StringUtils.isBlank(product.getName())) {
         errors.rejectValue("name", "name.empty");
      }
      if (product.getPrice() <= 0) {
         errors.rejectValue("price", "price.invalid");
      }
   }
}

在此示例中,我們使用 StringUtils.isBlank() 方法檢查名稱欄位是否為空,並檢查價格欄位是否大於零。如果任何檢查失敗,我們使用 rejectValue() 方法將錯誤新增到 Errors 物件中。

要使用此自定義驗證器,我們需要將其註冊到 Spring。我們可以將其新增到 ValidatorFactoryBean 中來實現。

@Configuration
public class ValidationConfig {

   @Bean
   public ValidatorFactoryBean validatorFactoryBean() {
      ValidatorFactoryBean validatorFactoryBean = new ValidatorFactoryBean();
      validatorFactoryBean.setValidationMessageSource(messageSource());
      return validatorFactoryBean;
   }

   @Bean
   public MessageSource messageSource() {
      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
      messageSource.setBasename("validation-messages");
      return messageSource;
   }
}

在此示例中,我們建立一個 ValidationConfig 類並定義一個 ValidatorFactoryBean bean。我們還建立一個包含驗證錯誤訊息的 MessageSource bean。

要在我們的 RESTful 服務中使用此自定義驗證器,我們需要將 @Validated 註解新增到我們的控制器方法中,並將 @Valid 註解新增到我們的請求物件中。

@RestController
@RequestMapping("/products")
@Validated
public class ProductController {

   @PostMapping
   public ResponseEntity<Product> createProduct(@Valid @RequestBody Product product) {
      // Create product and return response
   }
}

在此示例中,我們在控制器類上使用 @Validated 註解啟用方法級驗證。我們還在請求物件上使用 @Valid 註解,以便在收到請求時觸發驗證。

處理驗證錯誤

發生驗證錯誤時,我們需要向用戶提供有意義的錯誤訊息。Spring 提供了幾種處理驗證錯誤的方法,包括自定義錯誤訊息和全域性錯誤處理。

自定義錯誤訊息

我們可以透過在 resources 資料夾中建立一個 validation-messages.properties 檔案來為每個驗證錯誤提供自定義錯誤訊息。此檔案應包含每個驗證錯誤訊息的鍵值對。

例如,假設我們有一個針對產品名稱欄位為空的驗證錯誤訊息。我們可以將以下鍵值對新增到我們的 validation-messages.properties 檔案中。

name.empty=Product name cannot be empty

發生驗證錯誤時,Spring 將使用鍵查詢錯誤訊息,並將相應的錯誤訊息返回給使用者。

全域性錯誤處理

有時,我們可能希望在一箇中心位置處理所有驗證錯誤,而不是直接將它們返回給使用者。我們可以使用 Spring 的 GlobalExceptionHandler 來實現。

@ControllerAdvice
public class GlobalExceptionHandler {

   @ExceptionHandler(MethodArgumentNotValidException.class)
   @ResponseStatus(HttpStatus.BAD_REQUEST)
   @ResponseBody
   public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
      List<String> errors = ex.getBindingResult().getFieldErrors().stream()
         .map(error -> error.getField() + " " + error.getDefaultMessage())
         .collect(Collectors.toList());
         return new ErrorResponse("Validation error", errors);
   }
}

在此示例中,我們建立了一個 GlobalExceptionHandler 類,用於處理 MethodArgumentNotValidException 異常。當發生驗證錯誤時,會丟擲此異常。

我們返回一個自定義的 ErrorResponse 物件,其中包含錯誤訊息和錯誤字串列表。我們使用 getBindingResult() 方法從異常中檢索錯誤,並將它們格式化為列表。

約束分組

有時,我們可能希望將約束分組在一起,以將其應用於特定欄位子集。例如,我們可能希望將一組約束應用於使用者的個人資訊欄位,並將另一組約束應用於其付款資訊欄位。

我們可以透過建立約束組並使用相應的組註解對欄位進行註解來實現。

public class User {
   @NotBlank(groups = PersonalInfo.class)
   private String firstName;

   @NotBlank(groups = PersonalInfo.class)
   private String lastName;

   @NotBlank(groups = PaymentInfo.class)
   private String creditCardNumber;

   @NotBlank(groups = PaymentInfo.class)
   private String cvv;

   // Getters and setters
}

在此示例中,我們建立了兩個介面組:PersonalInfo 和 PaymentInfo。我們使用相應的組註解對欄位進行註解,並使用 @Validated 註解指定我們要驗證的組。

結論

驗證是任何 RESTful 服務的重要組成部分。透過使用 Spring 實現驗證,我們可以確保客戶端和伺服器之間交換的資料有效、安全並提供良好的使用者體驗。

Spring 提供了多種工具來實現驗證,包括驗證註解和自定義驗證器。我們可以使用自定義錯誤訊息或全域性錯誤處理來處理驗證錯誤。

透過遵循這些最佳實踐,我們可以建立健壯可靠的 RESTful 服務,為我們的使用者和利益相關者提供價值。

更新於: 2023-04-28

213 次瀏覽

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.