java - 过去日期的验证
问题描述
我需要验证生日是否在过去。
我有以下表格:
@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);
}
不幸的是,这里的注释没有帮助
解决方案
你的问题在这里:
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);
}
推荐阅读
- c++ - 递归包含模板文件无法编译
- c# - c# .net mysql - 在百万行表中查找更新行的最佳方法
- javascript - JSON.parse(e.data) - websocket 的 onmessage - ReferenceError: e is not defined / 'data' of undefined / WebSocket 已经处于 CLOSING 或 CLOSED 状态
- c++ - 尝试使用 std::vector 时出现静态断言失败错误
- docker - Docker compose 支持“附加到 Traefik”
- php - 如何与 PDO 建立一个 mysql 连接
- r - R中数据帧中的无效数据
- python - 如何正确定义具有 numpy 数组作为参数和返回类型的函数?
- java - 从包含 textview 值的文件 .txt (ArrayList) 将所有项目设置为列表视图 [Android Java]
- azure - 在 ARM 模板的每次迭代中创建一个新的 guid