返回顶部
首页 > 资讯 > 精选 >@valid注解不生效怎么办
  • 351
分享到

@valid注解不生效怎么办

2023-06-15 10:06:57 351人浏览 八月长安
摘要

这篇文章主要为大家展示了“@valid注解不生效怎么办”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“@valid注解不生效怎么办”这篇文章吧。一、背景在进行一次Controller层单测时,方法

这篇文章主要为大家展示了“@valid注解不生效怎么办”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“@valid注解不生效怎么办”这篇文章吧。

一、背景

在进行一次Controller层单测时,方法参数违反Validation约束,发现却没有抛出预期的【违反约束】异常。

方法参数上的@Valid注解不生效??

但是以TomcatWEB容器方式启动,请求该api,@Valid注解却生效了,甚是怪异。

代码如下:

@RestController@RequestMapping("/api/user/")public class UserController    @RequestMapping(value = "") public Response test(@RequestBody @Valid User user) {  ... }}

其中Test对象如下所示

@Datapublic class User {    @NotNull(message = "用户名称不能为空!")    private String name;}

单元测试代码如下,注意:这里的user对象并没有设置name属性。

@RunWith(springJUnit4ClassRunner.class)@ContextConfiguration(locations = {        "classpath:/config/spring/application-core.xml",        "classpath:/config/spring/application-mvc.xml"})@Transactional@Commitpublic class UserControllerTest {   @Autowired   private UserController controller;   @Test   public void test(){      controller.test(new User());   }}

以上UserControllerTest在进行测试的时候并未抛出参数校验ConstraintViolationException的异常。

下面是mvc配置文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="Http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <context:component-scan base-package="com.mtdp" use-default-filters="false">        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>    </context:component-scan>        <mvc:annotation-driven validator="validator"/>    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>    </bean></beans>

二、解决过程

1.测试过程

在执行单元测试的时候首先暴露出的问题是缺少EL的jar包,因为Hibernate validater执行会依赖EL的jar包。引入对应的jar即可,@see EL依赖

<dependency>    <groupId>org.glassfish</groupId>    <artifactId>jakarta.el</artifactId>    <version>3.0.3</version></dependency>

web容器默认会引这个jar,所以不需要添加。

2.原因探究

众所周知,Spring Validation只是一个抽象,真正执行参数校验的是hibernate validator,既然以Tomcat的方式能够生效。那么我们的办法:以debug的方式启动Tomcat,在org.hibernate.validator.internal.engine.ValidatorFactoryImpl#getValidator打上断点,执行Controller层API调用,看是谁调用的该方法,进而执行参数校验的。

结果发现是由HandlerMethodArgumentResolver(该接口的作用是对HandlerMethod的方法参数进行校验、解析、转换等工作)的实现类RequestResponseBodyMethodProcessor调用的。

RequestResponseBodyMethodProcessor类会转发给WebDataBinder类,由WebDataBinder最终委托给真正的Validator执行参数校验。

如下所示:

@valid注解不生效怎么办

下面是整体的调用链路:

@valid注解不生效怎么办

继而使用之前的UserControllerTest类进行测试,发现执行路径并不是如此,没有进DispatcherServlet类。

问题到此明了了,是因为测试的姿势不太对,我们应该使用Mock mvc的方式去进行测试,这样的话就会mock出一个mvc环境,路由到RequestResponseBodyMethodProcessor(标记@RequestBody或者@ResponseBody注解的参数解析器)进行处理,最终执行到方法参数校验的逻辑。

3.解决方案

修改后的测试代码如下所示,这样测试返回的结果是符合预期的,【违反约束】的异常信息被封装在了MvcResult的response字段中了。

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {        "classpath:/config/spring/application-core.xml",        "classpath:/config/spring/application-mvc.xml"})@Transactional@Commit@WebAppConfiguration@EnableWebMvcpublic class UserControllerTest {    @Autowired    private WebApplicationContext context;    private MockMvc mockMVC;    @Before    public void initMockMvc() {        mockMVC = MockMvcBuilders.webAppContextSetup(context).build();    }    @Test    public void testPage() throws Exception {        String userJSON = new Gson().tojson(new User());MvcResult mvcResult = mockMVC.perfORM(MockMvcRequestBuilders.post("/api/user").contentType(MediaType.APPLICATION_JSON).content(userJson)).andReturn();        System.out.println(mvcResult.getResponse());    }}

三、Controller 层@Valid注解原理探究

众所周知,spring mvc XML文件中如果配置了<mvc:annotation-driven>标签时,annotation-driven标签将会使用MvcNamespaceHandler中的org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser解析器进行解析。

MVC xml handler类如下:

public class MvcNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {reGISterBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());}}

