Spring Boot @模式注解未验证格式

30byixjq  于 2023-02-19  发布在  Spring
关注(0)|答案(2)|浏览(244)

我有一个接受项目名称和开始日期的projectDTO。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProjectDTO {
    @NotBlank(message = "project name is required")
    private String projectName;

    @NotNull(message = "project start date is required")
    @Pattern(regexp = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$", message = "date format should be yyyy-MM-dd")
    private LocalDate startDate;
}

下面是我的ExceptionHandler类

@RestControllerAdvice
public class ApplicationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    private ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {

        List<String> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList());

        ApiException apiException = ApiException.builder()
                .errors(errors)
                .httpStatus(HttpStatus.BAD_REQUEST)
                .timestamp(ZonedDateTime.now(ZoneId.of("Z")))
                .build();

        return new ResponseEntity<>(apiException, HttpStatus.BAD_REQUEST);
    }
}

如果我为项目名添加一个空值,它将按预期进行验证,并给出如下所示的自定义错误响应。

{
    "errors": [
        "project name is required"
    ],
    "httpStatus": "BAD_REQUEST",
    "timestamp": "2023-02-17T05:06:08.9362836Z"
}

但是,如果我提供了一个错误的开始日期格式(eidogg. -2023/12 - 17),验证将不起作用。

{
    "timestamp": "2023-02-17T05:21:07.004+00:00",
    "status": 400,
    "error": "Bad Request",
    "path": "/api/projects"
}

在控制台中

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDate` from String "2023/02-17": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2023/02-17' could not be parsed at index 4; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDate` from String "2023/02-17": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2023/02-17' could not be parsed at index 4<LF> at [Source: (PushbackInputStream); line: 5, column: 25] (through reference chain: com.theravado.donationservice.dto.ProjectRequest["projects"]->java.util.ArrayList[0]->com.theravado.donationservice.dto.ProjectDTO["startDate"])]

你能给我一些输入如何得到这个日期格式验证可以为@模式,以便我可以输出一个信息错误消息一样,在项目名称?
干杯

    • 已编辑**

感谢@times29。我觉得我的验证根本不适用于这里的开始日期。精确地说,"日期格式应该是yyyy-MM-dd",而不是JSON解析错误:无法从字符串"2023/02 - 17"反序列化java.time.LocalDate类型的值

@Pattern(regexp = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$", message = "date format should be yyyy-MM-dd")
ve7v8dk2

ve7v8dk21#

您需要为HttpMessageNotReadableException创建一个单独的@ExceptionHandler。您当前的@ExceptionHandler(MethodArgumentNotValidException.class)只能处理MethodArgumentNotValidException异常,但是当出现HttpMessageNotReadableException时(如您的情况),handleMethodArgumentNotValid方法无法处理它。

@ExceptionHandler(HttpMessageNotReadableException.class)
    private ResponseEntity<Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        List<String> errors = ...; // Extract info from the exception
        ApiException apiException = ApiException.builder()
                .errors(errors)
                .httpStatus(HttpStatus.BAD_REQUEST)
                .timestamp(ZonedDateTime.now(ZoneId.of("Z")))
                .build();
        return new ResponseEntity<>(apiException, HttpStatus.BAD_REQUEST);
    }
jogvjijk

jogvjijk2#

实际上问题是@Pattern不能用于LocalDate。当我在我的projectDTO中将类型更改为String时,它开始工作

@NotNull(message = "project start date is required")
    @Pattern(regexp = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$", message = "date format should be yyyy-MM-dd")
    private String startDate;

相关问题