[英]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.