`
jinnianshilongnian
  • 浏览: 21435978 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2405365
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:2997971
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5631665
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:257613
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1593281
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:249002
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5847801
Group-logo
跟我学Nginx+Lua开...
浏览量:698233
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:780585
社区版块
存档分类
最新评论

Spring3.1 对Bean Validation规范的新支持(方法级别验证)

阅读更多

 


上接
Spring提供的BeanPostProcessor的扩展点-1继续学习。

 

一、Bean Validation框架简介

 写道
Bean Validation standardizes constraint definition, declaration and validation for the Java platform.

大体意思是:Bean Validation 标准化了Java平台的约束定义、描述、和验证。

 

详细了解请参考:http://beanvalidation.org/

 

Bean Validation现在一个有两个规范:

 

1Bean Validation 1.0JSR-303

 写道
This JSR will define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.

定义了基于注解方式的JavaBean验证元数据模型和API,也可以通过XML进行元数据定义,但注解将覆盖XML的元数据定义。

 

详细了解请参考:http://jcp.org/en/jsr/detail?id=303

 

JSR-303主要是对JavaBean进行验证,如方法级别(方法参数/返回值)、依赖注入等的验证是没有指定的。因此又有了JSR-349规范的产生。

 

2Bean Validation 1.1JSR-349

 写道
Bean Validation standardizes constraint definition, declaration and validation for the Java platform.

Bean Validation 标准化了Java平台的约束定义、描述、和验证。

 

此规范目前处于草案状态,详细了解请参考:http://jcp.org/en/jsr/detail?id=349.

 

该草案现在主要内容:

方法级别验证支持(验证方法参数和和返回值);

依赖注入验证的支持。

  

Bean Validation的详细介绍可参考Bean Validation官网查看http://beanvalidation.org/


Spring3.1目前已经完全支持依赖注入验证和方法级别验证的支持,只是不是原生的(规范还是草案)。


Bean Validation 1.0的参考实现有Hibernate Validator(下载地址:http://www.hibernate.org/subprojects/validator.html);1.1还处于草案状态。

 

二、Bean Validation在开发中的位置


 


 

 

上图摘自hibernate validator 参考文档,从图中可以看出,我们可以在任何位置实施验证。

 

1、表现层验证:SpringMVC提供对JSR-303的表现层验证;

2、业务逻辑层验证:Spring3.1提供对业务逻辑层的方法验证(当然方法验证可以出现在其他层,但笔者觉得方法验证应该验证业务逻辑);

3DAO层验证:Hibernate提供DAO层的模型数据的验证(可参考hibernate validator参考文档的7.3. ORM集成)。

4、数据库端的验证:通过数据库约束来进行;

5、客户端验证支持:JSR-303也提供编程式验证支持。

 

对于DAO层和客户端验证支持不在我们示例范围,忽略,感兴趣的同学可以参考《hibernate validator reference》(有中文)。

  

在测试支持大家需要准备好如下jar包:

validation-api-1.0.0.GA.jar

hibernate-validator-4.2.0.Final.jar

 

四、Spring3.0支持表现层验证

可以参考我的《最新SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结》或《SpringMVC 使用JSR-303进行校验 @Valid》。

 

此处不再阐述。

 

五、Spring3.0支持依赖注入验证(Bean Validation 1.1草案)

Spring3.0开始支持对依赖注入的依赖进行验证。Spring对依赖注入验证支持请参考《Spring开闭原则的表现-BeanPostProcessor扩展点-2》中的BeanValidationPostProcessor

 

示例:

1Bean组件类定义

public class UserModel {
    @NotNull(message = "user.username.null")
    @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")
    private String username;
    @Size(min = 5, max=10, message = "password.length.illegal")
    private String password;
    //省略setter/getter
}

 2、开启依赖注入验证支持(spring-config-bean-validator.xml

<!--注册Bean验证后处理器-->
<bean class="org.springframework.validation.beanvalidation.BeanValidationPostProcessor"/>

 3BeanXML配置定义(spring-config-bean-validator.xml

<bean id="user" class="com.sishuok.validator.UserModel">
    <property name="username" value="@"/>
    <property name="password" value="#"/>
</bean>

 4、测试用例

@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:spring-config-bean-validator.xml"})
public class BeanValidatorTest {
    @Autowired
    UserModel user;
    @Test
    public void test() {
    }
}

 5、运行测试后,容器启动失败并将看到如下异常:

java.lang.IllegalStateException: Failed to load ApplicationContext
……
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'user' defined in class path resource [spring-config-bean-validator.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Bean state is invalid: password - password.length.illegal; username - user.username.illegal
……
Caused by: org.springframework.beans.factory.BeanInitializationException: Bean state is invalid: password - password.length.illegal; username - user.username.illegal

 我们可以看出 用户名验证失败。

 

六、Spring3.1支持方法级别验证(Bean Validation 1.1草案)

Spring3.1开始支持方法级别的验证。Spring对方法级别的验证支持请参考《Spring开闭原则的表现-BeanPostProcessor扩展点-2》中的MethodValidationPostProcessor

 

有了方法级别验证,我们就能够更加简单的在Java世界进行契约式设计了,关于契约式设计请参考《建造无错软件:契约式设计引论》。

 

没有MethodValidationPostProcessor之前我们可能这样验证:

public UserModel get(Integer uuid) {
    //前置条件
    Assert.notNull(uuid);
    Assert.isTrue(uuid > 0, "uuid must lt 0");

    //获取 User Model
    UserModel user = new UserModel(); //此处应该从数据库获取

    //后置条件
    Assert.notNull(user);
    return user;
}

前置条件和后置条件的书写是很烦人的工作。

 

有了MethodValidationPostProcessor之后我们可以这样验证:

public @NotNull UserModel get2(@NotNull @Size(min = 1) Integer uuid) {
    //获取 User Model
    UserModel user = new UserModel(); //此处应该从数据库获取
    return user;
}

 

前置条件的验证:在方法的参数上通过Bean Validation注解进行实施;

后置条件的验证:直接在返回值上通过Bean Validation注解进行实施。 

非常好,非常好,自此我们可以在Java世界进行更完美的契约式编程了。

 

示例:

1Service类定义

@Validated      //① 告诉MethodValidationPostProcessor此Bean需要开启方法级别验证支持
public class UserService {
    public @NotNull UserModel get2(@NotNull @Min(value = 1) Integer uuid) { //②声明前置条件/后置条件
        //获取 User Model
        UserModel user = new UserModel(); //此处应该从数据库获取
        if(uuid > 100) {//方便后置添加的判断(此处假设传入的uuid>100 则返回null)
            return null;
        }
        return user;
    }
}

 2、开启Spring3.1对方法级别验证支持(spring-config-method-validator.xml

<!--注册方法验证的后处理器-->
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

 3BeanXML配置定义(spring-config-method-validator.xml

<bean id="userService" class="com.sishuok.validator.UserService"/>

 4、测试用例

@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:spring-config-method-validator.xml"})
public class MethodValidatorTest {
    @Autowired
    UserService userService;
    @Test
    public void testConditionSuccess() {//① 正常流程 
        userService.get2(1);
    }
    @Test(expected = org.hibernate.validator.method.MethodConstraintViolationException.class)
    public void testPreCondtionFail() { //②错误的uuid(即前置条件不满足)
        userService.get2(0);
    }

    @Test(expected = org.hibernate.validator.method.MethodConstraintViolationException.class)
    public void testPostCondtionFail() { //③不满足后置条件的返回值
        userService.get2(10000);
    }
}

通过如上测试,我们可以看出Spring3.1已经非常好的支持契约式编程了。

 

注意,在使用方法级别验证时:

1、由于Bean Validation1.1正处于草案状态,Spring3.1无法支持原生的Bean Validation1.1,在未来的Bean Validation1.1发布时会直接使用原生的。

2Spring3.1需要使用Hibernate Validator 4.2及更高版本。

 

让我们期待Bean Validation 1.1的发布吧。

 

 

 

17
6
分享到:
评论
19 楼 javatozhang 2016-10-19  
dohongdayi 写道
jinnianshilongnian 写道
dohongdayi 写道
@Validated
@Transactional
public interface UserService {

	UserModel login(@NotBlank String account, @NotEmpty String password);

}


我在以下接口应用MethodValidationPostProcessor和Spring注解式事务后发现:

验证参数之前就先开启了事务(获得了DB连接),我认为应该先验证输入,验证失败后直接抛出异常,验证成功再开启事务,这样对业务层的性能才更好,不知道楼主怎么看,Spring这样设计的理由是什么?

这个可以修改它们的order来完成;不能使用<tx:ann……> 注册 ,手工注册相应的bean指定order即可


经过不懈努力,终于将验证切面放在了事务切面外:


<!-- 这个标签上可以写order,默认是Integer.MAX_VALUE -->
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="validator" class="com.gmail.dohongdayi.ssh.common.validation.ValidatorFactoryBean">
	<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
	<!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties
	<property name="validationMessageSource" ref="messageSource" /> -->
</bean>

<bean id="validationPointcut" class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
	<constructor-arg index="0" value="org.springframework.validation.annotation.Validated" />
	<constructor-arg index="1" value="true" />
</bean>


<bean id="validationAdvice" class="org.springframework.validation.beanvalidation.MethodValidationInterceptor">
	<constructor-arg index="0" ref="validator" />
</bean>

<!-- 替代MethodValidationPostProcessor,让验证切面的advisor加入到Spring AOP的AspectJAwareAdvisorAutoProxyCreator的advised -->
<aop:config>
	<!-- 通过order指定验证优先于事务(100 < Integer.MAX_VALUE) -->
	<aop:advisor pointcut-ref="validationPointcut" advice-ref="validationAdvice" order="100" />
</aop:config>

厉害超级赞
18 楼 javatozhang 2016-10-19  
yxb1990 写道
有一个大坑,在spring mvc post方法中,配置了@NotBlank username的注解后,如果前端不写username字段, 则不会进入这个post方法,搞了一天。

问题描述的不太清晰呀
17 楼 javatozhang 2016-10-19  
liveandevil 写道
help help!!!
为什么我这么写不起作用?
@Service
@Validated
public class BusinessServiceImpl implements BusinessService {
/** {@inheritDoc} */
@NotNull(message="Null returns are not permitted")
public String convertToUpperCase(@NotEmpty(message="Input must not be null or empty.")String input) {

if ("returnnull".equalsIgnoreCase(input)) {
return null;
}
return input.toUpperCase();
}

}
配置文件是:
<!-- 指定自己定义的validator --> 
    <mvc:annotation-driven validator="validator"/>
 
    <!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册--> 
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties --> 
        <property name="validationMessageSource" ref="messageSource"/> 
    </bean>
    <!--注册方法验证的后处理器--> 
    <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

个人认为<!-- 指定自己定义的validator -->
    <mvc:annotation-driven validator="validator"/>
  是控制层代码, 而<!--注册方法验证的后处理器--> 
    <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>是你业务逻辑层代码是不是配置文件配置问题。
16 楼 yxb1990 2015-03-24  
有一个大坑,在spring mvc post方法中,配置了@NotBlank username的注解后,如果前端不写username字段, 则不会进入这个post方法,搞了一天。
15 楼 liveandevil 2014-07-17  
help help!!!
为什么我这么写不起作用?
@Service
@Validated
public class BusinessServiceImpl implements BusinessService {
/** {@inheritDoc} */
@NotNull(message="Null returns are not permitted")
public String convertToUpperCase(@NotEmpty(message="Input must not be null or empty.")String input) {

if ("returnnull".equalsIgnoreCase(input)) {
return null;
}
return input.toUpperCase();
}

}
配置文件是:
<!-- 指定自己定义的validator --> 
    <mvc:annotation-driven validator="validator"/>
 
    <!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册--> 
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties --> 
        <property name="validationMessageSource" ref="messageSource"/> 
    </bean>
    <!--注册方法验证的后处理器--> 
    <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
14 楼 wenxiang_tune 2014-05-12  
loginuser.username.illegal=用户名长度必须在${min}到${max}之间
输出的错误是
message: "用户名长度必须在$min到$max之间"
没有对${}做处理,怎么解决呢?
13 楼 dohongdayi 2014-02-16  
jinnianshilongnian 写道
dohongdayi 写道
@Validated
@Transactional
public interface UserService {

	UserModel login(@NotBlank String account, @NotEmpty String password);

}


我在以下接口应用MethodValidationPostProcessor和Spring注解式事务后发现:

验证参数之前就先开启了事务(获得了DB连接),我认为应该先验证输入,验证失败后直接抛出异常,验证成功再开启事务,这样对业务层的性能才更好,不知道楼主怎么看,Spring这样设计的理由是什么?

这个可以修改它们的order来完成;不能使用<tx:ann……> 注册 ,手工注册相应的bean指定order即可


经过不懈努力,终于将验证切面放在了事务切面外:


<!-- 这个标签上可以写order,默认是Integer.MAX_VALUE -->
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="validator" class="com.gmail.dohongdayi.ssh.common.validation.ValidatorFactoryBean">
	<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
	<!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties
	<property name="validationMessageSource" ref="messageSource" /> -->
</bean>

<bean id="validationPointcut" class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
	<constructor-arg index="0" value="org.springframework.validation.annotation.Validated" />
	<constructor-arg index="1" value="true" />
</bean>


<bean id="validationAdvice" class="org.springframework.validation.beanvalidation.MethodValidationInterceptor">
	<constructor-arg index="0" ref="validator" />
</bean>

<!-- 替代MethodValidationPostProcessor,让验证切面的advisor加入到Spring AOP的AspectJAwareAdvisorAutoProxyCreator的advised -->
<aop:config>
	<!-- 通过order指定验证优先于事务(100 < Integer.MAX_VALUE) -->
	<aop:advisor pointcut-ref="validationPointcut" advice-ref="validationAdvice" order="100" />
</aop:config>
12 楼 jinnianshilongnian 2014-02-15  
dohongdayi 写道
@Validated
@Transactional
public interface UserService {

	UserModel login(@NotBlank String account, @NotEmpty String password);

}


我在以下接口应用MethodValidationPostProcessor和Spring注解式事务后发现:

验证参数之前就先开启了事务(获得了DB连接),我认为应该先验证输入,验证失败后直接抛出异常,验证成功再开启事务,这样对业务层的性能才更好,不知道楼主怎么看,Spring这样设计的理由是什么?

这个可以修改它们的order来完成;不能使用<tx:ann……> 注册 ,手工注册相应的bean指定order即可
11 楼 dohongdayi 2014-02-13  
@Validated
@Transactional
public interface UserService {

	UserModel login(@NotBlank String account, @NotEmpty String password);

}


我在以下接口应用MethodValidationPostProcessor和Spring注解式事务后发现:

验证参数之前就先开启了事务(获得了DB连接),我认为应该先验证输入,验证失败后直接抛出异常,验证成功再开启事务,这样对业务层的性能才更好,不知道楼主怎么看,Spring这样设计的理由是什么?
10 楼 hellostory 2013-09-13  
jinnianshilongnian 写道
osacar 写道
PTZhuf 写道
jinnianshilongnian 写道
osacar 写道
jinnianshilongnian 写道
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。


这样的话确实是个问题啊。因为通常做开发的时候一个实体会有一二十个属性是很平常的。就如上面说的那个user,还可能有email,city,qq,msn,ip,credit等属性,如果只更新其中的一部分属性,那也要单独收集?那这个校验不是用不上了?还得单独再校验,岂不是又回到了原来的老路上了?我想请教一下一般是怎么解决的。


1、最简单的方式 是把所有数据传到界面;
2、不开启自动验证,而是自己手工调用验证API进行验证。

这个问题是无法避免的


这个问题是不是考虑使用Constrain中的groups?通过validated传入不同的阶段,使得在bean的生命周期的不同阶段,采用不同的验证方案。

不过@Validated似乎无法使用在返回值的后置验证上,要做后置验证还是得用原生的注解@NotNull之类的,这样在返回bean的时候就没办法对内部属性(设置了group的)做验证了。spring 4.0 M1也出了,已经支持了JSR349,不知道是否有什么改善。



我还是用传统的那种验证方法。
注解验证还是不能解决上面的问题。
就是后端做验证太悲催了。。。

嗯 缺点很明显,要么全部,要么没有; 没有提供开关控制;。。。。


不是有个叫做VO的东西吗?


9 楼 jinnianshilongnian 2013-05-31  
osacar 写道
PTZhuf 写道
jinnianshilongnian 写道
osacar 写道
jinnianshilongnian 写道
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。


这样的话确实是个问题啊。因为通常做开发的时候一个实体会有一二十个属性是很平常的。就如上面说的那个user,还可能有email,city,qq,msn,ip,credit等属性,如果只更新其中的一部分属性,那也要单独收集?那这个校验不是用不上了?还得单独再校验,岂不是又回到了原来的老路上了?我想请教一下一般是怎么解决的。


1、最简单的方式 是把所有数据传到界面;
2、不开启自动验证,而是自己手工调用验证API进行验证。

这个问题是无法避免的


这个问题是不是考虑使用Constrain中的groups?通过validated传入不同的阶段,使得在bean的生命周期的不同阶段,采用不同的验证方案。

不过@Validated似乎无法使用在返回值的后置验证上,要做后置验证还是得用原生的注解@NotNull之类的,这样在返回bean的时候就没办法对内部属性(设置了group的)做验证了。spring 4.0 M1也出了,已经支持了JSR349,不知道是否有什么改善。



我还是用传统的那种验证方法。
注解验证还是不能解决上面的问题。
就是后端做验证太悲催了。。。

嗯 缺点很明显,要么全部,要么没有; 没有提供开关控制;。。。。
8 楼 osacar 2013-05-31  
PTZhuf 写道
jinnianshilongnian 写道
osacar 写道
jinnianshilongnian 写道
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。


这样的话确实是个问题啊。因为通常做开发的时候一个实体会有一二十个属性是很平常的。就如上面说的那个user,还可能有email,city,qq,msn,ip,credit等属性,如果只更新其中的一部分属性,那也要单独收集?那这个校验不是用不上了?还得单独再校验,岂不是又回到了原来的老路上了?我想请教一下一般是怎么解决的。


1、最简单的方式 是把所有数据传到界面;
2、不开启自动验证,而是自己手工调用验证API进行验证。

这个问题是无法避免的


这个问题是不是考虑使用Constrain中的groups?通过validated传入不同的阶段,使得在bean的生命周期的不同阶段,采用不同的验证方案。

不过@Validated似乎无法使用在返回值的后置验证上,要做后置验证还是得用原生的注解@NotNull之类的,这样在返回bean的时候就没办法对内部属性(设置了group的)做验证了。spring 4.0 M1也出了,已经支持了JSR349,不知道是否有什么改善。



我还是用传统的那种验证方法。
注解验证还是不能解决上面的问题。
就是后端做验证太悲催了。。。
7 楼 PTZhuf 2013-05-27  
jinnianshilongnian 写道
osacar 写道
jinnianshilongnian 写道
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。


这样的话确实是个问题啊。因为通常做开发的时候一个实体会有一二十个属性是很平常的。就如上面说的那个user,还可能有email,city,qq,msn,ip,credit等属性,如果只更新其中的一部分属性,那也要单独收集?那这个校验不是用不上了?还得单独再校验,岂不是又回到了原来的老路上了?我想请教一下一般是怎么解决的。


1、最简单的方式 是把所有数据传到界面;
2、不开启自动验证,而是自己手工调用验证API进行验证。

这个问题是无法避免的


这个问题是不是考虑使用Constrain中的groups?通过validated传入不同的阶段,使得在bean的生命周期的不同阶段,采用不同的验证方案。

不过@Validated似乎无法使用在返回值的后置验证上,要做后置验证还是得用原生的注解@NotNull之类的,这样在返回bean的时候就没办法对内部属性(设置了group的)做验证了。spring 4.0 M1也出了,已经支持了JSR349,不知道是否有什么改善。
6 楼 jinnianshilongnian 2012-07-27  
osacar 写道
jinnianshilongnian 写道
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。


这样的话确实是个问题啊。因为通常做开发的时候一个实体会有一二十个属性是很平常的。就如上面说的那个user,还可能有email,city,qq,msn,ip,credit等属性,如果只更新其中的一部分属性,那也要单独收集?那这个校验不是用不上了?还得单独再校验,岂不是又回到了原来的老路上了?我想请教一下一般是怎么解决的。


1、最简单的方式 是把所有数据传到界面;
2、不开启自动验证,而是自己手工调用验证API进行验证。

这个问题是无法避免的
5 楼 osacar 2012-07-27  
jinnianshilongnian 写道
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。


这样的话确实是个问题啊。因为通常做开发的时候一个实体会有一二十个属性是很平常的。就如上面说的那个user,还可能有email,city,qq,msn,ip,credit等属性,如果只更新其中的一部分属性,那也要单独收集?那这个校验不是用不上了?还得单独再校验,岂不是又回到了原来的老路上了?我想请教一下一般是怎么解决的。
4 楼 jinnianshilongnian 2012-07-27  
osacar 写道
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?



username无论如何 都得有值。
你说的这种情况会报错。

你说的这种修改密码的情况,可以通过只收集password完成。
3 楼 osacar 2012-07-27  
    public class UserModel {  
        @NotNull(message = "user.username.null")  
        @Pattern(regexp = "[a-zA-Z0-9_]{5,10}", message = "user.username.illegal")  
        private String username;  
        @Size(min = 5, max=10, message = "password.length.illegal")  
        private String password;  
        //省略setter/getter  
    }  

上面在username上定义了@NotNull注解,那么在添加user的时候是必须的,但是如果在修改这个user时,username就不用再校验了,也就是说,form不会把username给post到后台,只post了password这个属性。这样会不会报user.username.illegal?

2 楼 jinnianshilongnian 2012-05-30  
dzj2046 写道
{This JSR will define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.

定义了基于注解方式的JavaBean验证元数据模型和API,也可以通过XML进行元数据定义,但注解将覆盖XML的元数据定义。}
这句话对吗?是不是应该为:XML的元数据定义会覆盖注解定义的

你试一下 按照上边说的 是 注解将继承并覆盖xml方式的
1 楼 dzj2046 2012-05-30  
{This JSR will define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.

定义了基于注解方式的JavaBean验证元数据模型和API,也可以通过XML进行元数据定义,但注解将覆盖XML的元数据定义。}
这句话对吗?是不是应该为:XML的元数据定义会覆盖注解定义的

相关推荐

    spring杂谈 作者zhang KaiTao

    1.8 Spring3.1 对Bean Validation规范的新支持(方法级别验证) 1.9 Spring对事务管理的支持的发展历程(基础篇) 1.10 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。 ...

    Spring_Framework_ API_5.0.5 (CHM格式)

    Bean Validation 1.1 与 Java 基准类似,许多其他框架的基准也有变化。例如: Hibernate 5 Jackson 2.6 EhCache 2.10 JUnit 5 Tiles 3 另外,请记下各种服务器最低支持版本。 Tomcat 8.5+ Jetty ...

    SpringBasic:Spring基础知识

    该项目设置为允许您使用 Spring MVC、JPA 2.0 和 Bean Validation 1.0 创建兼容的 Spring 3.1 应用程序。 它包括一个持久性单元和一些示例持久性和事务代码,向您介绍企业 Java 中的数据库访问。 该示例使用由应用...

    spring-boot-reference.pdf

    Bean Conditions 46.3.3. Property Conditions 46.3.4. Resource Conditions 46.3.5. Web Application Conditions 46.3.6. SpEL Expression Conditions 46.4. Testing your Auto-configuration 46.4.1. Simulating ...

    pangpang:我用这个项目来学习spring mvc

    该项目的设置允许您使用Spring MVC,JPA 2.0和Bean Validation 1.0创建兼容的Spring 3.1应用程序。 它包括一个持久性单元以及一些示例性持久性和事务代码,以向您介绍企业Java中的数据库访问。 该示例使用由应用...

    wechat:宠物美容师项目

    该项目设置为允许您使用 Spring MVC、JPA 2.0 和 Bean Validation 1.0 创建兼容的 Spring 3.1 应用程序。 它包括一个持久性单元和一些示例持久性和事务代码,向您介绍企业 Java 中的数据库访问。 该示例使用由应用...

    spring-framework-reference-4.1.2

    3.1. Improved Getting Started Experience .................................................................. 17 3.2. Removed Deprecated Packages and Methods ...............................................

    Struts2 in action中文版

    10.4.1 在域对象级别验证 231 10.4.2 使用验证上下文优化验证 233 10.4.3 验证继承 235 10.4.4 验证短路效应 236 10.4.5 使用注解声明验证 237 10.5 小结 239 第11章 理解国际化 240 11.1 Struts 2框架和Java i18n ...

    springmvcmybatis

    &lt;bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&gt; &lt;!-- 添加 mybatis-config配置上去。--&gt; &lt;!-- 扫描com.flong.pojo下面的所有类,减少mybatis的mapping所有实体类的...

    spring-framework-reference4.1.4

    3.1. Improved Getting Started Experience .................................................................. 17 3.2. Removed Deprecated Packages and Methods ...............................................

    struts-2.5.2-all所有jar包

    struts2-bean-validation-plugin-2.5.2.jar, struts2-cdi-plugin-2.5.2.jar, struts2-config-browser-plugin-2.5.2.jar, struts2-convention-plugin-2.5.2.jar, struts2-core-2.5.2.jar, struts2-dwr-plugin-2.5.2....

    struts-2.5.10-all所有jar包

    4.1.6.RELEASE.jar,spring-context-4.1.6.RELEASE.jar,spring-core-4.1.6.RELEASE.jar,spring-expression-4.1.6.RELEASE.jar,spring-test-4.1.6.RELEASE.jar,spring-web-4.1.6.RELEASE.jar,struts2-bean-validation-...

Global site tag (gtag.js) - Google Analytics