知識庫 / Spring / Spring Boot RSS 訂閱

Spring Boot 中驗證布爾類型

Spring Boot
HongKong
4
11:25 AM · Dec 06 ,2025

1. 簡介

在本教程中,我們將學習如何在 Spring Boot 應用程序中驗證 <em >Boolean</em> 類型,並探討各種驗證方法。此外,我們還將驗證不同 Spring Boot 應用程序層(例如控制器或服務層)的 <em >Boolean</em> 類型對象。

2. 編程驗證

`Boolean 類提供了兩個關鍵方法來創建類的實例:Boolean.valueOf()Boolean.parseBoolean()

Boolean.valueOf() 可以接受 <em>String</em><em>boolean</em> 值。 它會檢查輸入字段的值是否為 <em>true</em><em>false</em>,並相應地提供一個 <em>Boolean</em> 對象。 <em>Boolean.parseBoolean()</em> 方法僅接受字符串值。

這些方法不區分大小寫——例如,“true”、“True”、“TRUE”、“false”、“False” 和 “FALSE” 都是可接受的輸入。

讓我們通過一個單元測試來驗證 <em>String</em><em>Boolean</em> 的轉換:

@Test
void givenInputAsString_whenStringToBoolean_thenValidBooleanConversion() {
    assertEquals(Boolean.TRUE, Boolean.valueOf("TRUE"));
    assertEquals(Boolean.FALSE, Boolean.valueOf("false"));
    assertEquals(Boolean.TRUE, Boolean.parseBoolean("True"));
}

我們現在將對從原始布爾值轉換為 Boolean 包裹類的轉換進行驗證:

@Test
void givenInputAsboolean_whenbooleanToBoolean_thenValidBooleanConversion() {
    assertEquals(Boolean.TRUE, Boolean.valueOf(true));
    assertEquals(Boolean.FALSE, Boolean.valueOf(false));
}

3. 使用自定義 Jackson 序列化器進行驗證

由於 Spring Boot API 經常處理 JSON 數據,因此我們將探討如何通過數據反序列化來驗證 JSON 到布爾值的轉換。我們可以使用自定義序列化器反序列化自定義的布爾值表示形式。

讓我們考慮一個場景,我們想要消費以 + (表示 true ) 和 - (表示 false) 符號表示布爾值的數據。 讓我們編寫一個自定義序列化器來實現這一點:

public class BooleanDeserializer extends JsonDeserializer<Boolean> {
    @Override
    public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String value = parser.getText();
        if (value != null && value.equals("+")) {
            return Boolean.TRUE;
        } else if (value != null && value.equals("-")) {
            return Boolean.FALSE;
        } else {
            throw new IllegalArgumentException("Only values accepted as Boolean are + and -");
        }
    }
}

4. 使用註解進行 Bean 驗證

Bean 驗證約束是另一種流行的驗證字段的方法。要使用此方法,我們需要 `spring-boot-starter-validation 依賴項。 在所有可用的驗證註解中,有三種可以用於 Boolean 字段:

  • @NotNull: 如果 Boolean 字段為 null 時,會產生錯誤
  • @AssertTrue: 如果 Boolean 字段設置為 false 時,會產生錯誤
  • @AssertFalse: 如果 Boolean 字段設置為 true 時,會產生錯誤

請注意,@AssertTrue@AssertFalse 都將 null 值視為有效輸入。 這意味着,如果我們想確保僅接受實際的布爾值,則需要將這兩個註解與 @NotNull 結合使用。

5. 布爾值驗證示例

為了演示這一點,我們將同時在控制器和服務層使用 Bean 約束以及自定義 JSON 解析器。讓我們創建一個名為 BooleanObject 的自定義對象,其中包含四個 Boolean 類型的參數。每個參數將採用不同的驗證方法:

public class BooleanObject {

    @NotNull(message = "boolField cannot be null")
    Boolean boolField;

    @AssertTrue(message = "trueField must have true value")
    Boolean trueField;

    @NotNull(message = "falseField cannot be null")
    @AssertFalse(message = "falseField must have false value")
    Boolean falseField;

