簡體   English   中英

無法使用@Valid 在 Spring 引導中驗證請求正文

[英]Not able to validate request body in Spring boot with @Valid

我想使用@Valid注釋驗證我的請求正文,但它在 Spring Boot 中不起作用

我在 JAR 文件中有一個請求 class,我無法用兩個字段對其進行修改。 一個字段的類型是 Object。我的 controller class 接受這個 class object 作為請求主體。 當我將下面的 JSON 傳遞給 controller 時,驗證不起作用。 以下是代碼示例。

請求 Class:

public class Request {

    Object data;
    Map<String, Object> meta;

    public <T> T getData() throws ClassCastException {
        return (T) this.data;
    }
}

另一個Class:

public class StudentSignUpRequest {

     @NotNull(message = "First Name should not be empty")
     @Size(max = 64, message = "FirstName should not exceed 64 characters")
     private String firstName;

     @NotNull(message = "Last Name should not be empty")
     @Size(max = 64, message = "LastName should not exceed 64 characters")
     private String lastName;

     @NotNull(message = "Email cannot be empty")
     @Size(max = 50, message = "Email cannot exceed 50 characters")
     @Pattern(regexp = EMAIL_REGEX_PATTERN, message = "Email should contain a valid email address.")
     private String email;

     // other fields
}

Controller Class:

@PostMapping(value = Constants.STUDENT_SIGN_UP)
public Response signUpStudent(@Valid @RequestBody Request request, HttpServletRequest servletRequest) {

    // retrieving the actual resource from request payload
    StudentSignUpRequest signUpRequest = request.getData(StudentSignUpRequest.class);
    // call service to sign-up student
    return loginRegistrationService.signUpStudent(signUpRequest);
}

調用代碼設置請求如下:

StudentSignUpRequest studentSignUpRequest = new StudentSignUpRequest();
//setter methods

Request payload = new Request();
payload.setData(studentSignUpRequest);

這是我發送的請求:

對於 firstName 超過 64 個字符:

樣本 JSON:

{
    "data": {
        "firstName": "student111111111111111111111111111111111111111111111111111111111111",
        "lastName": "somesurname",
        "email": "developer@gmail.com"
    }
}

不包括名字的地方:

{
    "data": {
        "lastName": "somesurname",
        "email": "developer@gmail.com"
    }
}

這里@Size@NotNull注釋都不起作用。

任何解決方案?

如果Request類是這樣的,驗證就會起作用;

public class Request {

    @Valid
    StudentSignUpRequest data;

    // other stuff
}

您沒有data類類型這一事實使得無法對其應用驗證,忽略字段上甚至沒有@Valid注釋的事實。 @Valid注釋用於傳播驗證級聯。

但是由於您無法修改Request對象,讓我們繼續使用另一種方法來處理驗證,而無需手動進行。


另一種方法是在從request對象中獲取StudentSignUpRequest后觸發驗證;

StudentSignUpRequest signUpRequest = request.getData(StudentSignUpRequest.class);
loginRegistrationService.signUpStudent(signUpRequest) // validation will trigger with this call

你可以做的如下;

@Service
@Validated
public class LoginRegistrationService {

    public void signUpStudent(@Valid StudentSignUpRequest signUpRequest) {
        // some logic
    }
}

使用@Validated批注,您將激活對該類中public方法中的任何@Valid批注參數的驗證檢查。

可與方法級別驗證一起使用,表示應該在方法級別驗證特定類(充當相應驗證攔截器的切入點)

這可能是昂貴的,因為您希望盡快獲得任何違反約束的情況,而無需為已經注定的請求做任何昂貴的工作。

沒有驗證將按照您使用它的方式工作,您需要將 @valid 放在請求對象內的對象上,但由於您無法控制該類,因此另一種方法是擴展 Request 對象並覆蓋 getData 方法並應用 @valid在這種方法上,它應該以這種方式工作。

因此,您可以使用以下代碼進行驗證。

public <T> T getData() throws ClassCastException, SomeCustomValidationException {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    validator = factory.getValidator();
    Set s = validator.validate(this.data);
    //throw SomeCustomValidationException if set is not empty else return this.data
}

首先對字符串使用@NotEmpty@Notblank 然后確保您導入javax.validation.constraints而不是 hibernate 的。 如果您使用自定義驗證器,則需要(final BindingResult bindingResult)作為控制器方法變量的一部分。

這里有幾件事: Request類中data Object類型使驗證器不可能知道它是StudentSignUpRequest類型。 所以改變數據類型。

public class Request {
    StudentSignUpRequest data;
    Map<String, Object> meta;
}

其次,雖然你已經添加@Valid在控制器的方法,以在驗證領域StudentSignUpRequest你必須添加@Valid這里。 現在,如果在 API 請求中傳遞數據,將對其進行驗證。 如果不存在,則不會進行驗證。 如果你想讓數據被強制傳遞,也添加@NotNull。

public class Request {

    @Valid
    @NotNull
    StudentSignUpRequest data;
    Map<String, Object> meta;
}

您是否添加了以下依賴項?

spring-boot-starter-validation

還要檢查https://www.baeldung.com/spring-boot-bean-validation

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM