精华内容
下载资源
问答
  • 主要介绍了JSR303校验注解和自定义校验注解的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了Java如何使用JSR303校验数据与自定义校验注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • JSR303jar包

    2018-11-09 15:44:31
    JSR303所依赖的jar包,亲测可用,有需要可以联系我。请放心下载,使用愉快
  • JSR303 Jar包

    2018-01-09 10:30:51
    JSR303用到的jar包,本人使用的,现分享给大家,希望能给大家带来帮助
  • jsr 303 jar包下载

    2018-01-24 21:24:50
    按照课件推荐下载,准确有效,包括(hibernate-validator-4.3.2.Final.jar;jboss-logging-3.1.0.CR2.jar;validation-api-1.1.0.Alpha1.jar和jsr303约束文档)
  • 一、自定义参数校验 1、为什么要自定义? 通过学习,了解到很多常用注解了,但是呢,总是有那么些需求… 2、案例分析(手机号格式) 2.1、需要验证的实体 Bean public class LoginVo { @NotNull ...
  • hibernate validator jsr303

    2018-02-14 19:07:42
    Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现
  • jsr 303需要的jar包

    2018-05-14 15:53:18
    内涵 jboss-logging-3.1.0.CR2、hibernate-validator-4.3.2.Final、validation-api-1.0.0.GA
  • jsr303相应jar包

    2018-04-10 11:45:51
    jsr303相应jar包,用于spring框架的数据验证,直接加到lib目录下即可
  • SpringMVC JSR303数据校验DEMO(附:JSR303的JAR包) SpringMVC JSR303数据校验DEMO(附:JSR303的JAR包)
  • JSR303校验Hibernate Validator实现需要用到的jar包。hibernate-validator-5.4.1.Final.jar + jboss-logging-3.1.3.GA.jar + validation-api-1.1.0.Final.jar+classmate-1.3.3.jar + hibernate-validator-cdi-5.4.1....
  • springmvc_jsr303

    2015-12-29 15:46:37
    项目中所需的jar包在压缩包中已提供,项目中用到了JSR303和hibernate-validator的技术,大量采用了注解@NotNull,@Email,@Length,@Max,@Pattern,@Size等,此外还采用了自定义注解,验证信息全部配置在属性文件中.
  • JSR303依赖的jar包

    2018-05-18 14:10:48
    validator-5.2.4.Final.jar、hibernate-validator-annotation-processor-5.2.4.Final.jar、hibernate-validator-cdi-5.2.4.Final.jar、validation-api-1.1.0.Final.jar四个jar包,用于JSR303的校验。
  • JSR303需要用到的3个jar包。hibernate-validator-4.3.2.Final+jboss-logging-3.1.0.CR2+validation-api-1.0.0.GA
  • jsr303jar包.zip

    2020-03-22 23:22:38
    JSR303用到的jar包,本人使用的,现分享给大家,希望能给大家带来帮助 classmate-0.8.0.jar hibernate-validator-5.0.0.CR2.jar hibernate-validator-annotation-processor-5.0.0.CR2.jar jboss-logging-3.1.1...
  • jsr 303 验证日期 在本文中,我将向您展示如何使用新的Bean验证框架(又名JSR-303)。 遗产 在获得JSR 303(又名Bean验证框架)的结果之前,有两次有趣的尝试尝试验证框架。 每一个都来自层的末端,并专注于其...

    jsr 303 验证日期

    在本文中,我将向您展示如何使用新的Bean验证框架(又名JSR-303)。

    遗产

    在获得JSR 303(又名Bean验证框架)的结果之前,有两次有趣的尝试尝试验证框架。 每一个都来自层的末端,并专注于其范围。

    前端验证

    Struts是2001-2002年在表示层上学习和使用框架。 Struts使用MVC模型并专注于Controller,在带有Action Struts中表示。 视图是普通的JSP,Struts使用ActionForm以便将数据从Controller传递到View,反之亦然。 简而言之,这些是框架用于与View交互的POJO。

    作为表示层框架,Struts关注的是验证用户输入。 动作表单有一个漂亮的方法,称为validate() 。 此方法的签名如下:

    publicActionErrorsvalidate(ActionMappingmapping,HttpServletRequestrequest)

    开发人员必须检查表单是否有效,然后填写(如果不是) ActionErrors对象(基本上是List )。 然后,如果ActionErrors对象不为空,Struts会将流重定向到错误页面(输入)。 由于手动检查很无聊且容易出错,因此使这种验证自动化可能是一个好主意。 即使在那时,声明式验证也被认为是关键。

    Commons Validator徽标

    这是Apache Commons Validator的目标。 其配置通过XML进行。 您指定:

    • 您有权访问的验证器。 有一些内置的,但您可以添加自己的
    • bean和验证器之间的关联:将通过哪些规则验证哪些bean

    尽管Struts紧密集成了Commons Validator,但是您可以完全单独使用后者。 但是,最新的稳定版本(1.3.1)已于2006年末发布。当前开发的版本是1.4,但是Maven网站自2008年初以来就没有进行过更新。我的做法有些遗漏,因此我将其排除在外当我被迫使用Struts时,可以节省我的验证需求。

    在这种情况下,我必须使用它,因为Struts插件知道如何使用两个XML配置文件来生成JavaScript客户端验证。

    后端验证

    以前,我们看到第一个验证框架来自用户输入。 另一方面,由于在数据库中强制执行了约束,因此插入/更新数据不需要进行此类验证。 例如,尝试将50个字符长的字符串插入VARCHAR(20)列将失败。

    但是,让数据库处理验证有两个主要缺点:

    • 由于您需要连接到数据库,发送请求并处理错误,因此会降低性能
    • 这种错误不能轻易地映射到Java异常,如果可能的话,也可以映射到错误的特定属性

    Hibernate验证器

    最后,在将数据发送到数据库之前,最好在Java世界中验证域模型。 这就是Hibernate Validator的范围。 Commons Validator配置基于XML,而Hibernate Validator配置基于Java 5注释。

    即使Hibernate Validator旨在验证域模型,您也可以使用它来验证任何bean。

    JSR 303 Bean验证

    最终,JSR 303取得了成果。 有两个重要的事实:它是不可知的,这意味着您可以在任何喜欢的地方使用它(前端,后端,甚至是DTO(如果遵循此模式)),并且其参考实现是Hibernate Validator v4。

    JSR 303的功能包括:

    • 在两个不同级别上进行验证:属性或整个bean。 Hibernate Validator不可能做到这一点(因为它是面向数据库的),而Commons Validator却有很多限制
    • i18n准备就绪,消息已参数化
    • 可使用您自己的验证器扩展
    • 可使用注释或XML进行配置。 在下面,将仅显示注释配置

    在JSR 303中,验证是以下各项之间交互作用的结果:

    • 注释本身。 有些是JSR 303随附的,但是您可以构建自己的
    • 将验证带注释的bean的类

    最简单的例子

    最简单的示例可能包括在类的属性上设置非空约束。 这样做很简单:

    publicclassPerson{
    
      privateStringfirstName;
    
      @NotNull
      publicStringgetFirstName(){
        returnfirstName;
      }
    
      // setter
    }

    请注意,@ @NotNull批注可以放在属性或getter上(就像在JPA中一样)。 如果使用Hibernate,它也可以使用JSR 303注释来创建/更新数据库模式。

    现在,为了验证此bean的实例,您要做的就是:

    Set<ConstraintViolation<Person>>violations=validator.validate(person);

    如果集合为空,则验证成功,否则,验证失败:其原理与之前的两个框架非常相似。

    有趣的是,规范强制要求约束被继承。 因此,如果User类继承自Person ,则其firstName属性也将具有非null约束。

    约束组

    在表示层上,可能必须在两个不同的上下文(例如创建和更新)中使用相同的Form bean。 在这两种情况下,您都有不同的约束。 例如,创建个人资料时,用户名是必填项。 更新时,无法更改它,因此无需验证。

    Struts(及其忠实的盟友Commons Validator)通过将验证规则与Java类而不是映射相关联来解决此问题,因为它的范围是前端。 使用注释时,这是不可能的。 为了简化bean的重用,JSR 303引入了约束分组。 如果未指定任何内容(如前所述),则约束将分配给默认组,而在验证时,将在默认组中进行分配。

    您还可以按如下约束指定组:

    publicclassPerson{
    
      privateStringfirstName;
    
      @NotNull(groups=DummyGroup)
      publicStringgetFirstName(){
        returnfirstName;
      }
      // setter
    }

    因此,这将验证:

    Personperson=newPerson();
    // Empty set
    Set<Constraintviolation<Person>>violations=validator.validate(person);

    这还将:

    Personperson=newPerson();
    // Empty set
    Set<Constraintviolation<Person>>violations=validator.validate(person,Default.class);

    而且这不会:

    Personperson=newPerson();
    // Size 1 set
    Set<Constraintviolation<Person>>violations=validator.validate(person,DummyGroup.class);

    自定义约束

    完成内置约束(和Hibernate扩展)的使用后,您可能需要开发自己的约束。 这很简单:约束是使用@Constraint注释的注释。 让我们创建一个约束来检查未大写的字符串:

    @Target({METHOD,FIELD,ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Constraint(validatedBy=CapitalizedValidator.class)
    public@interfaceCapitalized{
    
      Stringmessage()default"{ch.frankel.blog.validation.constraints.capitalized}";
      Class<?>[]groups()default{};
      Class<?extendsPayload>[]payload()default{};
    }

    这三个元素分别用于国际化,分组(请参见上文)和传递元数据。 这些都是强制性的:如果未定义,则该框架将无法工作! 也可以添加更多元素,例如以参数化验证: @Min@Max约束使用此元素。

    注意,没有什么可以阻止将约束应用于实例而非属性,这是由@Target定义的,这是一种设计选择。

    接下来是验证类。 它必须实现ConstraintValidator<?,?>

    publicclassCapitalizedValidatorimplementsConstraintValidator<Capitalized,String>{
    
      publicvoidinitialize(Capitalizedcapitalized){}
    
      publicbooleanisValid(Stringvalue,ConstraintValidatorContextcontext){
        returnvalue==null||value.equals(WordUtils.capitalizeFully(value));
      }
    }

    就这样! 您现在要做的就是使用@Capitalized注释属性,并使用框架验证实例。 无需注册新创建的验证器。

    约束构成

    鼓励创建简单的约束,然后组合它们以创建更复杂的验证规则。 为了做到这一点,创建一个新的约束,并用您想要组成的约束对其进行注释。 让我们创建一个约束,该约束将验证String既不为null也不不大写:

    @NotNull
    @Capitalized
    @Target({METHOD,FIELD,ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Constraint(validatedBy={})
    public@interfaceCapitalizedNotNull{
    
      Stringmessage()default"{ch.frankel.blog.validation.constraints.capitalized}";
      Class<?>[]groups()default{};
      Class<?extendsPayload>[]payload()default{};
    }

    现在,用它注释您的属性并观看魔术发生!

    当然,如果要防止约束组合,则必须限制@Target值以排除ANNOTATION_TYPE

    结论

    本文仅涉及JSR 303的表面。但是,我希望它是对它的功能的不错的介绍,并希望您有进一步研究它的愿望。

    您可以在此处找到Eclipse / Maven格式的本文的源(以及更多)。

    翻译自: https://blog.frankel.ch/bean-validation-and-jsr-303/

    jsr 303 验证日期

    展开全文
  • 详细介绍了普通校验,分组校验,自定义注解校验等,全局异常处理,代码均为我自己编写,是我的学习笔记,并且发表了相关子蛾子,可以配合我的帖子查看,是一些简单的相关示例代码
  • 主要介绍了Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化的相关知识,需要的朋友可以参考下
  • 主要介绍了SpringBoot结合JSR303对前端数据进行校验的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • SpringMVC 数据的格式化、JSR 303数据校验和国际化 实例.zip 对应博客:http://blog.csdn.net/peng_hong_fu/article/details/53559773
  • JSR303.zip

    2020-04-20 15:54:08
    【原创作者田超凡,未经许可请勿转发,侵权仿冒必究】
  • 主要给大家介绍了关于Spring Boot利用JSR303实现参数验证的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • Spring验证器+JSR303.rar

    2020-06-11 21:15:52
    使用SpringMVC的验证器完成货物入库输入校验。验证入库时间,以及商品价格是否合理等。主要用到的JSR303中:@Past:验证Date和Calender对象是否在当前时间之前。@Pattern:验证String对象是否符合正则表达式的规则。
  • JSR303分组校验

    2021-08-29 23:26:09
    JSR303分组校验属于后端校验的一种很方便的方式 步骤: 1.新建两个接口,用来代表哪两个组,比如,AddGroup,UpdateGroup代表添加分组和修改分组 //添加分组 package com.jc.common.valid; public interface ...

    JSR303分组校验属于后端校验的一种很方便的方式
    步骤:

    1.新建两个接口,用来代表哪两个组,比如,AddGroup,UpdateGroup代表添加分组和修改分组

    //添加分组
    package com.jc.common.valid;
    
    public interface AddGroup {
    }
    
    //修改分组
    package com.jc.common.valid;
    
    public interface UpdateGroup {
    }
    
    
    

    2.给需要验证的实体类的字段上添加对应的校验注解,并且指定其分组

    package com.jc.gulimall.product.entity;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    
    import java.io.Serializable;
    import java.util.Date;
    
    import com.jc.common.valid.AddGroup;
    import com.jc.common.valid.UpdateGroup;
    import lombok.Data;
    import org.hibernate.validator.constraints.URL;
    
    import javax.validation.constraints.*;
    
    /**
     * 品牌
     * 
     * @author wjc
     * @email 1678912421@gmail.com
     * @date 2021-07-16 21:22:32
     */
    @Data
    @TableName("pms_brand")
    public class BrandEntity implements Serializable {
    	private static final long serialVersionUID = 1L;
    
    	/**
    	 * 品牌id
    	 */
    	@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
    	@Null(message = "添加不能添加品牌id",groups = {AddGroup.class})
    	@TableId
    	private Long brandId;
    	/**
    	 * 品牌名
    	 */
    
    
    	@NotBlank(message = "品牌名不能为空!")
    	private String name;
    	/**
    	 * 品牌logo地址
    	 */
    	@URL(message = "logo地址必须是一个合法的URL!",groups = {AddGroup.class,UpdateGroup.class})
    	@NotNull(message = "logo不能为空!",groups = {AddGroup.class,UpdateGroup.class})
    	private String logo;
    	/**
    	 * 介绍
    	 */
    	private String descript;
    	/**
    	 * 显示状态[0-不显示;1-显示]
    	 */
    	private Integer showStatus;
    	/**
    	 * 检索首字母
    	 */
    	@NotNull(message = "首字母不能为空!",groups = {AddGroup.class,UpdateGroup.class})
    	@Pattern(regexp = "/^[a-zA-Z]$/",message = "检索首字符必须是一个字母",groups = {AddGroup.class,UpdateGroup.class})
    	private String firstLetter;
    	/**
    	 * 排序
    	 */
    	@NotNull(message = "排序字段不能为空!",groups = {AddGroup.class,UpdateGroup.class})
    	@Min(value = 0,message = "排序必须大于等于0",groups = {AddGroup.class,UpdateGroup.class})
    	private Integer sort;
    
    }
    
    

    上边的logo,firstLetter,sort字段我都添加了两个分组,也就是说在修改和添加的情况下都会校验

    3.在url对应的方法参数中需要校验的实体类前加上@Validated(AddGroup.class)注解,在需要校验的实体类中标注AddGroup分组的字段进行校验,@Validated注解后边不指定分组类别,则默认是对不标注分组的字段进行校验

    	//对BrandEntity 字段中指定UpdaGroup分组的字段就行校验 
        @RequestMapping("/update")
        public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){
    		brandService.updateByid(brand);
    
            return R.ok();
        }
    
        @RequestMapping("/save")
        public R save(@Validated(AddGroup.class) @RequestBody BrandEntity brand/*, BindingResult bindingResult*/){
    
    //    统一异常处理
    //            if (bindingResult.hasErrors()){
    //                Map<String,String> map = new HashMap<>();
    //                bindingResult.getFieldErrors().stream().forEach((item)->{
    //                    String defaultMessage = item.getDefaultMessage();
    //                    String field = item.getField();
    //                    map.put(field,defaultMessage);
    //                });
    //                return R.error(400,"提交的数据不合法").put("data",map);
    //            }
    
                brandService.save(brand);
                return R.ok();
        }
    

    实践:
    在save请求中,对实体类标注了AddGroup分组,则对实体类中所有标注AddGroup的分组就行校验,
    对应上边的也就是,

    	@Null(message = "添加不能添加品牌id",groups = {AddGroup.class})
    	private Long brandId;
    	@NotNull(message = "首字母不能为空!",groups = {AddGroup.class,UpdateGroup.class})
    	@Pattern(regexp = "/^[a-zA-Z]$/",message = "检索首字符必须是一个字母",groups = {AddGroup.class,UpdateGroup.class})
    	private String firstLetter;
    	/**
    	 * 排序
    	 */
    	@NotNull(message = "排序字段不能为空!",groups = {AddGroup.class,UpdateGroup.class})
    	@Min(value = 0,message = "排序必须大于等于0",groups = {AddGroup.class,UpdateGroup.class})
    	private Integer sort;
    	@URL(message = "logo地址必须是一个合法的URL!",groups = {AddGroup.class,UpdateGroup.class})
    	@NotNull(message = "logo不能为空!",groups = {AddGroup.class,UpdateGroup.class})
    	private String logo;
    

    在这里插入图片描述
    下面我们再看没有标注任何分组的字段,也就是name字段

    	@NotBlank(message = "品牌名不能为空!")
    	private String name;
    

    我们将BrandController中的update方法中分组去掉原来是@Validated(updateGroup.class)

        @RequestMapping("/update")
        public R update(@Validated @RequestBody BrandEntity brand){
    		brandService.updateByid(brand);
    
            return R.ok();
        }
    
    

    由于除了name之外的字段都标注了分组,所以name之外的字段是不进行校验的,只有没有标注分组的name字段才进行校验。
    在这里插入图片描述

    总结:
    在需要校验的实体类中,哪个字段标注了哪个分组,就在方法参数注解中指定校验分组的情况下进行校验。
    字段没有标注分组的情况下,就在方法参数注解中没指定校验分组的情况下进行校验。

    展开全文
  • Spring - JSR303数据校验

    2020-05-14 16:00:12
    在做项目的时候需要对表单的值进行校验,只有校验通过才能提交,一般来说前端和后端都需要做校验,JSR303是做后端校验的一种方式。 JSR303简介 JSR是Java Specification Requests的缩写,意思是Java 规范提案。是...

    在做项目的时候需要对表单的值进行校验,只有校验通过才能提交,一般来说前端和后端都需要做校验,JSR303是做后端校验的一种方式。

    JSR303简介

    JSRJava Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务,JSR已成为Java界的一个重要标准。
    JSR-303JAVA EE 6 中的一项子规范,叫做Bean ValidationHibernate ValidatorBean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint

    一、Bean Validation 中内置的 constraint

    在这里插入图片描述

    二、Hibernate Validator 附加的 constraint

    在这里插入图片描述
    更多的constraint请见百度。

    JSR303的使用

    下文需要的基础返回类型 - R
    public class R extends HashMap<String, Object> {
    	private static final long serialVersionUID = 1L;
    	
    	public R() {
    		put("code", 0);
    		put("msg", "success");
    	}
    	
    	public static R error() {
    		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
    	}
    	
    	public static R error(String msg) {
    		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
    	}
    	
    	public static R error(int code, String msg) {
    		R r = new R();
    		r.put("code", code);
    		r.put("msg", msg);
    		return r;
    	}
    
    	public static R ok(String msg) {
    		R r = new R();
    		r.put("msg", msg);
    		return r;
    	}
    	
    	public static R ok(Map<String, Object> map) {
    		R r = new R();
    		r.putAll(map);
    		return r;
    	}
    	
    	public static R ok() {
    		return new R();
    	}
    
    	public R put(String key, Object value) {
    		super.put(key, value);
    		return this;
    	}
    }
    

    一、常规使用

    1、标注校验注解

    给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示。

    // Brand对象里的属性
    @NotBlank(message = "品牌名至少包含一个非空字符")
    private String name;  // 品牌名
    
    @NotNull(message = "必须指定品牌Id")
    private Long id;      // 品牌id
    
    @URL(message = "logo必须是一个合法的url地址")       // URL校验
    private String logo;  // 品牌logo的url
    
    @NotEmpty
    @Pattern(regexp = "^[a-zA-Z]", message = "检索首字母必须是一个字母")   // 正则校验
    Private String firstLetter;   // 品牌首字母,如小米就是X
    
    @NotNull
    @Min(value = 0, message = "排序必须大于等于0")
    private Integer sort;        // 排序字段
    
    2、开启校验功能

    在需要校验的对象前添加@Valid注解开启校验功能,在被校验的对象之后添加BindingResult对象可以获取校验结果。

    // Controller层,返回的是JSON数据(即@RestController)
    @RequestMapping("/save")
    public R save(@Valid @RequestBody Brand brand, BindingResult result){
    	if(result.hasErrors()){   // 获取校验的错误结果
    		Map<String, String> resultMap = new HashMap<>();
    		result.getFieldErrors().forEach((item) -> {
    			// 获取错误的校验消息
    			String message = item.getDefaultMessage();
    			// 获取错误的属性名
    			String field = item.getField();
    			resultMap.put(field,message);
    		});
    		return R.error(400,"提交的数据不合法").put("data",map);
    	}
    	// 正常保存 - 调用Service层进行保存
    	brandService.save(brand);
    	return R.ok();
    }
    

    3、全局异常处理

    上面的步骤已经完成了基本校验,但是有点复杂,需要在Controller方法里添加重复代码。
    错误需要返回一个错误码及错误消息,因此使用一个枚举类型来定义,然后这种方式也挺适合项目里使用。

    /***
     * 错误码和错误信息定义类
     * 1. 错误码定义规则为5为数字
     * 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
     * 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
     * 错误码列表:
     *  10: 通用
     *      001:参数格式校验
     *  11: 商品
     *  12: 订单
     *  13: 购物车
     *  14: 物流
     */
    public enum BizCodeEnum {
        UNKNOW_EXCEPTION(10000,"系统未知异常"),
        VAILD_EXCEPTION(10001,"参数格式校验失败");
    
        private int code;
        private String msg;
        BizCodeEnum(int code,String msg){
            this.code = code;
            this.msg = msg;
        }
    
        public int getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    }
    
    

    处理全局异常 - 处理校验错误异常:

    @Slf4j
    @RestControllerAdvice(basePackages = "top.liuchengyin.product.controller")
    public class ExceptionControllerAdice {
    	@ExceptionHandler(value = MethodArgumentNotValidException.class)
    	 public R handleVaildException(MethodArgumentNotValidException e){
            log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());
            // 获取错误结果
            BindingResult bindingResult = e.getBindingResult();
            Map<String,String> errorMap = new HashMap<>();
            bindingResult.getFieldErrors().forEach((fieldError)->{
                errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
            });
            // 返回错误信息
            return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(),BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data",errorMap);
        }
    }
    

    这样,Controller层的代码就变得十分简略了:

    @RequestMapping("/save")
    public R save(@Valid @RequestBody Brand brand){
    	brandService.save(brand);
    	return R.ok();
    }
    

    二、分组校验

    分组校验用于多场景的复杂校验,比如说我们在做新增功能的时候,这是不需要校验ID的(ID是自动生成的),但是做修改的时候就需要校验ID了(没有ID,就没办法判断修改的谁)。也就是说,给校验注解标注什么情况需要进行校验。

    1、创建分组标识

    分组标识是一个空的接口即可,只是用来标识是那种情况。这里创建两个标识表示:新增、修改。

    // 修改分组标识
    public interface UpdateGroup {
    
    }
    
    // 新增分组标识
    public interface AddGroup {
    
    }
    
    2、在Bean中添加分组
    // Brand对象
    @NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
    @Null(message = "新增不能指定id",groups = {AddGroup.class})
    private Long brandId;      // 品牌ID
    
    @NotBlank(message = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class})
    private String name;	 // 品牌名
    
    @NotBlank(groups = {AddGroup.class})
    @URL(message = "logo必须是一个合法的url地址",groups={AddGroup.class,UpdateGroup.class})
    private String logo;     // logo的url地址
    
    3、在Controller方法中指定分组

    注意:上面的Bean中,如果@NotBlank没有指定分组的话,那么在分组校验@Validated({AddGroup.class})的情况下是不会生效的,只会在@Validated生效,因此需要指定分组。即默认没有指定分组的校验注解在有分组注解Vlaidated指定分组时不会生效。

    @RequestMapping("/save")
    public R save(@Validated({AddGroup.class}) @RequestBody Brand brand){
    	brandService.save(brand);
    	return R.ok();
    }
    
    @RequestMapping("/update")
    public R update(@Validated(UpdateGroup.class) @RequestBody Brand brand){
    	brandService.updateDetail(brand);
    	return R.ok();
    }
    

    三、自定义校验

    上面的校验可能有时候满足不了我们的需求,因此我们也可以自己自定义一个校验注解,编写一个校验器进行关联。

    1、引入依赖
    <!-- 校验 -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
    
    2、Bean上加入自定义校验注解
    @ListValue(vals={0,1},groups = {AddGroup.class, UpdateGroup.class})
    private Integer showStatus;
    
    3、编写自定义校验注解
    @Documented
    // 指定自定义校验器,可以指定多个类型的,使用逗号隔开
    @Constraint(validatedBy = { ListValueConstraintValidator.class })   
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
    @Retention(RUNTIME)
    public @interface ListValue {
    	// 错误信息默认会从配置文件中获取即下面的top.xxxx的值(自定义的)
        String message() default "{top.liuchengyin.product.valid.ListValue.message}";
    
        Class<?>[] groups() default { };
    
        Class<? extends Payload>[] payload() default { };
    
        int[] vals() default { };   // 对应注解中的vals
    }
    
    4、编写自定义校验器

    自定义校验器,需要实现ConstraintValidator接口。

    // ConstraintValidator<校验注解,类型>
    public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {
        private Set<Integer> set = new HashSet<>();
        // 初始化方法
        @Override
        public void initialize(ListValue constraintAnnotation) {
            // 取出注解中的值,放入Set
            int[] vals = constraintAnnotation.vals();
            for (int val : vals) {
                set.add(val);
            }
    
        }
        
        /**
         * 判断是否校验成功
         * @param value 需要校验的值
         */
        @Override
        public boolean isValid(Integer value, ConstraintValidatorContext context) {
            return set.contains(value);
        }
    }
    
    展开全文
  • JSR303+AOP数据校验

    2017-11-20 00:14:41
    集成Swagger api管理 包含对象的一般校验和级联校验,可直接进入swagger-ui.html进行测试
  • jsr303自定义验证 借助JSR 310,Java 8终于为我们带来了不错的日期和时间API。 对于仍在使用Java 7的那些人(就像我目前在我的当前项目中一样),有很好的反向移植,请访问www.threeten.org了解更多详细信息。 但是...

    jsr303自定义验证

    借助JSR 310,Java 8终于为我们带来了不错的日期和时间API。 对于仍在使用Java 7的那些人(就像我目前在我的当前项目中一样),有很好的反向移植,请访问www.threeten.org了解更多详细信息。 但是,由于有关该主题的博客已经很多,因此我将不涉及使用新API的任何细节。 我将在本文中向您展示的是如何通过编写自己的自定义批注将Date / Time API与JSR 303 Bean验证API结合使用。

    如果您同时使用bean验证和新的日期/时间API,则可能需要结合使用它们。 API和Hibernate Validator之类的实现仅提供了少数约束,例如NotEmpty@Pattern 。 但是,到目前为止,JSR 310还没有现成的约束。幸运的是,创建自己的约束非常容易。 作为示例,我将演示如何编写自己的@Past批注以验证java.time.LocalDate字段。

    为了进行测试,我们将从一个非常简单的类开始,该类包含一个日期和一个dateTime。 这些字段应该代表过去的日期。 因此,它们使用@Past注释进行注释:

    ClassWithPastDates

    package it.jdev.example.jsr310.validator;
    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    
    public class ClassWithPastDates {
    
        @Past
        private LocalDate date;
    
        @Past
        private LocalDateTime dateTime;
        
        public LocalDate getDate() {
            return date;
        }
        
        public void setDate(LocalDate date) {
            this.date = date;
        }
        public LocalDateTime getDateTime() {
            return dateTime;
        }
        
        public void setDateTime(LocalDateTime dateTime) {
            this.dateTime = dateTime;
        }
    
    }

    接下来,我们将为@Past约束编写一个非常基本的单元测试,以证明我们的意图:显然,除了过去的日期之外,我们还希望null引用有效,但将来的日期无效,甚至今天也算作无效。

    过去测试

    package it.jdev.example.jsr310.validator;
    
    import static org.junit.Assert.assertEquals;
    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.util.Set;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.Validation;
    import javax.validation.Validator;
    import javax.validation.ValidatorFactory;
    
    import org.junit.Before;
    import org.junit.Test;
    
    public class PastTest {
        
        private ClassWithPastDates classUnderTest;
    
        @Before
        public void setup() {
            classUnderTest = new ClassWithPastDates();
        }
    
        @Test
        public void thatNullIsValid() {
            Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);
            assertEquals(violations.size(), 0);
        }
    
        @Test
        public void thatYesterdayIsValid() throws Exception {
            classUnderTest.setDate(LocalDate.now().minusDays(1));
            classUnderTest.setDateTime(LocalDateTime.now().minusDays(1));
            Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);
            assertEquals(violations.size(), 0);
        }
    
        @Test
        public void thatTodayIsInvalid() throws Exception {
            classUnderTest.setDate(LocalDate.now());
            classUnderTest.setDateTime(LocalDateTime.now());
            Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);
            assertEquals(violations.size(), 2);
        }
    
        @Test
        public void thatTomorrowIsInvalid() throws Exception {
            classUnderTest.setDate(LocalDate.now().plusDays(1));
            classUnderTest.setDateTime(LocalDateTime.now().plusDays(1));
            Set<ConstraintViolation<ClassWithPastDates>> violations = validateClass(classUnderTest);
            assertEquals(violations.size(), 2);
        }
    
        private Set<ConstraintViolation<ClassWithPastDates>> validateClass(ClassWithPastDates myClass) {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();
            Set<ConstraintViolation<ClassWithPastDates>> violations = validator.validate(myClass);
            return violations;
        }
    
    }

    现在我们已经建立了基本测试,我们可以实现约束本身。 这包括两个步骤。 首先,我们必须编写注释,然后必须实现ConstraintValidator 。 从注释开始:

    @interface过去

    package it.jdev.example.jsr310.validator;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    
    @Target({ ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = PastValidator.class)
    @Documented
    public @interface Past {
    
        String message() default "it.jdev.example.jsr310.validator.Past.message";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
    }

    如您所见, @Past注释不是很壮观。 需要注意的主要事情是@Constraint批注,在其中我们指定将使用哪个类来执行实际的验证。

    PastValidator

    package it.jdev.example.jsr310.validator;
    
    import java.time.LocalDate;
    import java.time.temporal.Temporal;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    
    public class PastValidator implements ConstraintValidator<Past, Temporal> {
    
        @Override
        public void initialize(Past constraintAnnotation) {
        }
    
        @Override
        public boolean isValid(Temporal value, ConstraintValidatorContext context) {
            if (value == null) {
                return true;
            }
            LocalDate ld = LocalDate.from(value);
            if (ld.isBefore(LocalDate.now())) {
                return true;
            }
            return false;
        }
    
    }

    PastValidator是所有魔术发生的地方。 通过实现ConstraintValidator接口,我们不得不提供两种方法,但对于我们的示例,仅使用isValid()方法,这是我们执行实际验证的地方。

    请注意,我们使用java.time.temporal.Temporal作为类型,因为它是LocalDate和LocalDateTime类共同的接口。 这使我们可以对LocalDate和LocalDateTime字段使用相同的@Past

    真正的全部就是它。 在这个非常基本的示例中,我展示了创建自己的定制JSR 303 bean验证约束是多么容易。

    翻译自: https://www.javacodegeeks.com/2014/09/custom-jsr-303-bean-validation-constraints-for-the-jsr-310-new-datetime-api.html

    jsr303自定义验证

    展开全文
  • SpringBoot 2.X整合JSR303服务端数据校验 一、JSR-303简介 JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,注重于服务端数据校验,官方参考实现是Hibernate Validator。 Bean Validation 中内置的...
  • springmvc&JSR303;的jar包

    2018-11-09 21:36:52
    压缩包里面包含的是我所在springmvc项目里面的springmvc以及JSR303数据验证说依赖的jar包,可以方向使用,亲测有效

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,080
精华内容 6,432
关键字:

jsr303