    @JsonDeserialize(using = BooleanDeserializer.class)
    Boolean boolStringVar;

    //getters and setters
}

6. 控制器中的驗證

當通過 RequestBody 將對象傳遞到 REST 端點時,我們可以使用 @Valid 註解來驗證該對象。 當我們對方法參數應用 @Valid 註解時,我們指示 Spring 驗證相應的用户對象:

@RestController
public class ValidationController {

    @Autowired
    ValidationService service;

    @PostMapping("/validateBoolean")
    public ResponseEntity<String> processBooleanObject(@RequestBody @Valid BooleanObject booleanObj) {
        return ResponseEntity.ok("BooleanObject is valid");
    }

    @PostMapping("/validateBooleanAtService")
    public ResponseEntity<String> processBooleanObjectAtService() {
        BooleanObject boolObj = new BooleanObject();
        boolObj.setBoolField(Boolean.TRUE);
        boolObj.setTrueField(Boolean.FALSE);
        service.processBoolean(boolObj);
        return ResponseEntity.ok("BooleanObject is valid");
    }
}

在驗證後,如果發現任何違規,Spring 會拋出 MethodArgumentNotValidException 異常。為了處理這種情況,可以使用帶有相關 ExceptionHandler 方法的 ControllerAdvice。讓我們創建三個方法來處理來自 Controller 和 Service 層的相應異常:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public String handleValidationException(MethodArgumentNotValidException ex) {
        return ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(e -> e.getDefaultMessage())
            .collect(Collectors.joining(","));
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public String handleIllegalArugmentException(IllegalArgumentException ex) {
        return ex.getMessage();
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public String handleConstraintViolationException(ConstraintViolationException ex) {
       return ex.getMessage();
    }
}

在測試 REST 功能之前,我們建議先通過 Spring Boot 中的 API 進行測試。下面我們來創建 Controller 測試類結構:

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = ValidationController.class)
class ValidationControllerUnitTest {

    @Autowired
    private MockMvc mockMvc;

    @TestConfiguration
    static class EmployeeServiceImplTestContextConfiguration {
        @Bean
        public ValidationService validationService() {
            return new ValidationService() {};
        }
    }

    @Autowired
    ValidationService service;
}

有了這些配置,我們現在可以測試我們在類中使用的驗證註釋。

6.1. 驗證 <em @NotNull/> 註解

讓我們看看 <em @NotNull/> 註解的工作方式。當我們將帶有 null Boolean 參數的 BooleanObject 傳遞時,@Valid 註解將驗證 Bean 並拋出一個“400 Bad Request” HTTP 響應:

@Test
void whenNullInputForBooleanField_thenHttpBadRequestAsHttpResponse() throws Exception {
    String postBody = "{\"boolField\":null,\"trueField\":true,\"falseField\":false,\"boolStringVar\":\"+\"}";

    mockMvc.perform(post("/validateBoolean").contentType("application/json")
            .content(postBody))
        .andExpect(status().isBadRequest());
}

6.2. 驗證 @AssertTrue 註解

接下來,我們將測試 @AssertTrue 註解的工作原理。當我們將 BooleanObject 與一個 false Boolean 參數一起傳遞時,@Valid 註解將驗證 Bean 並拋出一個“400 Bad Request” HTTP 響應。如果捕獲響應體,我們可以獲取 @AssertTrue 註解內部設置的錯誤消息:

 @Test
 void whenInvalidInputForTrueBooleanField_thenErrorResponse() throws Exception {
     String postBody = "{\"boolField\":true,\"trueField\":false,\"falseField\":false,\"boolStringVar\":\"+\"}";

     String output = mockMvc.perform(post("/validateBoolean").contentType("application/json")
             .content(postBody))
         .andReturn()
         .getResponse()
         .getContentAsString();

     assertEquals("trueField must have true value", output);
 }

讓我們也檢查一下如果提供 null 的情況。由於我們僅對該字段進行了 @AssertTrue 的標註,但未進行 @NotNull 的標註,因此不會產生任何驗證錯誤:

 @Test
 void whenNullInputForTrueBooleanField_thenCorrectResponse() throws Exception {
    String postBody = "{\"boolField\":true,\"trueField\":null,\"falseField\":false,\"boolStringVar\":\"+\"}";

    mockMvc.perform(post("/validateBoolean").contentType("application/json")
                    .content(postBody))
            .andExpect(status().isOk());
}

