Hibernate Validator

来源:互联网 发布:pycharm与python 编辑:程序博客网 时间:2024/05/12 23:47

以前在项目中使用过hibernate Validator,说说大致的情况。

1、常用的基本校验

@Null   被注释的元素必须为 null  


@NotNull    被注释的元素必须不为 null  


@AssertTrue     被注释的元素必须为 true  


@AssertFalse    被注释的元素必须为 false  


@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值  


@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值  


@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值  


@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值  


@Size(max=, min=)   被注释的元素的大小必须在指定的范围内  


@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内  


@Past   被注释的元素必须是一个过去的日期  


@Future     被注释的元素必须是一个将来的日期  


@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式  


@NotBlank(message =)   验证字符串非null,且长度必须大于0  


@Email  被注释的元素必须是电子邮箱地址  


@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内  


@NotEmpty   被注释的字符串的必须非空  


@Range(min=,max=,message=)  被注释的元素必须在合适的范围内  


2、基本用法

(1) 定义一个基本的接收参数对象,在属性字段上添加注解。

public class OrgOpenForm extends Form{/** *  */private static final long serialVersionUID = 1L;@NotEmpty(message = "{orgopen.form.bankacctname.notempty}")private String bankAcctName;//企业银行账户名称@NotEmpty(message = "{orgopen.form.bankacctno.notempty}")private String bankAcctNo;//企业银行账号@NotEmpty(message = "{orgopen.form.custname.notempty}")private String custName;//经办人姓名@NotEmpty(message = "{orgopen.form.mobile.notempty}")@Pattern(regexp = "^(1[3|4|5|8|9][0-9]\\d{8})$", message = "{orgopen.form.mobile.validate}")private String mobile;//经办人手机号码@NotEmpty(message = "{orgopen.form.verifycode.notempty}")private String verifyCode;//输入附加码public String getBankAcctName() {return bankAcctName;}public void setBankAcctName(String bankAcctName) {this.bankAcctName = bankAcctName;}public String getBankAcctNo() {return bankAcctNo;}public void setBankAcctNo(String bankAcctNo) {this.bankAcctNo = bankAcctNo;}public String getCustName() {return custName;}public void setCustName(String custName) {this.custName = custName;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}public String getVerifyCode() {return verifyCode;}public void setVerifyCode(String verifyCode) {this.verifyCode = verifyCode;}}

(2) 在spring的controller接收参数前添加注解@Valid,也可以直接在单个参数前直接加具体的校验注解。

@Controller@RequestMapping( value = "/account/openaborgaccount")public class OpenAborgAccountCtl extends BaseController {/*** * @describe 开户第一步获取用户输入的相关信息 * @param orgOpenForm * @param result * @return */@RequestMapping(value = "/orgopen")public @ResponseBody JsonResult orgopen(@Valid OrgOpenForm orgOpenForm,BindingResult result){JsonResult json = new JsonResult();json.setResult(0);try{if (result.hasErrors()) {//判断是否有参数校验失败return handleJsonValid(json, result);}//参数基本校验通过之后.....进入service处理}catch(BusiException e){handleBusiException(e);json.setResult(1);json.setErrmsg(e.getMessage());}return json;<span style="white-space:pre"></span>}}
</pre><p></p><p></p><pre name="code" class="java">public @ResponseBody JsonResult orgopen(@NotEmpty String username,BindingResult result){................}

BindingResult result必须紧跟在需要校验的参数对象之后,有参数没校验通过,错误信息就会放在BindingResult 中,之后调用父Controller中的方法统一设置错误信息,可以遍历取出所有的错误信息。

public JsonResult handleJsonValid(JsonResult obj, BindingResult result) {String firstErrormsg = result.getFieldErrors().get(0).getDefaultMessage();obj.setErrmsg(firstErrormsg);Map<String, String> err = new HashMap<String, String>();List<FieldError> list = result.getFieldErrors();FieldError error = null;for (int i = 0; i < list.size(); i++) {error = list.get(i);err.put(error.getField(), error.getDefaultMessage());}obj.set("errfields", err);obj.setResult(1);return obj;}
3、自定义校验器。基本校验器不能满足业务需求,可以自定义一个。以下三个步骤:

Create a constraint annotation (首先定义一个约束注解)
Implement a validator(第二步是实现这个验证器)
Define a default error message(最后添加一条默认的错误消息即可)

首先自定义注解:

@Target({ ElementType.FIELD })@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = AddressValidator.class)public @interface Address {    String message() default "{com.test.Address.message}";    Class<?>[] groups() default {};        Class<? extends Payload>[] payload() default { };}

接着定义一个校验类,
@Constraint(validatedBy = AddressValidator.class)可以看出这个类是<span style="font-family: Arial, Helvetica, sans-serif;">AddressValidator。</span>

比如定义一个5-30位非空字符的校验

public class AddressValidator implements ConstraintValidator<Address, String> {    public void initialize(Address annotation) {    }    public boolean isValid(String value, ConstraintValidatorContext context) {        if (value == null || value.length() <= 0) {            return true;        }        return value.matches("^\\S{5,30}$");    }}
接着就可以和hibernate自带的注解一样使用,com.test.Address.message是当校验失败出现的错误消息,统一自定义在.properties文件中。

4、类注解定义

这些基本的还是难以满足需求,经常用到的是2个参数的比较,比如密码与确认密码必须相等,参数A必须大于B等等,这就需要定义一个作用在类上的注解。

import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.*;@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = MatchesValidator.class)@Documentedpublic @interface Matches {    String message() default "{constraint.not.matches}";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};    String field();    String verifyField();}


package org.leochen.samples;import org.apache.commons.beanutils.BeanUtils;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.lang.reflect.InvocationTargetException;public class MatchesValidator implements ConstraintValidator<Matches,Object>{    private String field;    private String verifyField;    public void initialize(Matches matches) {        this.field = matches.field();        this.verifyField = matches.verifyField();    }    public boolean isValid(Object value, ConstraintValidatorContext context) {        try {            String fieldValue= BeanUtils.getProperty(value,field);            String verifyFieldValue = BeanUtils.getProperty(value,verifyField);            boolean valid = (fieldValue == null) && (verifyFieldValue == null);            if(valid){                return true;            }            boolean match = (fieldValue!=null) && fieldValue.equals(verifyFieldValue);            if(!match){                String messageTemplate = context.getDefaultConstraintMessageTemplate();                context.disableDefaultConstraintViolation();                context.buildConstraintViolationWithTemplate(messageTemplate)                        .addNode(verifyField)                        .addConstraintViolation();            }            return match;        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        }        return true;    }}

使用示例:

package org.leochen.samples;@Matches(field = "password", verifyField = "confirmPassword",                 message = "{constraint.confirmNewPassword.not.match.newPassword}")public class TwoPasswords {    private String password;    private String confirmPassword;    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public String getConfirmPassword() {        return confirmPassword;    }    public void setConfirmPassword(String confirmPassword) {        this.confirmPassword = confirmPassword;    }} 


5、组合校验

比如A输入了,B、C必须有效,D存在了,E、F、G又必须满足条件,可以用group来标记。

public class OpenAccountForm extends Form {public interface step1 {}public interface step2 {}public interface step3 {}public interface step4 {}public interface step5 {}/*@NotEmpty(message = "{account.form.loginName.notempty}", groups = step1.class)@LoginName(message = "{account.form.loginName.message}",groups = step1.class)*/private String loginName;@NotEmpty(message = "{account.form.mobile.notempty}", groups = step1.class)@Mobile(groups = step1.class)private String mobile;//@NotEmpty(message = "{account.form.email.notempty}", groups = step1.class)//@Email(groups = step1.class)private String email;@NotEmpty(message = "{account.form.tradePwd.notempty}", groups = step1.class)@TradePassword(groups = step1.class)private String tradePwd;@NotEmpty(message = "{account.form.tradePwdConfirm.notempty}", groups = step1.class)private String tradePwdConfirm;@NotEmpty(message = "{account.form.realName.notempty}", groups = {step1.class, step2.class, step3.class,step4.class })@CustName(message = "{account.form.realName.message}",groups = {step1.class, step2.class, step4.class })private String realName;@NotEmpty(message = "{account.form.bankInfo.notempty}", groups = step2.class)private String bankNo;//银行编号private String bankAcco;//银行卡卡号@NotEmpty(message = "{account.form.certNo.notempty}", groups = {step1.class, step2.class, step3.class,step4.class })private String certNo;@NotEmpty(message = "{account.form.certType.notempty}", groups = {step1.class, step2.class, step4.class })@CertType(groups = {step1.class, step2.class, step4.class })private String certType;@NotEmpty(message = "{account.form.payAmount.notempty}", groups = step3.class)@Money(message = "{account.form.payAmount.message}", groups = step3.class)private String payAmount;private String flag;    @NotEmpty(message = "{account.form.randomCode.notempty}", groups = { step5.class})private String randomCode;//验证码private String checkMobile;//第一个注册页面手机号码输入错误时是否需要重新输入public String getRandomCode1() {return randomCode1;}public void setRandomCode1(String randomCode1) {this.randomCode1 = randomCode1;}private String randomCode1;//验证码//private String private String isConvert;//是否将18位身份证转换成15位,Y  or  N@NotEmpty(message = "{account.form.bankAcco.notempty}", groups = step4.class)@BankAcctNo(groups = step2.class)private String bocbankacco;@Mobile(groups = step2.class)@NotEmpty(message = "{account.form.mobile.notempty}", groups = step4.class)private String bocmobile;@NotEmpty(message = "{account.form.identifycode.notempty}", groups = step1.class)private String identifycode;@NotEmpty(message = "{account.form.reference.notempty}", groups = step4.class)@Reference(message="{cn.jsfund.trade.validation.Reference.message}",groups = step4.class)private String reference;private String kjrandom;private String kjmobile;//四者关系验证手机号private String bankfullname; //银行名称全称(北京银行使用)格式如:XX  银行  XX  分行  XXpublic String getBankfullname() {return bankfullname;}public void setBankfullname(String bankfullname) {this.bankfullname = bankfullname;}public String getKjmobile() {return kjmobile;}public void setKjmobile(String kjmobile) {this.kjmobile = kjmobile;}public String getKjrandom() {return kjrandom;}public void setKjrandom(String kjrandom) {this.kjrandom = kjrandom;}private String confirmbankAcco;public String getConfirmbankAcco() {return confirmbankAcco;}public void setConfirmbankAcco(String confirmbankAcco) {this.confirmbankAcco = confirmbankAcco;}public String getReference() {return reference;}public void setReference(String reference) {this.reference = reference;}public String getIdentifycode() {return identifycode;}public void setIdentifycode(String identifycode) {this.identifycode = identifycode;}public String getBocbankacco() {return bocbankacco;}public void setBocbankacco(String bocbankacco) {this.bocbankacco = bocbankacco;}public String getBocmobile() {return bocmobile;}public void setBocmobile(String bocmobile) {this.bocmobile = bocmobile;}public String getIsConvert() {return isConvert;}public void setIsConvert(String isConvert) {this.isConvert = isConvert;}public String getRandomCode() {return randomCode;}public void setRandomCode(String randomCode) {this.randomCode = randomCode;}private String sex;public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getFlag() {return flag;}public void setFlag(String flag) {this.flag = flag;}public String getLoginName() {return loginName;}public void setLoginName(String loginName) {this.loginName = loginName;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getTradePwd() {return tradePwd;}public void setTradePwd(String tradePwd) {this.tradePwd = tradePwd;}public String getTradePwdConfirm() {return tradePwdConfirm;}public void setTradePwdConfirm(String tradePwdConfirm) {this.tradePwdConfirm = tradePwdConfirm;}public String getBankNo() {return bankNo;}public void setBankNo(String bankNo) {this.bankNo = bankNo;}public String getRealName() {return realName;}public void setRealName(String realName) {this.realName = realName;}public String getBankAcco() {return bankAcco;}public void setBankAcco(String bankAcco) {this.bankAcco = bankAcco;}public String getCertNo() {return certNo;}public void setCertNo(String certNo) {this.certNo = certNo;}public String getCertType() {return certType;}public void setCertType(String certType) {this.certType = certType;}public String getPayAmount() {return payAmount;}public void setPayAmount(String payAmount) {this.payAmount = payAmount;}public String getCheckMobile() {return checkMobile;}public void setCheckMobile(String checkMobile) {this.checkMobile = checkMobile;}}

6、@Valid @RequestBody这种方式貌似不支持。












































































0 0
原创粉丝点击