org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser解析器主要是向spring容器中注册了几个mvc组件bean,分别是RequestMappingHandlerMapping,RequestMappingHandlerAdapter,ExceptionHandlerExceptionResolver,代码如下所示:

mvc:annotation-driven will registers a RequestMappingHandlerMapping, a RequestMappingHandlerAdapter, and an ExceptionHandlerExceptionResolver (among others) in support of processing requests with annotated controller methods using annotations such as @RequestMapping, @ExceptionHandler, and others.

@valid注解不生效怎么办

可以看到在上图(1)(2)处解析了<mvc:annotation-driven>中的validator属性,并将获取到的validator赋值给RequestMappingHandlerAdapter中的webBindingInitializer中的validator属性。

获取validator的方法如下所示

这里的逻辑是,如果<mvc:annotation-driven>标签里有配置validator属性,将会使用该属性引用的validator bean作为检验器执行参数校验,否则会判断classpath下是否存在JSR validator类,如果存在,将会使用FactoryBean的方式创建默认的OptionalValidatorFactoryBean。

@valid注解不生效怎么办

这个validator最终会在RequestResponseBodyMethodProcessor执行参数解析,创建WebDataBinder类时被赋值给WebDataBinder的validators属性(准确来说,应该是作为validators的一项)。

@valid注解不生效怎么办

在RequestResponseBodyMethodProcessor#validateIfApplicable方法中执行校验逻辑。binder.validate其实会路由给binder的validators执行校验。

这里的validators是spring的一个抽象,最终会转发给真实的validator(也就是配置的providerClass 类)执行参数校验。

@valid注解不生效怎么办

至此完成了标注@RequestBody注解的方法参数的校验。

@Valid注解是什么

@Valid

用于验证注解是否符合要求,直接加在变量user之前,在变量中添加验证信息的要求,当不符合要求时就会在方法中返回message 的错误提示信息。

@RestController@RequestMapping("/user")public class UserController {    @PostMapping    public User create (@Valid @RequestBody User user) {        System.out.println(user.getId());        System.out.println(user.getUsername());        System.out.println(user.getPassword());        user.setId("1");        return user;    }}

然后在 User 类中添加验证信息的要求:

public class User {    private String id;       @NotBlank(message = "密码不能为空")    private String passWord;}

@NotBlank 注解所指的 password 字段,表示验证密码不能为空,如果为空的话,上面 Controller 中的 create 方法会将message 中的"密码不能为空"返回。

当然也可以添加其他验证信息的要求:

限制说明
@Null限制只能为null
@NotNull限制必须不为null
@AssertFalse限制必须为false
@AssertTrue限制必须为true
@DecimalMax(value)限制必须为一个不大于指定值的数字
@DecimalMin(value)限制必须为一个不小于指定值的数字
@Digits(integer,fraction)限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future限制必须是一个将来的日期
@Max(value)限制必须为一个不大于指定值的数字
@Min(value)限制必须为一个不小于指定值的数字
@Past限制必须是一个过去的日期
@Pattern(value)限制必须符合指定的正则表达式
@Size(max,min)限制字符长度必须在min到max之间
@Past验证注解的元素值(日期类型)比当前时间早
@NotEmpty验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

除此之外还可以自定义验证信息的要求,例如下面的 @MyConstraint:

public class User {    private String id;    @MyConstraint(message = "这是一个测试")    private String username;}

注解的具体内容:

@Constraint(validatedBy = {MyConstraintValidator.class})@Target({ELementtype.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface MyConstraint {    String message();    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {}; }

下面是校验器:

public class MyConstraintValidator implements ConstraintValidator<MyConstraint, Object> {    @Autowired    private UserService userService;        @Override    public void initialie(@MyConstraint constarintAnnotation) {        System.out.println("my validator init");    }        @Override    public boolean isValid(Object value, ConstraintValidatorContext context) {        userService.getUserByUsername("seina");        System.out.println("valid");        return false;    }}

以上是“@valid注解不生效怎么办”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: @valid注解不生效怎么办

本文链接: https://lsjlt.com/news/279710.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • @valid注解不生效怎么办
    这篇文章主要为大家展示了“@valid注解不生效怎么办”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“@valid注解不生效怎么办”这篇文章吧。一、背景在进行一次Controller层单测时,方法...
    99+
    2023-06-15
  • Spring in action @valid验证不生效怎么办
    小编给大家分享一下Spring in action @valid验证不生效怎么办,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!解决Spring in action @valid验证不生效按照书上的示例代码来实现但是,添加了...
    99+
    2023-06-15
  • 一次踩坑记录 @valid注解不生效 排查过程
    一、背景 在进行一次Controller层单测时,方法参数违反Validation约束,发现却没有抛出预期的【违反约束】异常。 方法参数上的@Valid注解不生效?? 但是以Tomc...
    99+
    2024-04-02
  • java SpringBoot注解@Async不生效怎么解决
    这篇“java SpringBoot注解@Async不生效怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“j...
    99+
    2023-06-29
  • php extension不生效怎么办
    本文操作环境:Windows7系统、PHP7.1版、DELL G3电脑php extension不生效怎么办?解决php扩展安装不生效问题php安装扩展模块后,重启不生效的原因及解决办法在lnmp运维环境中,我们经常会碰到有些php依赖的扩...
    99+
    2015-08-13
    php extension
  • linux php.ini不生效怎么办
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。linux php.ini不生效怎么办?在linux环境下修改php.ini不生效问题排查php.ini修改后不生效主要有如下几种原因:1、修改php.ini配置文件...
    99+
    2024-04-02
  • mac php不生效怎么办
    这篇文章主要介绍了mac php不生效怎么办,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。mac php不生效的解决办法:1、在“/etc/profile”文件中增加“sud...
    99+
    2023-06-22
  • react+maxlength不生效怎么办
    本教程操作环境:Windows10系统、react18.0.0版、Dell G3电脑。react+maxlength不生效怎么办?问题描述:我有一个 React 输入,但 maxlength 不起作用。有谁知道如何解决这个问题?这是hand...
    99+
    2023-05-14
    maxLength React
  • 改css不生效怎么办
    本教程操作环境:Windows10系统、CSS3版、DELL G3电脑改css不生效怎么办?CSS样式不起作用?史上最全解决方法汇总在我们写页面时,有时会发现自己写的css样式无法生效,导致这种现象的原因有很多,下面列举一些常见的原因希望可...
    99+
    2023-05-14
    css
  • php curl exec 不生效怎么办
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。php curl exec 不生效怎么办?本地php环境不支持curl_exec的解决办法在测试安装某源码时,安装程序检测到本地php环境不支持curl_exec我果...
    99+
    2024-04-02
  • react中modal不生效怎么办
    本教程操作环境:Windows10系统、react18.0.0版、Dell G3电脑。react中modal不生效怎么办?react中使用ant组件库的modal弹窗报错解决在react项目中使用ant-design库中的modal弹窗控制...
    99+
    2023-05-14
    modal React
  • springboot2中使用@JsonFormat注解不生效怎么解决
    这篇“springboot2中使用@JsonFormat注解不生效怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“sp...
    99+
    2023-06-29
  • html引入js不生效怎么办
    这篇文章主要为大家展示了html引入js不生效怎么办,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带大家一起来研究并学习一下“html引入js不生效怎么办”这篇文章吧。html有什么特点1、简易性:超级文本标记语言版本升级采...
    99+
    2023-06-06
  • mysql字符集不生效怎么办
    导致 mysql 字符集设置后不生效的原因可能有多种:客户端和数据库字符集不一致。数据库字符集和表字符集不一致。字符集转换异常。其他因素(例如操作系统设置不正确、collation 未正...
    99+
    2024-08-01
    mysql 数据丢失
  • php.ini设置时区不生效怎么办
    本文操作环境:Windows7系统、PHP7.1版、DELL G3电脑php.ini设置时区不生效怎么办?在php.ini里边配置了依然不生效这个时候就需要打开apache来设置了打开httpd.conf在文件的末尾添加下边的这些代码 &l...
    99+
    2022-03-05
    php.ini
  • MySQL中sql_mode修改不生效怎么办
    小编给大家分享一下MySQL中sql_mode修改不生效怎么办,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!场景模拟基于业务敏感性的考虑,下面涉及的表、存储过程等...
    99+
    2023-06-14
  • css数字换行不生效怎么办
    本教程操作环境:Windows10系统、CSS3版、DELL G3电脑css数字换行不生效怎么办?css解决纯数字或字母不自动换行1.css word-break: break-all;效果:以上就是css数字换行不生效怎么办的详细内...
    99+
    2023-05-14
    换行 css
  • 如何解决Spring in action @valid验证不生效的问题
    解决Spring in action @valid验证不生效 按照书上的示例代码来实现但是,添加了验证但是没有生效。 Spring提供了校验Api是使用但是没有提供实现,所以需要自己...
    99+
    2024-04-02
  • crontab不生效怎么解决
    要解决crontab不生效的问题,可以采取以下几个步骤:1. 检查crontab文件路径:确保你正在编辑正确的crontab文件。默...
    99+
    2023-08-14
    crontab
  • @Valid注解怎么规范使用
    这篇文章主要介绍“@Valid注解怎么规范使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“@Valid注解怎么规范使用”文章能帮助大家解决问题。@Valid注解大全及用法规范注解描述@Assert...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作