Java JSR303bean验证可以与SpringDataREST一起使用吗?
我从文档中了解到,我可以使用某些前缀声明验证器 我使用的是JSR303,因此我的域实体使用验证注释进行注释 我可以——如果可以,如何——将JSR303bean验证与SpringDataREST一起使用吗Java JSR303bean验证可以与SpringDataREST一起使用吗?,java,spring-boot,spring-data-jpa,spring-data-rest,Java,Spring Boot,Spring Data Jpa,Spring Data Rest,我从文档中了解到,我可以使用某些前缀声明验证器 我使用的是JSR303,因此我的域实体使用验证注释进行注释 我可以——如果可以,如何——将JSR303bean验证与SpringDataREST一起使用吗 PS:我正在使用Spring Boot//编辑-根据此答案的注释提供更多信息,并相应地更改代码 有关文件- 注释 //这使处理程序成为应用程序的全局处理程序 //如果这是在@controllerbean上,那么它将是控制器的本地 @控制器建议 //指定返回一个值 @ResponseStatus(
PS:我正在使用Spring Boot//编辑-根据此答案的注释提供更多信息,并相应地更改代码 有关文件- 注释
//这使处理程序成为应用程序的全局处理程序
//如果这是在@controllerbean上,那么它将是控制器的本地
@控制器建议
//指定返回一个值
@ResponseStatus(值=HttpStatus.BAD_请求)
//要处理哪个异常
@ExceptionHandler(ConstraintViolationException.class)
//指定使返回值为JSON。
@应答器
//该类用于建模我们返回的错误。
//(如果您觉得HashMap更干净,也可以使用它)
类约束ViolationModel{
这是一个Spring的异常处理程序,应该可以在Spring引导中正常工作
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class ExceptionHandlingController {
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public @ResponseBody List<ConstraintViolationModel> handleConstraintViolation(
HttpServletRequest req, final ConstraintViolationException exception) {
ArrayList<ConstraintViolationModel> list = new ArrayList<ConstraintViolationModel>();
for (ConstraintViolation<?> violation : exception
.getConstraintViolations()) {
list.add(new ConstraintViolationModel(violation.getPropertyPath()
.toString(), violation.getMessage(), violation
.getInvalidValue()));
}
return list;
}
private static class ConstraintViolationModel {
public String field;
public String message;
public Object invalidValue;
public ConstraintViolationModel(String field, String message,
Object invalidValue) {
this.field = field;
this.message = message;
this.invalidValue = invalidValue;
}
}
}
import java.util.ArrayList;
导入java.util.List;
导入javax.servlet.http.HttpServletRequest;
导入javax.validation.ConstraintViolation;
导入javax.validation.ConstraintViolationException;
导入org.springframework.http.HttpStatus;
导入org.springframework.web.bind.annotation.ControllerAdvice;
导入org.springframework.web.bind.annotation.ExceptionHandler;
导入org.springframework.web.bind.annotation.ResponseBody;
导入org.springframework.web.bind.annotation.ResponseStatus;
@控制器建议
公共类例外处理控制器{
@ResponseStatus(值=HttpStatus.BAD_请求)
@ExceptionHandler(ConstraintViolationException.class)
public@ResponseBody列表handleConstraintViolation(
HttpServletRequest请求,最终约束ViolationException(异常){
ArrayList=新建ArrayList();
对于(约束冲突:异常
.getConstraintViolations()){
添加(新的ConstraintViolationModel(violation.getPropertyPath())
.toString(),违例。getMessage(),违例
.getInvalidValue());
}
退货清单;
}
私有静态类ConstraintViolationModel{
公共字符串字段;
公共字符串消息;
公共客体无效价值;
public ConstraintViolationModel(字符串字段、字符串消息、,
对象无效值){
this.field=字段;
this.message=消息;
this.invalidValue=invalidValue;
}
}
}
这似乎有效:
@Configuration
protected static class CustomRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
@Autowired
private Validator validator;
@Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", validator);
validatingListener.addValidator("beforeSave", validator);
}
}
要自定义spring数据rest配置,请注册一个
RepositoryRestConfigurer
(或扩展RepositoryRestConfigurerAdapter
),并为特定用例实现或覆盖configureValidatingRepositoryEventListener
方法
public class CustomRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter {
@Autowired
private Validator validator;
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", validator);
validatingListener.addValidator("beforeSave", validator);
}
}
这(validatingListener.addValidator(“beforeCreate”,validator);
)并不能完全工作,因为验证只管理实体
因此,例如,如果您尝试对非实体进行验证,您会得到一个严重错误,即org.springframework.beans.NotReadablePropertyException:bean类[…非实体的…]的无效属性“…”:Bean属性“..”不可读或具有无效的getter方法:getter的返回类型是否与setter的参数类型匹配?
虽然显然更费力,但您可以直接在验证器上手动执行验证,例如:
@Component("beforeSaveListingValidator")
public class BeforeSaveListingValidator implements Validator {
@Autowired
private LocalValidatorFactoryBean validator;
@Override
public void validate(Object object, Errors errors) {
BindingResult bindingResult = new BeanPropertyBindingResult(object, errors.getObjectName());
validator.validate(object, bindingResult);
errors.addAllErrors(bindingResult);
是的,您的陈述是正确的,但此验证异常直接来自JPA,因此是500。当使用编码验证程序时,Spring Data Rest返回400,并有错误响应。我希望此行为也与注释一起出现。可能我的q不够清楚。再次感谢Zergleb。Spring Data Rest已包含此.Se的功能e也是我自己的答案。创建了自动/可配置的改进请求:另一种方法是在Spring数据REST文档中正确记录这一点:在方法configureValidatingRepositoryEventListener()中创建验证器实例的问题is-validator无法访问其他spring管理的bean。最好在应用程序上下文中定义validator bean,并在CustomRepositoryRestMVCCConfiguration中定义autowire,如上图所示。也许我来晚了一点,但如何使用事件并将@Valid放在参数上?如果使用spring Boot,请查看此问题。要保持Spring Boot自动配置,您应该扩展SpringBootRepositoryRestMvcConfiguration的可能重复项
@Component("beforeSaveListingValidator")
public class BeforeSaveListingValidator implements Validator {
@Autowired
private LocalValidatorFactoryBean validator;
@Override
public void validate(Object object, Errors errors) {
BindingResult bindingResult = new BeanPropertyBindingResult(object, errors.getObjectName());
validator.validate(object, bindingResult);
errors.addAllErrors(bindingResult);