在执行POST时,由验证程序检查以确保没有重复ID的最佳方法是什么?
我试图创建一个自定义验证器,但总是得到一个Internal Server Error
{“ timestamp”:“ 2020-04-25T14:37:19.158 + 0000”,“状态”:500,“错误”:“内部服务器错误”,“ message”:“ HV000030:找不到约束类型'com.omega.mtest.validator.IdConstraint'的验证器,验证类型'java.lang.Integer'。检查'id'的配置”,“路径”:“ /用户”}
这是我的模特班
public class User {
@IdConstraint
@Min(value = 1, message = "ID can't be zero or null")
@Max(value = 1000000, message = "We collect a billion records")
private int id;
@Pattern(regexp = "^[a-zA-Z ]*$", message = "Input doesn't match for a full name")
private String name;
@Min(value = 10)
@Max(value = 120, message = "We didn't expect that age")
private int age;
@Pattern(regexp = "^[a-zA-Z ]*$", message = "Input doesn't match for a city name")
private String city;
public User(int id, String name, int age, String city) {
this.id = id;
this.name = name;
this.age = age;
this.city = city;
}
//getters
}
自定义验证程序界面:
@Constraint(validatedBy = UserValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RUNTIME)
public @interface IdConstraint {
String message() default "The input list cannot contain two ugual IDs";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
接口的类实现
public class UserValidator implements ConstraintValidator<IdConstraint, List<User>> {
@Override
public void initialize(IdConstraint constraintAnnotation) {
}
@Override
public boolean isValid(List<User> users, ConstraintValidatorContext context) {
if (users.size() == 1) {
return true;
} else {
for (int i = 0; i < users.size(); i++) {
for (int j = 0; j < users.size(); j++) {
if (i != j) {
if (users.get(i).getId() == users.get(j).getId()) {
return true;
}
}
}
}
return false;
}
}
控制器类:
@Validated
@RestController
public class UsersController {
@Autowired
public UserService userService;
@RequestMapping(value = "/user", method = RequestMethod.POST)
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
return new ResponseEntity<>(userService.createUser(user), HttpStatus.CREATED);
}
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
ResponseEntity<String> handleConstraintViolationException(ConstraintViolationException e) {
return new ResponseEntity<>("Not valid due to validation error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
}
@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getUsers() {
return userService.getAllUsers();
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public User getUserById(@PathVariable int id) {
return userService.findUserById(id);
}
}
UserService
public interface UserService {
List<User> getAllUsers();
User createUser(User user);
User findUserById(int id);
List<User> list();
}
回购
@Component
public class UserRepository implements UserService {
private List<User> users;
public UserRepository() {
users = new ArrayList<>();
}
@Override
public List<User> getAllUsers() {
return users.stream().collect(Collectors.toList());
}
@Override
public User createUser(User user) {
users.add(user);
return user;
}
@Override
public User findUserById(int id) {
return users.stream()
.filter(t -> t.getId() == id)
.findAny()
.orElse(null);
}
@Override
public List<User> list() {
return users;
}
}
您的验证者签名不正确。
这里您不是验证用户列表,而是一个整数。
喜欢这个
public class UserValidator implements ConstraintValidator<IdConstraint, Integer> {
然后,您必须通过注入服务或存储库来在验证器中恢复用户列表
public class UserValidator implements ConstraintValidator<IdConstraint, Integer> {
@Autowired
Private UserService userService;
@Override
public void initialize(IdConstraint constraintAnnotation) {
}
@Override
public boolean isValid(Integer id, ConstraintValidatorContext context) {
List<User> users = userService.list();
if (users.isEmpty()) {
return true;
} else {
for (int i = 0; i < users.size(); i++) {
if (users.get(i).getId().equals(id)) {
return false;
}
}
}
}
return true;
}
}
首先,您在错误的位置使用@IdConstraint
表示private int id
。您必须将其放在List<User>
上。当您拥有用户列表且两个用户中的任何一个都不具有相同的ID时,验证程序就可以工作。
在发布端点中,您正在使用一个用户作为请求正文。因此,您可以使用存储库的getById()
检查服务中的数据库中是否存在ID。如果存在,则引发异常,否则插入。