JSR 303数据校验

来源:互联网 发布:网络在线肝病咨询 编辑:程序博客网 时间:2024/06/05 06:23

简介

JSR 303是Java为Bean数据合法性校验所提供的标准框架,它已经包含在Java EE 6.0中。JSR 303通过在Bean属性上标注类似于@NotNull@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。 可以通过http://jcp.org/en/jsr/detail?id=303了解JSR 303的详细内容。



Maven依赖:

            <dependency>                    <groupId>org.hibernate</groupId>                    <artifactId>hibernate-validator</artifactId>                    <version>4.3.2.Final</version>            </dependency>

有时候会出现jboss-logging缺失的错误,一般是因为网速问题导致依赖jboss-logging包下载不了,我的解决办法是直接下载个对应版本的jboss-logging的Jar包扔到maven仓库里...适用于任何因网速问题缺失Jar包的maven依赖.....


mvc-servlet.xml:

<context:component-scan base-package="需要扫描的包"></context:component-scan><!-- 将除控制器外的所有资源文件交给servlet处理 --><mvc:default-servlet-handler /><!-- 将spring注解的action交给springMvc处理 --><mvc:annotation-driven></mvc:annotation-driven>


web.xml:

<context-param>        <param-name>contextConfigLocation</param-name>        <param-value>classpath:spring.xml</param-value></context-param><listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

加ContextLoaderListener的原因是下面需要用到Spring的form标签库,使用SpringMVC或者Spring国际化都需要Spring支持,意思就是说在Spring的基础上使用SpringMVC或者Spring的扩展技术,需要先配置ContextLoaderListener以及Spring框架自己的配置文件,这个配置文件称之为root(ApplicationContext.xml),根配置文件。然后在Spring的基础上使用MVC,MVC自己也需要一个配置文件,称之为hierarchy,层配置文件。先有Root,再加hierarchy。不然启动项目会抛异常。


后台验证的步骤:

1.Javabean中添加如上验证注解

2.action中使用@valid表示要验证的JavaBean, 再使用Errors或者BindingResult对象判断是否验证失败。


数据校验是基于bean的,也就是说校验的一般都是bean的字段,比如用户名、密码、邮箱、

手机号等等都可以是一个User类的字段,那么这些注解自然是加在bean的字段上,下面看个例子:

import javax.validation.constraints.Pattern;import org.hibernate.validator.constraints.NotEmpty;import org.hibernate.validator.constraints.Range;public class User {    @NotEmpty(message = "请输入用户名")    private String userName;        @NotEmpty(message = "请输入密码")    private String password;        @Range(max = 100 , min = 1 , message = "年龄范围:1 ~ 100")    private int age;        @NotEmpty(message = "请输入二次确认密码")    private String rePassword;        @NotEmpty(message = "手机号码不能为空")    private String phone;        @Pattern(regexp = "\\w+(\\.\\w)*@\\w+(\\.\\w{2,3}){1,3}" , message = "非法邮箱格式")    private String email;        public String getUserName() {            return userName;    }    public void setUserName(String userName) {            this.userName = userName;    }    public String getPassword() {            return password;    }    public void setPassword(String password) {            this.password = password;    }    public String getRePassword() {            return rePassword;    }    public void setRePassword(String rePassword) {            this.rePassword = rePassword;    }    public String getPhone() {            return phone;    }    public void setPhone(String phone) {            this.phone = phone;    }    public String getEmail() {            return email;    }    public void setEmail(String email) {            this.email = email;    }    public int getAge() {            return age;    }    public void setAge(int age) {            this.age = age;    }        @Override    public String toString() {            return "User [userName=" + userName + ", password=" + password                            + ", age=" + age + ", rePassword=" + rePassword + ", phone="                            + phone + ", email=" + email + "]";    }}


Controller层:

import javax.validation.Valid;import org.springframework.stereotype.Controller;import org.springframework.validation.Errors;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import cn.et.entity.User;@Controllerpublic class UserController {        @RequestMapping(value="reg" , method = RequestMethod.POST)        public String userReg(@Valid User user , Errors errors){                if (errors.hasErrors()) {    // 如果有一项验证失败,hasErrors就返回true                        return "/fail.jsp";                }                return "/index.jsp";        }}

这样表单提交过来的数据一旦有验证失败的项,就直接跳转到fail.jsp页面了。

当然这种做法欠妥,这个例子也只是为了演示一下后台验证的步骤,正确的做法应该是这样,  

把错误信息在错误项的输入框旁边用醒目的字体提示一下

上面提到的Errors类能够完成这个需求,或者BidingResult类也可以。

验证失败时,那些在注解中定义的错误信息,会自动保存到Errors或者BindingResult中,两者基本等价。


1.首先在action的参数列表中加个BindingResult类:

@RequestMapping(value="reg" , method = RequestMethod.POST)public String userReg(@Valid User user , BindingResult errors){        if (errors.hasErrors()) {                return "/index.jsp";        }        return "/index.jsp";}


2.在跳转的JSP中引入form标签库:

   <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>


3.在需要输出错误信息的地方:

  <form:errors path="bean的类名小写.验证的字段"></form:errors>     like this:<form:errors path="user.userName">


比如这样:



全都不合法的情况下:



注意:path属性的名字user并不等价于action方法中的@valid标识的变量名user,Spring

创建一个bean默认是以类名小写命名的。如果要在页面中使用自定义的bean名,可以这样:


使用@ModelAttribute注解设置。



注解校验只能做一些简单的最基本的校验,比如格式不合法、不能为空之类的,复杂一点的需要用逻辑实现的它就办不到了,比如用户名是否重复、手机号码是不是已被注册过、两次密码是否都相同等等,就需要用编程式校验实现,这个也很简单,看看下面这个你就知道该怎么做了:

@Controllerpublic class UserController {        @RequestMapping(value="reg" , method = RequestMethod.POST)        public String userReg(@Valid User userInfo , BindingResult errors){                                if (errors.hasErrors()) {                                                // 两次密码不相符                        if (!userInfo.getPassword().equals(userInfo.getRePassword())) {                                errors.addError(new FieldError("userInfo", "rePassword", "两次密码输入不一致"));                        }                }                                return "/index.jsp";        }}

addError方法三个参数:需要校验的对象名,校验的字段和错误信息。


然后在页面中故意输入不一致的密码后:


我们在addError方法中定义的错误消息就被带到JSP中了。这里还有个错误消息堆积的问题,意思就是不能为空、密码不一致两个错误都满足时,会有这样一种现象:


两条错误信息都会被带到页面上,这个需要自己来控制,比如一部分放到前端去校验、一部分后台校验,两者不会冲突就OK了。