Spring Boot 显示无效日期(年月)格式的错误消息:例如 2020-15
Springboot show error message for invalid date (YearMonth) formats: eg 2020-15
我有一个带有 Spring 引导的项目,如果给定的日期格式不正确,我想显示错误响应。
正确的格式是 yyyy-MM (java.time.YearMonth),但我想在有人发送 2020-13、2020-111 或 2020-1 时显示一条消息。
当我添加自定义验证器时,调试器会进入那里并发出有效请求,但不会发出错误请求。我还尝试将 message.properties 与 typeMismatch.project.startdate=Please enter a valid date.
一起使用,但我也没有在响应正文中看到该消息。
应用程序似乎不理解我的错误请求,然后总是抛出一个空主体的 BAD REQUEST,这并不奇怪,因为它不是有效日期。
谁能解释一下如何在响应中针对这些不正确的值显示错误消息?
或者没有其他方法然后使用字符串并将其转换为 YearMonth 对象以便我可以显示 catch 并显示错误消息?
请求对象:
@Getter
@Setter
public class Project {
@NotNull(message = "mandatory")
@DateTimeFormat(pattern = "yyyy-MM")
private YearMonth startdate;
}
控制器:
@RestController
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class ProjectController {
@PostMapping(value = "/project", consumes = MediaType.APPLICATION_JSON_VALUE)
public Project newProject(@Valid @RequestBody Project newProject) {
return projectService.newProject(newProject);
}
}
异常处理程序:
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@SneakyThrows
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
headers.add("Content-Type", "application/json");
ObjectMapper mapper = new ObjectMapper();
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach(error -> {
String name;
if (error instanceof FieldError)
name = ((FieldError) error).getField();
else
name = error.getObjectName();
String errorMessage = error.getDefaultMessage();
errors.put(name, errorMessage);
});
return new ResponseEntity<>(mapper.writeValueAsString(errors), headers, status);
}
}
好的,我制定了一个适合我的解决方案。
我已经在下面添加了解决方案,以供日后发现此主题并遇到与我相同的问题的人使用。
使用简单的正则表达式模式创建自定义验证器:
@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = YearMonthValidator.class)
@Documented
public @interface YearMonthPattern {
String message() default "{YearMonth.invalid}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
public class YearMonthValidator implements ConstraintValidator<YearMonthPattern, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
Pattern pattern = Pattern.compile("^([0-9]{4})-([0-9]{2})$");
Matcher matcher = pattern.matcher(value);
try {
return matcher.matches();
} catch (Exception e) {
return false;
}
}
}
更新请求对象:
@Getter
@Setter
public class Project {
@NotNull(message = "mandatory")
@YearMonthPattern
private String startdate;
public YearMonth toYearMonth(){
return YearMonth.parse(startdate);
}
}
DateTimeFormat 注释已替换为我们新的自定义验证器,而不是 YearMonth,将其设为字符串。现在可以执行验证器注解了,因为到 YearMonth 的映射不会再失败了。
我们还添加了一个新方法,在 Spring 验证请求正文后将 String startdate 转换为 YearMonth,因此我们可以在服务中将其用作 YearMonth,而不必每次都转换它.
现在当我们发送一个请求体时:
{
"startdate": "2020-1"
}
我们收到一个不错的 400 错误请求,响应如下:
{
"endDate": "{YearMonth.invalid}"
}
我有一个带有 Spring 引导的项目,如果给定的日期格式不正确,我想显示错误响应。 正确的格式是 yyyy-MM (java.time.YearMonth),但我想在有人发送 2020-13、2020-111 或 2020-1 时显示一条消息。
当我添加自定义验证器时,调试器会进入那里并发出有效请求,但不会发出错误请求。我还尝试将 message.properties 与 typeMismatch.project.startdate=Please enter a valid date.
一起使用,但我也没有在响应正文中看到该消息。
应用程序似乎不理解我的错误请求,然后总是抛出一个空主体的 BAD REQUEST,这并不奇怪,因为它不是有效日期。
谁能解释一下如何在响应中针对这些不正确的值显示错误消息? 或者没有其他方法然后使用字符串并将其转换为 YearMonth 对象以便我可以显示 catch 并显示错误消息?
请求对象:
@Getter
@Setter
public class Project {
@NotNull(message = "mandatory")
@DateTimeFormat(pattern = "yyyy-MM")
private YearMonth startdate;
}
控制器:
@RestController
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class ProjectController {
@PostMapping(value = "/project", consumes = MediaType.APPLICATION_JSON_VALUE)
public Project newProject(@Valid @RequestBody Project newProject) {
return projectService.newProject(newProject);
}
}
异常处理程序:
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@SneakyThrows
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
headers.add("Content-Type", "application/json");
ObjectMapper mapper = new ObjectMapper();
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach(error -> {
String name;
if (error instanceof FieldError)
name = ((FieldError) error).getField();
else
name = error.getObjectName();
String errorMessage = error.getDefaultMessage();
errors.put(name, errorMessage);
});
return new ResponseEntity<>(mapper.writeValueAsString(errors), headers, status);
}
}
好的,我制定了一个适合我的解决方案。 我已经在下面添加了解决方案,以供日后发现此主题并遇到与我相同的问题的人使用。
使用简单的正则表达式模式创建自定义验证器:
@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = YearMonthValidator.class)
@Documented
public @interface YearMonthPattern {
String message() default "{YearMonth.invalid}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
public class YearMonthValidator implements ConstraintValidator<YearMonthPattern, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
Pattern pattern = Pattern.compile("^([0-9]{4})-([0-9]{2})$");
Matcher matcher = pattern.matcher(value);
try {
return matcher.matches();
} catch (Exception e) {
return false;
}
}
}
更新请求对象:
@Getter
@Setter
public class Project {
@NotNull(message = "mandatory")
@YearMonthPattern
private String startdate;
public YearMonth toYearMonth(){
return YearMonth.parse(startdate);
}
}
DateTimeFormat 注释已替换为我们新的自定义验证器,而不是 YearMonth,将其设为字符串。现在可以执行验证器注解了,因为到 YearMonth 的映射不会再失败了。
我们还添加了一个新方法,在 Spring 验证请求正文后将 String startdate 转换为 YearMonth,因此我们可以在服务中将其用作 YearMonth,而不必每次都转换它.
现在当我们发送一个请求体时:
{
"startdate": "2020-1"
}
我们收到一个不错的 400 错误请求,响应如下:
{
"endDate": "{YearMonth.invalid}"
}