我正在构建一个Sping Boot 应用程序,并尝试为一些DTO/实体实现自定义验证,我将在服务层中验证这些DTO/实体。基于有关此问题的Spring文档,我认为实现此目的的一种方法是实现org.springframework.validation.Validator
接口。
作为一个最小、完整、可重现的示例,请考虑以下代码:
Spring初始化程序引导项目
在src/main/java/com.example.usingvalidation
中添加以下代码:
第一个
如果我点击端点触发验证,什么也不会发生。我看到calling validate
日志消息。但是errors对象是空的。PersonValidater
中没有任何日志消息被记录,所以很明显没有调用到达那里。
我的问题是:我如何向Spring * 注册 * 我的验证器,以便可以使用该验证器?
我已经浏览了多次文档和数百个SO问题(如X1 E0 F1 X),但无济于事。
附加信息
- 如果有任何像
@NotNull
这样的JSR-303注解,那么当前的设置将拾取与JSR-303验证相关的错误。但这不是我需要的,我需要它来使用我的自定义验证器。 - 我看到其他SO问题,其中
InitBinder
在控制器中用于向Spring注册验证器,但我不想这样做,因为我计划在服务层中进行这些自定义验证。
4条答案
按热度按时间vhmi4jdf1#
这对您不起作用的主要原因是您尚未向DataBinder注册验证器。
对控制器进行一些更改。不是自动连接
LocalValidatorFactoryBean
,而是将验证器自动连接到控制器中,并将它们注册到DataBinder。您的控制器方法也将变得更简单,因为您不再需要显式调用ValidatorFactory,当您向方法参数添加@Valid注解时,Spring将自动调用验证器。向方法添加
BindingResult
参数,所有来自验证器的错误都将出现在BindingResult错误中,这包括由javax验证导致的错误,如@Min、@Max、@NotNull、等等。当你想在服务层做这个的时候,你就不得不写你自己的逻辑来处理这个。Spring并没有做任何神奇的事情来调用自定义验证。这是有意的,进入你的应用程序是通过控制器的,这是一个你对输入的数据有有限控制的地方,所以如果你想验证,它应该在这里处理。控制器下游的Person对象的每一个变化都是您完全控制的。如果您觉得绝对必须在服务层进行验证,那么您将自己编写,坦率地说,我不会为此使用Spring的Validator实现。如果您执意要在服务层中执行此操作,这里有一种方法可以实现。
创建要应用于
Person
类的注解将上面的注解添加到
Person
类中。将您的PersonValidator修改为
ConstraintValidator
,我已经提供了一个实现来验证Person上的两个字段。在服务类中,注入一个Validator并在方法中调用它,这将调用您已定义并添加到
Person
的ConstraintValidator
您可以用AOP做一些奇妙的事情,以Spring在控制器端所做的方式自动完成这一工作,但我将留给您去发现。
svgewumm2#
你应该用
@Validated
注解你的控制器,别忘了把spring-boot-starter-validation
添加到你的pom中。de90aj5v3#
经过一番幸运的搜索,从这篇文档中得到了启示https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/validation.html#validation-binder
我讨厌写自定义注解,所以我们来了。
验证器类
public class PersonValidator implements Validator
的类保持原样,它是迄今为止封装“validator类”最好的类。AOP类
这个AOP类,在方法“保存”执行之前“神奇地”截取。
异常处理程序
处理“AOP类”抛出的异常
就是这样。也许你想知道“@RestControllerAdvice”的关键字。是的,它是专为控制器设计的(可能是!如果我错了,请纠正)。
但是,不用担心它也可以使用原生java“try catch”来处理。例如:
vql8enpb4#
如果你想以注解的形式创建你自己的验证器。下面的信息将帮助你。
我已经在我的项目中创建了我自己的验证器来验证用户给出的标记。它验证空格和#的标记。下面代码中的**@Hashtag**注解是我的自定义注解。
首先,您需要确定注解名称并声明一个接口,如下所示:(此接口将由java类“HashtagConstraintValidator”实现,您将在其中提供验证逻辑)
实作类别
您需要在控制器中使用@Valid和BindingResult来捕获验证错误并将错误发送回用户。
如果您使用thymeleaf作为模板,下面的代码将在UI上向用户显示错误