活动地址: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) | 被注释的元素必须符合指定的正则表达式 |
被注释的元素必须是电子邮箱地址 | |
@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来进行分组校验。
/**
* 保存
*/
@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)