# JSR303数据校验 ​ JSR303是Java为Bean数据合法性校验提供给的标准框架,已经包含在 JavaEE6.0 中、JSR303通过在Bean 属性中标注类似 @NotNull @Max 等标准的注解指定校验规则并通过标准的验证接口对 Bean进行验证 ### 注解 ### JSR303中含有的注解 ``` @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=) 被注释的元素必须符合指定的正则表达式 ``` #### Hibernate Validator 附加的注解 ``` @NotBlank(message =) 验证字符串非null,且长度必须大于0 @Email 被注释的元素必须是电子邮箱地址 @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内 @NotEmpty 被注释的字符串的必须非空 @Range(min=,max=,message=) 被注释的元素必须在合适的范围内 注:HIbernate Validator是JSR303的一个参考实现,除了支持所有标准的校验注解外,另外HIbernate Validator还有JSR-380的实现 ``` ### SpringMVC中使用JSR303进行服务器端验证 a. 添加相关依赖 org.hibernate hibernate-validator 6.0.7.Final b. 给校验对象的指定属性添加校验规则 public class User { private Long userId; @NotBlank(message = "用户名不能为空") private String userName; @NotBlank(message = "密码不能为空") private String userPwd; ............ } c. 在请求处理方法中,使用@Validated或@Valid注解要验证的对象,并根据BindingResult判断校验是否通过 另外,验证参数后必须紧跟BindingResult参数,否则spring会在校验不通过时直接抛出异常 public String login(@Validated @ModelAttribute User user, BindingResult bindingResult){ // 服务器端校验不通过 if (bindingResult.hasErrors()) { return "login"; } .... } 注1:@Valid和Validated的区别,随便使用哪个都行 @Valid是使用hibernate validation的时候使用 @Validated 是只用spring Validator校验机制使用 ### 在JSP页面上通过form标签显示消息 显示表单所有错误 显示特定表单对象属性的错误 delimiter:如果一个属性有多个错误,错误信息的分隔符。默认是换行 注1:errors标签要放到form标签中才能显示错误消息 注2:如果使用form:errors标签不显示错误消息,请检查Model中是否已经添加了命令对象,没有是不会显示错误消息的 注3:注意命名规范,Book-->book @ModelAttribute public void init(Model model) { System.out.println("init..."); model.addAttribute("user", new User()); } ### 通过BindingResult和form:errors标签在JSP页面显示非验证消息 public String login(@Valid @ModelAttribute Yh yh, BindingResult bindingResult, Model model){ bindingResult.rejectValue("yhzh", null, "帐号错误"); ... } bindingResult.rejectValue("email", "validate.email.empty", "邮箱不能为空");//这个函数有好几个重载的变体 它们是可以支持国际化的。 比如,上面这个例子表示, 错误的字段(filed)是“email”, errorCode是“validate.email.empty”, 与资源文件对应, 第三个是defaultMessage 作业1:从BindingResult对象获得错误消息,生成基于json字符串返回到客户端 如何实现分组校验 2.1 通过接口定义若干个分组 2.2 给校验对象的指定属性添加校验规则,并指定校验组 2.3 在请求处理方法中,使用@Validated标记要验证的对象,并指定校验组 还可以对验证进行分组(@Validated) public class Book { // 书本验证分组 public static interface ValidateGroups { // 新增/修改 public static interface AddEdit { } // 上架/下架 public static interface DeployUndeploy { } // 更新封面 public static interface UpdateBookImage { } } private Long bookId; @NotBlank(message = "书名不能为空", groups = { AddEdit.class }) private String bookName; private String bookNamePinyin; @NotNull(message = "类别不能为空", groups = { AddEdit.class }) private Long bookCategoryId; @NotBlank(message = "作者不能为空", groups = { AddEdit.class }) private String bookAuthor; @NotNull(message = "价格不能为空", groups = { AddEdit.class }) @Min(value = 1, message = "价格不能为负") private Double bookPrice; private Long bookImage; @NotBlank(message = "出版社不能为空", groups = { AddEdit.class }) private String publishing; @NotBlank(message = "简介不能为空", groups = { AddEdit.class }) private String bookDesc; private Integer bookState; private Date deployDatetime; private Integer salesVolume; } @RequestMapping("/add") public String add( @Validated(value = Book.BookGroups.Add.class) @ModelAttribute Book book, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "admin/addBook"; } return "admin/addBook"; } 3. 通过分组来指定顺序 @GroupSequence({First.class, Second.class, User.class})