我有一个请求data transfer object
(DTO),用于接受 API 的 POST 主体。该 DTO 具有X
实体的 ENUM 键。我创建了一个自定义验证注释,并通过其实体存储库验证 ENUM 是否存在于我的系统中,该实体存储库根据其存在返回实体或 null。
我想将该X
经过验证的实体传递给我的控制器。我不想X
在我的业务逻辑中再次通过 ENUM获取该实体,因为我已经在验证中这样做了。
我将该实体保存在注释验证器类的静态变量中,稍后在业务逻辑中需要时访问它,但如果 API 被并发命中,我的静态变量将被第二个请求覆盖,并且当我的第一个请求的业务逻辑获取X
实体时,由于覆盖问题,它获取第二个请求的实体。
我希望该X
实体对象在其自己的请求周期内限定范围,并在请求完成后像其他对象一样销毁或 GC。我怎样才能做到这一点?
我的自定义验证器:
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidateXimpl.class)
@Documented
public @interface ValidateX {
String message() default "Message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default{};
}
自定义验证器实现:
public class ValidateXimpl implements ConstraintValidator<ValidateX, String> {
@Autowired
DBRepo dbRepo;
@Override
public void initialize(ValidateX annotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
try {
XEntity X = dbRepo.findByEnum(value); // I want this entity in my controller
return (!value.isEmpty() && X != null);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
我的 DTO 放我验证的地方:
public class DTO{
....
@ValidateX
String xEntityEnum
....
}
我的控制器:
@RequestMapping(value = '/x', method = RequestMethod.POST)
public @ResponseBody
Map<String, Object> createX(@Validated @RequestBody DTO dto, BindingResult errors) {
// I want that entity here which I get from db repo in my validator
}
我刚刚解决了这个问题 RequestContextHolder
解决方案代码:
验证器实现
public class ValidateXimpl implements ConstraintValidator<ValidateX, String> {
@Autowired
DBRepo dbRepo;
@Override
public void initialize(ValidateX annotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
try {
XEntity X = dbRepo.findByEnum(value); // I want this entity in my controller
RequestContextHolder.getRequestAttributes().setAttribute(
"XEntity", X, RequestAttributes.SCOPE_REQUEST
); // I saved it in RequestContextHolder
return (!value.isEmpty() && X != null);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
我的控制器
@RequestMapping(value = '/x', method = RequestMethod.POST)
public @ResponseBody
Map<String, Object> createX(@Validated @RequestBody DTO dto, BindingResult errors) {
// I want that entity here which I get from db repo in my validator
System.out.println(
RequestContextHolder.getRequestAttributes().getAttribute(
"XEntity",
RequestAttributes.SCOPE_REQUEST
)
); // I get that from RequestContextHolder
}
这才是我真正需要的。RequestContextHolder
在请求完成时变得清晰,并且由于setAttribute
函数中的请求范围设置,也只能在它自己的请求线程中可用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句