Java 如何从自定义验证注释将实体对象传递给控制器
我有一个请求Java 如何从自定义验证注释将实体对象传递给控制器,java,spring,spring-mvc,spring-boot,spring-security,Java,Spring,Spring Mvc,Spring Boot,Spring Security,我有一个请求数据传输对象(DTO),用于接受API的POST主体。该DTO具有X实体的枚举键。我创建了一个自定义的验证注释,并通过其实体存储库验证枚举是否存在于我的系统中,该实体存储库根据枚举的存在返回entity或null 我想将该X验证实体传递给我的控制器。我不想在我的业务逻辑中再次通过ENUM获取X实体,因为我已经在验证中这样做了 我将该实体保存在annotation validator类中的一个静态变量中,并在以后需要在业务逻辑中访问该实体时访问它,但如果API同时被命中,则我的静态变量
数据传输对象
(DTO),用于接受API的POST主体。该DTO具有X
实体的枚举键。我创建了一个自定义的验证注释,并通过其实体存储库验证枚举是否存在于我的系统中,该实体存储库根据枚举的存在返回entity或null
我想将该X
验证实体传递给我的控制器。我不想在我的业务逻辑中再次通过ENUM获取X
实体,因为我已经在验证中这样做了
我将该实体保存在annotation validator类中的一个静态变量中,并在以后需要在业务逻辑中访问该实体时访问它,但如果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{};
}
我的控制器:
@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
}
@RequestMapping(值='/x',方法=RequestMethod.POST)
公共@ResponseBody
映射createX(@Validated@RequestBody DTO到DTO,BindingResult错误){
//我想在这里的实体,我从数据库回购在我的验证器
}
我刚刚从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);
}
}
}
公共类validateImpl实现ConstraintValidator{
@自动连线
DBRepo-DBRepo;
@凌驾
公共void初始化(ValidateX注释){
}
@凌驾
公共布尔值有效(字符串值,ConstraintValidatorContext ctx){
试一试{
XEntity X=dbRepo.findByEnum(值);//我希望控制器中有这个实体
RequestContextHolder.getRequestAttributes().setAttribute(
“XEntity”,X,RequestAttributes.SCOPE\u请求
);//我将其保存在RequestContextHolder中
返回(!value.isEmpty()&&X!=null);
}捕获(例外情况除外){
抛出新的运行时异常(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
}
@RequestMapping(值='/x',方法=RequestMethod.POST)
公共@ResponseBody
映射createX(@Validated@RequestBody DTO到DTO,BindingResult错误){
//我想在这里的实体,我从数据库回购在我的验证器
System.out.println(
RequestContextHolder.getRequestAttributes().getAttribute(
“至尊”,
RequestAttributes.SCOPE\u请求
)
);//我是从RequestContextHolder那里得到的
}
这就是我真正需要的
RequestContextHolder
在请求完成时变得清晰,并且由于在setAttribute
函数中设置了请求范围,因此仅在其自己的请求线程中可用。我刚刚从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);
}
}
}
公共类validateImpl实现ConstraintValidator{
@自动连线
DBRepo-DBRepo;
@凌驾
公共void初始化(ValidateX注释){
}
@凌驾
公共布尔值有效(字符串值,ConstraintValidatorContext ctx){
试一试{
XEntity X=dbRepo.findByEnum(值);//我希望控制器中有这个实体
RequestContextHolder.getRequestAttributes().setAttribute(
“XEntity”,X,RequestAttributes.SCOPE\u请求
);//我将其保存在RequestContextHolder中
返回(!value.isEmpty()&&X!=null);
}捕获(例外情况除外){
抛出新的运行时异常(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
}
@RequestMapping(值='/x',方法=RequestMethod.POST)
公共@ResponseBody
映射createX(@Validated@RequestBody DTO到DTO,BindingResult错误){
//我想在这里的实体,我从数据库回购在我的验证器
System.out.println(
RequestContextHolder.getRequestAttributes().getAttribute(
“至尊”,
RequestAttributes.SCOPE\u请求
)
);//我是从RequestContextHolder那里得到的
}
这就是我真正需要的
RequestContextHolder
在请求完成时变得清晰,并且由于setAttribute
函数中的请求范围设置,因此仅在其自己的请求线程中可用。如果使用表单对象接收请求参数,您可以验证该对象中的字段,并将其传递给controller方法。这是一个示例:否,我在自定义验证器中创建了另一个对象,我希望该对象在controller.hmm中传递。一种方法是只验证indata,然后在dto中的get方法中为该字段创建新对象。这样行吗?顺便说一句,一些代码会帮助你的项目清单使你的问题不可读。请重新措辞你的问题。不要使用项目符号列表,除非你真的在列出项目。对于一个问题,请使用普通的散文。如果使用表单对象接收请求参数,则可以验证该对象中的字段,并将其传递给控制器方法。这是一个示例:否,我在自定义验证器中创建了另一个对象,我希望该对象在controller.hmm中传递。好的。一种方法是只验证indata,然后在dto中的get方法中为该字段创建新对象。这样行吗?顺便说一句,一些代码会帮助你的项目清单使你的问题不可读。请重新措辞你的问题。不要使用项目符号列表,除非你真的在列出项目。对于一个问题,使用普通的散文。