6.3. 驗證 @AssertFalse 註解

我們將瞭解 @AssertFalse 的工作原理。當我們將 true 值傳遞給 @AssertFalse 參數時,帶有 @Valid 的註解會拋出錯誤請求。我們可以從響應體中獲取與 @AssertFalse 註解關聯的錯誤消息:

 @Test
 void whenInvalidInputForFalseBooleanField_thenErrorResponse() throws Exception {
     String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":true,\"boolStringVar\":\"+\"}";

     String output = mockMvc.perform(post("/validateBoolean").contentType("application/json")
             .content(postBody))
         .andReturn()
         .getResponse()
         .getContentAsString();

     assertEquals("falseField must have false value", output);
 }

再次,讓我們看看如果提供 null 會發生什麼。我們對該字段進行了標註,包括了 @AssertFalse@NotNull,因此將會得到一個驗證錯誤:

 @Test
 void whenNullInputForFalseBooleanField_thenHttpBadRequestAsHttpResponse() throws Exception {
    String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":null,\"boolStringVar\":\"+\"}";

    mockMvc.perform(post("/validateBoolean").contentType("application/json")
                    .content(postBody))
            .andExpect(status().isBadRequest());
 }

6.4. 驗證自定義 JSON 解序列化器針對 Boolean 類型

讓我們使用自定義 JSON 解序列化器驗證帶有標記的參數。自定義解序列化器僅接受“+”和“-”值。如果傳遞任何其他值,驗證將失敗並觸發錯誤。讓我們在輸入 JSON 中傳遞“plus”文本值,並查看驗證過程:

@Test
void whenInvalidBooleanFromJson_thenErrorResponse() throws Exception {
    String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":false,\"boolStringVar\":\"plus\"}";

    String output = mockMvc.perform(post("/validateBoolean").contentType("application/json")
            .content(postBody))
        .andReturn()
        .getResponse()
        .getContentAsString();

    assertEquals("Only values accepted as Boolean are + and -", output);
}

最後,讓我們測試一下成功的場景。我們將傳遞“+”符號作為自定義反序列化字段的輸入。由於這是一個有效的輸入,驗證將通過並返回成功響應:

 @Test
 void whenAllBooleanFieldsValid_thenCorrectResponse() throws Exception {
     String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":false,\"boolStringVar\":\"+\"}";

     String output = mockMvc.perform(post("/validateBoolean").contentType("application/json")
             .content(postBody))
         .andReturn()
         .getResponse()
         .getContentAsString();

     assertEquals("BooleanObject is valid", output);
 }

7. 服務層驗證

現在我們來看一下服務層中的驗證。要實現這一點,我們使用 @Validated 註解對服務類進行標註,並將 @Valid 註解放置在方法參數上。 組合這兩種註解將導致 Spring Boot 驗證對象。

與在控制器層中使用的 @RequestBody 註解不同,服務層中的驗證針對簡單的 Java 對象進行,因此 框架會在驗證失敗時引發 ConstraintViolationException

在控制器層創建或修改的對象隨後傳遞到服務層進行處理時,服務層驗證是首選

以下是此服務類的基本框架:

@Service
@Validated
public class ValidationService {

    public void processBoolean(@Valid BooleanObject booleanObj) {
        // further processing
    }
}

在上一節中,我們創建了一個端點來測試服務層和異常處理方法,用於處理 ConstraintViolationException。現在,我們來編寫一個新的測試用例來檢查這一點:

@Test
void givenAllBooleanFieldsValid_whenServiceValidationFails_thenErrorResponse() throws Exception {
    mockMvc.perform(post("/validateBooleanAtService").contentType("application/json"))
        .andExpect(status().isInternalServerError());
}

8. 結論

我們學習瞭如何使用三種方法在控制器和服務層驗證布爾型:程序驗證、Bean 驗證和使用自定義 JSON 解析器。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.