首页 > 解决方案 > 过去日期的验证

问题描述

我需要验证生日是否在过去。

我有以下表格:

@Data
public class PersonForm {
    static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
    private Long id;
    @NotNull(message = "Name should not be null")
    private String name;
    @NotNull(message = "Date should not be null")
    @Pattern(regexp = "^(0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.]((19|2[0-9])[0-9]{2})$", message = "Date format: dd.mm.yyyy")
    private String date;
    @Valid
    private List<CarForm> carForms;

如您所见,在这里我验证日期的字符串格式是否正确。我有以下实体:

@Data
@Entity
@Table(name = "person")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    private String name;
    @Past(message = "Birthdate should be in the past")
    private Date birthdate;
    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "persons_cars",
    joinColumns = @JoinColumn(name = "person_id"),
    inverseJoinColumns = @JoinColumn(name = "car_id"))
    private List<Car> cars;
}

以及一种将一个转换为另一个的实用方法:

public class PersonFormConverter {
    static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
    public static Person toPerson(PersonForm personForm) throws ParseException {
        Person person = new Person();
        person.setId(personForm.getId());
        person.setName(personForm.getName());
        person.setBirthdate(simpleDateFormat.parse(personForm.getDate()));
        if(personForm.getCarForms()!=null){
            person.setCars(personForm.getCarForms().stream().map(CarFormConverter::toCar).collect(Collectors.toList()));
        }
        return person;
    }

正如您在我的实体类 Person 中看到的那样,我对字段 Date 有一个验证约束,但它在我的控制器中无法正常工作:

@PostMapping("/person")
public ResponseEntity<Object> createNew(@RequestBody @Valid PersonForm personForm, BindingResult bindingResult) throws ParseException {
    if(bindingResult.hasErrors()){
        return new ResponseEntity<>(bindingResult.getFieldError().getDefaultMessage(), HttpStatus.BAD_REQUEST);
    }
    return new ResponseEntity<>(personService.createNewPerson(PersonFormConverter.toPerson(personForm)), HttpStatus.OK);
}

如果输入日期是过去的,则服务器返回错误代码 500,而不是 400。我可以理解为什么会发生,但我无法找出正确的方法来验证我的日期是否在过去。你能告诉我正确的变种是什么吗?我相信这一定是一个简单的解决方案,而且我很可能走错了方向。

编辑: 在这里我从我的服务类中添加了我的创建方法:

public Person createNewPerson(@Valid Person person) {
    return personRepository.save(person);
}

不幸的是,这里的注释没有帮助

标签: javavalidation

解决方案


你的问题在这里:

return new ResponseEntity<>(personService.createNewPerson(PersonFormConverter.toPerson(personForm)), HttpStatus.OK);

此行调用服务,该服务又调用存储库并执行验证并在数据无效时引发异常。该异常会冒泡到您的控制器,并且由于您没有捕获它,因此 Spring 框架会这样做并返回状态 500。那是因为它不知道异常的含义,所以它只返回一个“服务器错误”。

要改为返回 400,您需要将该调用包装在 try-catch 中:

try {
  return new ResponseEntity<>(personService.createNewPerson(PersonFormConverter.toPerson(personForm)), HttpStatus.OK);
} catch (TheValidationException e) { //don't rememer the exact name of the exception atm
  //if you can, extract information on what is invalid and tell the caller
  return new ResponseEntity<>("Invalid data provided", HttpStatus.BAD_REQUEST);
}

推荐阅读