【发布时间】:2019-07-06 18:08:06
【问题描述】:
我正在尝试创建一个 UniqueName 注释作为创建项目 api 的自定义 bean 验证注释:
@PostMapping("/users/{userId}/projects")
public ResponseEntity createNewProject(@PathVariable("userId") String userId,
@RequestBody @Valid ProjectParam projectParam) {
User projectOwner = userRepository.ofId(userId).orElseThrow(ResourceNotFoundException::new);
Project project = new Project(
IdGenerator.nextId(),
userId,
projectParam.getName(),
projectParam.getDescription()
);
...
}
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
class ProjectParam {
@NotBlank
@NameConstraint
private String name;
private String description;
}
@Constraint(validatedBy = UniqueProjectNameValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface UniqueName {
public String message() default "already existed";
public Class<?>[] groups() default {};
public Class<? extends Payload>[] payload() default{};
}
public class UniqueProjectNameValidator implements ConstraintValidator<UniqueName, String> {
@Autowired
private ProjectQueryMapper mapper;
public void initialize(UniqueName constraint) {
}
public boolean isValid(String value, ConstraintValidatorContext context) {
// how can I get the userId info??
return mapper.findByName(userId, value) == null;
}
}
问题是name 字段只需要用户级别的唯一性。所以我需要从 URL 字段中获取{userId} 进行验证。但是如何将其添加到UniqueProjectNameValidator 中?还是有更好的方法来处理这个验证?这只是一个大对象的一小部分,真正的对象在请求处理程序中有许多其他复杂的验证,这使得代码很脏。
【问题讨论】:
-
不确定,但您可以使用 Spring 的表达式语言 (SpEL)。使用
@Autowired Request request创建服务。现在,将此表达式添加到@interface属性中:#{requestService.getField('userId')}。如果需要静态访问,替换为T(package.class):#{T(org.organization...StaticRequestAccess).getField('userId')} -
ConstrainValidator应该是静态的,这样做非常丑陋和混乱,我认为这是不可能的,至少以一种可读的正确方式是不可能的。您应该在控制器接受请求后进行验证,因为此验证超出了基本验证,而是需要读取数据库的逻辑验证。 -
这样使用validation-api不是一个好习惯,你应该在领域层处理这个约束
-
@EduardoEljaiek 你能给我看一个在域层进行这种验证的例子吗?也许只是您在 Internet 上找到的示例的链接
-
我没有尝试这个,因此没有添加这个作为答案,但是博客中的最后一个例子是 @RequestMapping(value = "/path/{id}", method = RequestMethod.GET) public SampleDomainObject get(@ModelAttribute("id") @Validated(IdValidator.class) String id) { return ... // 获取并返回对象 } 应该适用于您的情况。更多信息,copyrightdev.tumblr.com/post/92560458673/…
标签: java spring spring-boot spring-mvc bean-validation