簡體   English   中英

Spring @Valid 消息未通過響應

[英]Spring @Valid Message Not Coming Through in Response

我有一個使用 Spring 和 Axon 的 CQRS Rest API。 使用javax.validation庫為輸入設置驗證。 驗證工作正常,並發現“用戶名”需要至少 2 個字符長。 但是,與驗證失敗相關的消息不會顯示在對 Post 請求的響應中。

響應最終缺少“錯誤”和“消息”信息,我不知道為什么。 MethodArgumentNotValidException不會被推送到 try-catch 塊並得到處理嗎? 如果驗證工作正常,為什么消息沒有以“400”狀態響應發出?

我錯過了什么?

這是我試圖得到的回應:

{
    "timestamp": "2022-04-24T01:23:27.809+00:00",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Size.registerUserCommand.user.account.username",
                "Size.user.account.username",
                "Size.username",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
               {
                    "codes": [
                        "registerUserCommand.user.account.username",
                        "user.account.username"
                    ],
                    "arguments": null,
                    "defaultMessage": "user.account.username",
                    "code": "user.account.username"
               },
               2134838498,
               2
           ],
           "defaultMessage": "username must have a minimum of 2 characters",
           "objectName": "registerUserCommand",
           "field": "user.account.username",
           "rejectedValue": "m",
           "bindingFailure": false,
           "code": "Size
        }
    ],
    "message": "Validation failed for object='registerUserCommand'. Error count: 1",
    "path": "/api/v1/registerUser"
}

這是我實際得到的回應:

{
    "timestamp": "2022-04-24T01:23:27.809+00:00",
    "status": 400,
    "error": "Bad Request",
    "message": "",
    "path": "/api/v1/registerUser"
}

發送到控制器的發布請求:

{
    "user": {
        "firstname": "Mike",
        "lastname": "Jacobs",
        "emailAddress": "mike@spripgbank.com",
        "account": {
            "username": "m",
            "password": "mik959593e0",
            "roles": [
                "READ_PRIVILEGE"
            ]
        }
    }
}

Post 請求的控制台輸出:

2022-04-24 20:32:21.339  INFO 11040 --- [nio-8081-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-04-24 20:32:21.340  INFO 11040 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-04-24 20:32:21.343  INFO 11040 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
2022-04-24 20:32:22.120  WARN 11040 --- [nio-8081-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<com.springbank.user.cmd.api.dto.RegisterUserResponse> com.springbank.user.cmd.api.controllers.RegisterUserController.registerUser(com.springbank.user.cmd.api.commands.RegisterUserCommand): [Field error in object 'registerUserCommand' on field 'user.account.username': rejected value [m]; codes [Size.registerUserCommand.user.account.username,Size.user.account.username,Size.username,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [registerUserCommand.user.account.username,user.account.username]; arguments []; default message [user.account.username],2147483647,2]; default message [username must have a min of 2 characters]] ]

接受請求的控制器:

    package com.springbank.user.cmd.api.controllers;

    import com.springbank.user.cmd.api.commands.RegisterUserCommand;
    import com.springbank.user.cmd.api.dto.RegisterUserResponse;
    import org.axonframework.commandhandling.gateway.CommandGateway;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import javax.validation.Valid;
    import java.util.UUID;
    
    @RestController
    @RequestMapping(path = "/api/v1/registerUser")
    public class RegisterUserController {
         private final CommandGateway commandGateway;

         @Autowired
         public RegisterUserController(CommandGateway commandGateway) {
             this.commandGateway = commandGateway;
         }
    
         @PostMapping
         public ResponseEntity<RegisterUserResponse> registerUser(@Valid @RequestBody RegisterUserCommand command) {
             var id = UUID.randomUUID().toString();
             command.setId(id);
    
             try{
                commandGateway.send(command);
                return new ResponseEntity<>(new RegisterUserResponse( id, "User Successfully Registered"), HttpStatus.CREATED);
    
             }catch (Exception e) {
                 var safeErrorMessage = "Error while processing register user request for id - " + id;
                 System.out.println(e.toString());
    
                 return new ResponseEntity<>(new RegisterUserResponse( id, safeErrorMessage), HttpStatus.INTERNAL_SERVER_ERROR);
             }
         }
    }

命令:

package com.springbank.user.cmd.api.commands;

import com.springbank.user.core.models.User;
import lombok.Builder;
import lombok.Data;
import org.axonframework.modelling.command.TargetAggregateIdentifier;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

@Data
@Builder
public class RegisterUserCommand {

    @TargetAggregateIdentifier
    private String id;
    @NotNull(message = "Need to supply User info")
    @Valid
    private User user;
}

用戶模型:

package com.springbank.user.core.models;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import javax.validation.Valid;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Document(collection = "users")
public class User {
    @Id
    private String id;
    @NotEmpty(message = "firstname is mandatory")
    private String firstname;
    @NotEmpty(message = "lastname is mandatory")
    private String lastname;
    @Email(message = "please provide a valid email")
    private String emailAddress;
    @NotNull(message = "Please provide account Credentials")
    @Valid
    private Account account;
}

進行驗證的帳戶模型:

package com.springbank.user.core.models;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Account {
    @Size(min = 2, message = "username must have a min of 2 characters")
    private String username;
    @Size(min = 7, message = "password must have a min of 7 characters")
    private String password;
    @NotNull(message = "specify at least one user role")
    private List<Role> roles;
}

注冊用戶響應:

package com.springbank.user.cmd.api.dto;


public class RegisterUserResponse extends BaseResponse{
    private String id;

    public RegisterUserResponse(String id, String message) {
        super(message);
        this.id = id;
    }
}

    

基本反應:

package com.springbank.user.cmd.api.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class BaseResponse {
    private String Message;
}

由於您使用@Valid RegisterUserCommand注釋控制器方法參數,因此對象的驗證將在執行進入您的 try/catch 塊之前進行。

如果您查看位於ResponseEntityExceptionHandler中的以下方法,那么您會看到默認實現如下所示。 如您所見,默認情況下將 null 作為正文發送,這會導致細節被遺漏。

protected ResponseEntity<Object> handleMethodArgumentNotValid(
        MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

    return handleExceptionInternal(ex, null, headers, status, request);
}

因此,如果您想以不同方式處理該錯誤,則需要為該異常類型添加自定義異常處理並覆蓋默認處理程序。

暫無
暫無

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

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