JSR303使用

活动地址:CSDN21天学习挑战赛

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。

前言

通过实战项目中了解到了jsr303,了解到了可以用于项目构建校验器实现参数验证,下面来详细了解一下jsr303。

什么是JSR303

JSR-303 是 JAVA EE 6 中的一项子规范,叫 Bean Validation。JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。

相关约束注解

Hibernate Validator 在 Bean Validation的基础上还添加了一些附加的 constraint。Hibernate Validator : The Bean Validation reference implementation. - Hibernate Validator

constraint
约束

Constraint详细信息
@Null被注释的元素必须为null
@NoNull被注释的元素必须不为null
@AssertTrue被注释的元素必须为true
@AssertFalse被注释的元素必须为false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,miin)被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式
@Email被注释的元素必须是电子邮箱地址
@Length被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的字符串的必须非空
@Range被注释的元素必须在合适的范围内

使用方法

导入依赖

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

springboot依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

直接在实体类中添加注解即可, 例:

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Car {

	@NotNull
	private String manufacturer;//manufacturer永远不能为null

	@NotNull
	@Size(min = 2, max = 14)
	private String licensePlate;//licensePlate永远不能为null,并且它的值字符串的长度要在2到14之间

	@Min(2)
	private int seatCount;//seatCount的值要不能小于2
    
	public Car(String manufacturer, String licencePlate, int seatCount) 	{
		this.manufacturer = manufacturer;
		this.licensePlate = licencePlate;
		this.seatCount = seatCount;
	}
    
//getters and setters ...
}
	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 = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class})
	private String name;
	/**
	 * 品牌logo地址
	 */
	@NotBlank(groups = {AddGroup.class})
	@URL(message = "logo必须是一个合法的url地址",groups={AddGroup.class,UpdateGroup.class})
	private String logo;
	/**
	 * 介绍
	 */
	private String descript;
	/**
	 * 显示状态[0-不显示;1-显示]
	 */
//	@Pattern()
	@NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
  	@ListValue(vals={0,1},groups = {AddGroup.class, UpdateStatusGroup.class})
	private Integer showStatus;
	/**
	 * 检索首字母
	 */
	@NotEmpty(groups={AddGroup.class})
	@Pattern(regexp="^[a-zA-Z]$",message = "检索首字母必须是一个字母",groups={AddGroup.class,UpdateGroup.class})
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull(groups={AddGroup.class})
	@Min(value = 0,message = "排序必须大于等于0",groups={AddGroup.class,UpdateGroup.class})
	private Integer sort;

新增和修改对于实体的校验规则是不同的,例如id是自增的时,新增时id要为空,修改则必须不为空;新增和修改,若用的恰好又是同一种实体,那就需要用到分组校验。使用@Validated来进行分组校验。

Validated源码

 /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand/*,BindingResult result*/){

        brandService.save(brand);

        return R.ok();
    }
 /**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:brand:update")
    public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){
		brandService.updateDetail(brand);

        return R.ok();
    }

Result类的编写 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;
	}
	public  Integer getCode() {

		return (Integer) this.get("code");
	}

}

创建自己的约束规则

因为jsr自带的约束规则已经满足我目前的开发需求,如果需要创建自己的约束规则可以参考官方的参考指南进行构建:

首先,我们需要一种方法来表示这两种模式( 译注: 大写或小写), 我们可以使用String常量, 但是 在Java 5中, 枚举类型是个更好的选择:

枚举类型CaseMode, 来表示大写或小写模式.

package com.mycompany;
public enum CaseMode {
UPPER,
LOWER;
}

现在我们可以来定义真正的约束标注了. 如果你以前没有创建过标注(annotation)的话,那么这个 可能看起来有点吓人, 可是其实没有那么难的 😃

例 定义一个CheckCase的约束标注

package com.mycompany;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = CheckCaseValidator.class)
@Documented
public @interface CheckCase {
String message() default "{com.mycompany.constraints.checkcase}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
CaseMode value();
}

一个标注(annotation) 是通过@interface关键字来定义的. 这个标注中的属性是声明成类似方法 的样式的. 根据Bean Validation API 规范的要求

•message属性, 这个属性被用来定义默认得消息模版, 当这个约束条件被验证失败的时候,通过 此属性来输出错误信息.

•groups 属性, 用于指定这个约束条件属于哪(些)个校验组(请参考第 2.3 节 “校验组”). 这 个的默认值必须是Class类型到空到数组.

•payload 属性, Bean Validation API 的使用者可以通过此属性来给约束条件指定严重级别. 这 个属性并不被API自身所使用.

除了这三个强制性要求的属性(message, groups 和 payload) 之外, 我们还添 加了一个属性用来指定所要求到字符串模式. 此属性的名称value在annotation的定义中比较特 殊, 如果只有这个属性被赋值了的话, 那么, 在使用此annotation到时候可以忽略此属性名称, 即@CheckCase(CaseMode.UPPER). 另外, 我们还给这个annotation标注了一些(所谓的) 元标注( 译注: 或"元模型信息"?, “meta annotatioins”):

•@Target({ METHOD, FIELD, ANNOTATION_TYPE }): 表示@CheckCase 可以被用在方法, 字段或者 annotation声明上.

•@Retention(RUNTIME): 表示这个标注信息是在运行期通过反射被读取的.

•@Constraint(validatedBy = CheckCaseValidator.class): 指明使用那个校验器(类) 去校验使用了 此标注的元素.

•@Documented: 表示在对使用了@CheckCase的类进行javadoc操作到时候, 这个标注会被添加到 javadoc当中.

想要深入了解可以看看JSR 303 的参考实现 使用指南 hibernate_validator_reference.pdf (jboss.org)

参考

JSR 303 的参考实现 使用指南 hibernate_validator_reference.pdf (jboss.org)

The Java Community Process(SM) Program - JSR: Java Specification Requests - detail JSR# 303 (jcp.org)

Jakarta Bean Validation - Home

Home - IBM Developer

Spring Boot 使用 JSR303 实现参数验证-阿里云开发者社区 (aliyun.com)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值