注:本文档只针对spring boot工程使用的情况有针对性的翻译,完整版本请登录GORM的github官网浏览
1. 约束介绍
1.1. Constraints 用法
Constraints约束通过定义DSL(领域专用语言)来生成校验规则、架构生成和CRUD生成元数据. 例如:
import grails.persistence.Entity;
import org.grails.datastore.gorm.GormEntity
@Entity
class User implements GormEntity<User>{
...
static constraints = {
login size: 5..15, blank: false, unique: true
password size: 5..15, blank: false
email email: true, blank: false
age min: 18
}
}
参看 Constraints 了解更多校验规则.
1.2. Global Constraints全局约束
可以在 `src/main/resources/application.groovy`中定义全局约束:
grails.gorm.default.constraints = {
'*'(nullable: true, size: 1..20)
}
其中的*通配符会应用在所有的属性上.也可以定义全局共享约束:
grails.gorm.default.constraints = {
myShared(nullable: true, size: 1..20)
}
这样就可以向下面代码一样在domain类中重用:
import grails.persistence.Entity;
import org.grails.datastore.gorm.GormEntity
@Entity
class User implements GormEntity<User>{
...
static constraints = {
login(shared: "myShared")
}
}
1.3. Quick Reference 快速参考
Constraint约束 | Description描述 | Example示例 |
---|---|---|
blank |
验证字符串值不是空 |
|
creditCard |
验证字符串值是有效的信用卡号 |
|
验证字符串值是有效的邮件地址 |
|
|
inList |
验证值是否在约束值的范围或集合中 |
|
matches |
验证字符串值是否与给定的正则表达式匹配 |
|
max |
验证值不超过给定的最大值 |
|
maxSize |
验证集合的大小不超过给定的最大值 |
|
min |
验证值不低于给定的最小值 |
|
minSize |
验证集合的大小不低于给定的最小值 |
|
notEqual |
验证属性不等于指定值 |
|
nullable |
允许属性设置为“null”-默认为“false” |
|
range |
使用Groovy的Range类型以确保属性值在指定范围内 |
|
scale |
设置为浮点数字所需的尺度(即小数点右边的位数) |
|
size |
使用GroovyRange类型限制集合或数字的大小或字符串的长度 |
|
unique |
在数据库级别将属性限制为唯一 |
|
url |
验证字符串值是有效URL |
|
validator |
向字段添加自定义验证 |
See documentation |
1.4. 编程访问
可以在代码中通过静态方法 GbSpringUtils.getDomainConstraintsMap(Class domainclass)
. 返回类型为 Map<String, http://docs.grails.org/3.2.8/api/grails/validation/ConstrainedProperty.html[ConstrainedProperty]>
.
import grails.persistence.Entity;
import org.grails.datastore.gorm.GormEntity
@Entity
class User implements GormEntity<User>{
String firstName
String middleName
static constraints = {
firstName blank: false, nullable: false
middleName blank: true, nullable: true
}
}
上面的例子中, GbSpringUtils.getDomainConstraintsMap(User).firstName.blank
返回值为 false
, 而`GbSpringUtils.getDomainConstraintsMap(User).middleName.blank` 返回值为 true
.
1.4.1. Command Objects 命令对象
command object是一种只验证约束关系、不生成数据库表映射的对象
可以通过命令对象的静态属性 constraintsMap`直接访问约束.返回类型为 `Map<String, http://docs.grails.org/3.2.8/api/grails/validation/ConstrainedProperty.html[ConstrainedProperty]>
class User implements Validateable {
String firstName
String middleName
static constraints = {
firstName blank: false, nullable: false
middleName blank: true, nullable: true
}
}
上面的例子中, User.constraintsMap.firstName.blank
返回值为 false
,而 User.constraintsMap.middleName.blank
返回值为 true
.
1.4.2. blank
2. blank 约束
2.1. 目的
验证字符串值是否为空白字符串值''.
2.2. 示例
login blank: false
2.3. 描述
如果字符串值不能为空字符串值'',则设置为“false”.
错误代码 Code: className.propertyName.blank
注意:如果字符串为“null”,它将不能通过验证“blank: true”。在这种情况下,设置 nullable约束为`true`。
2.3.1. creditCard
3. creditCard约束
3.1. 目的
验证字符串值是有效的信用卡号
3.2. 示例
cardNumber creditCard: true
3.3. 描述
如果字符串必须是信用卡号码,则设置为“true”。内部使用`org.apache.commons.validator.CreditCardValidator`类。
错误代码 Code: className.propertyName.creditCard.invalid
3.3.1. email
4. email约束
4.1. 目的
验证字符串值是有效的电子邮件地址.
4.2. 示例
homeEmail email: true
4.3. 描述
如果字符串值必须是电子邮件地址,则设置为“true”。内部使用`org.apache.commons.validator.EmailValidator`类。
错误代码 Code: className.propertyName.email.invalid
4.3.1. inList
5. inList约束
5.1. 目的
验证值是否在约束值的范围或集合中.
5.2. 示例
name inList: ["Joe", "Fred", "Bob"]
5.3. 描述
约束一个值,使其必须包含在给定的列表中.
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.not.inList
5.3.1. matches
6. matches约束
6.1. 目的
验证字符串值是否与给定的正则表达式匹配.
6.2. 例子
login matches: "[a-zA-Z]+"
6.3. 例子
对字符串值应用正则表达式.
错误代码 Code: className.propertyName.matches.invalid
6.3.1. max
7. max约束
7.1. 目的
确保值不超过最大值.
7.2. 示例
age max: new Date()
price max: 999F
7.3. 描述
可以设置最大值为任意实现接口implements `java.lang.Comparable`的类对象.值的类型必须和属性的类型相同。
注意: 如果值为`java.util.Date`类型,约束的值只在评估执行时创建一次。
class User {
...
static constraints = {
//此日期对象在评估约束执行时创建,而不是每次验证用户类的实例时创建
birthDate max: new Date()
}
}
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.max.exceeded
7.3.1. maxSize
8. maxSize约束
8.1. 目的
确保值的大小不超过最大值.
8.2. 示例
children maxSize: 25
9. min约束
9.1. 目的
确保值不低于最小值
9.2. 示例
age min: new Date()
price min: 0F
9.3. 描述
可以设置最小值为任意实现接口implements `java.lang.Comparable`的类对象.值的类型必须和属性的类型相同。
注意: 如果值为`java.util.Date`类型,约束的值只在评估执行时创建一次。
class User {
...
static constraints = {
//此日期对象在评估约束执行时创建,而不是每次验证用户类的实例时创建
age min: new Date()
}
}
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.min.notmet
9.3.1. minSize
10. minSize约束
10.1. 目的
确保值的大小不低于最小值.
10.2. 示例
children minSize: 25
10.3. 描述
设置集合或数字属性的最小大小.
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.minSize.notmet
10.3.1. notEqual
11. notEqual约束
11.1. 目的
确保属性不等于指定值
11.2. 示例
username notEqual: "Bob"
11.3. 描述
错误代码 Code: className.propertyName.notEqual
11.3.1. nullable
12. nullable约束
12.1. 目的
允许属性设置为“null”,默认设置为`false`
12.2. 示例
age nullable: true
12.3. 描述
如果属性允许设置为`null`值,设置为`true`.对应数据库会设置为allow null.
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.nullable
注意:web请求表单提交,对于没有输入值的输入框, 属性的值为空白字符串,不是`null`.
12.3.1. range
13. range约束
13.1. 目的
使用Groovy的Range类型以确保属性值在指定范围内
13.2. 示例
age range: 18..65
13.3. 描述
Groovy的Range类型可以包含数字类型`IntRange`或日期类型,或者任意类型(实现了implements Comparable
,并且提供`next` 和 previous
两个方法)
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.range.toosmall
或者 className.propertyName.range.toobig
13.3.1. scale
14. scale约束
14.1. 目的
设置为浮点数字所需的尺度(即小数点右边的位数)
14.2. 示例
salary scale: 2
14.3. 描述
设置为浮点数字所需的尺度(即小数点右边的位数)。这个限制适用于以下类型的属性: java.lang.Float
, java.lang.Double
, and java.math.BigDecimal
(及其子类)。当验证被调用时,此约束确定该数字是否包含比刻度允许更多的非零小数位置。如果是这样,它将数字循环到由刻度允许的最大小数位数。此约束不会生成验证错误消息。
这种约束的影响参见 schema generation.
无错误代码 Code: N/A
14.3.1. size
15. size约束
15.1. 目的
使用Groovy的Range类型限制集合、数字或字符串长度的大小
15.2. 示例
children size: 5..15
15.3. 描述
设置集合的大小、数字属性或字符串长度.
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.size.toosmall
或 className.propertyName.size.toobig
15.3.1. unique
16. unique约束
16.1. 目的
在数据库级别将属性限制为唯一,会在数据库表上建立唯一性约束
16.2. 示例
username unique: true
16.3. 描述
如果属性必须是唯一的,则设置为`true`。这是一个持久的调用,将查询数据库。
警告:有可能会发生(虽然不可能在实践中出现)唯一性验证通过,但随后的保存失败。场景为:如果同时有其他的进程修改数据库在GORM检查的同时,那么相关调用将失败。为了防止这一点的唯一方法就是使用`SERIALIZABLE`隔离级别的事务,但对性能影响很大。 还可以通过定义将字段包含为参数值来定义多列的“唯一”约束。如果有另一个字段,请指定它的名称,但如果有多于一个字段,请使用列表List,例如:
示例:
group unique: 'department'
这个例子中,每个`department`部门内`group`名是唯一的,不同的部门可以存在重名的组。组名本身不是唯一的.
示例2:
username(unique: ['group', 'department'])
这个例子要求在一个部门和组内的 `username`用户名是唯一的。不同的部门或不同的组内可以存在重名的情况
这种约束的影响参见 schema generation.
错误代码 Code: className.propertyName.unique
16.3.1. url
17. url约束
17.1. Purpose
验证字符串值是有效URL.
17.2. 例子
homePage url: true
17.3. 描述
如果一个字符串是 URL设置为 true
.
错误代码 Code: className.propertyName.url.invalid
17.3.1. validator
18. validator约束
18.1. 目的
为字段添加自定义约束.
18.2. 例子
even validator: {
return (it % 2) == 0
}
// is equivalent to
even validator: { val ->
return (val % 2) == 0
}
// 闭包的两个参数,第一个是属性值,第二个是实例对象
password1 validator: { val, obj ->
obj.password2 == val
}
//闭包的三个参数,第一个是属性值,第二个是实例对象 ,第三个是errors错误对象
password1 validator: { val, obj, errors ->
if (!(obj.password2 == val)) errors.rejectValue('password1', 'noMatch')
}
// Examples 传递参数到i18n的消息中 message.properties
// Example 1: 使用隐式的参数 0 (属性名称)
class Person {
String name
static constraints = {
name validator: {
if (!it) return ['entryMissing']
}
}
// 上述例子将调用如下消息:
// person.name.entryMissing=Please enter a name in the field {0}
// Example 2: 使用隐式的参数 0 (属性名称) and 参数2 (属性值)
class Person {
Integer yearOfBirth
static constraints = {
yearOfBirth validator: {
if (yearOfBirth>2013) return ['yearTooBig']
}
}
// 上述例子将调用如下消息:
// person.yearOfBirth.yearTooBig=The value {2} entered in the field {0} is not valid because it lies in the future.
// Example 3: 复杂
class Astronaut {
Integer yearOfBirth
Integer yearOfFirstSpaceTravel
yearOfFirstSpaceTravel validator: { val, obj ->
if (val < obj.yearOfBirth) ['datePriorTo', val.toString(), obj.yearOfBirth]
else if (val < (obj.yearOfBirth+18)) ['maybeABitTooYoung', val-obj.yearOfBirth]
}
}
// 各自的消息
// 注意,参数3是属性值转换toString方法,以避免不必要的格式,如前所述.
astronaut.yearOfFirstSpaceTravel.datePriorTo=The value {3} entered for the year of the first space travel is prior to the year of birth ({4}). Please correct the value.
astronaut.yearOfFirstSpaceTravel.maybeABitTooYoung={3} years seems a bit young for travelling to space, dude!
18.3. 描述
自定义验证通过闭包来实现,并接受3个参数。
如果闭包接受0个或1个参数,参数值将被验证("it" 是闭包的第0个参数).
如果接受2个参数,第一个是值,第二个是domain类的实例.
如果接受3个参数,第一个是值,第二个是domain类的实例,第3个是Spring Errors
对象。
闭包可以返回:
-
null
或者true
(或者没有返回值) 说明值是有效的。 -
false
说明值是无效的并使用默认的消息代码 -
string 指明错误代码增加到 "classname.propertyName."字符串后,从而获取错误消息.如果无法解决特定字段消息,错误代码本身将使用全局错误消息.
-
一个包含字符串的list列表,后面是参数. 将使用 i18n/message.properties 中的定义组织消息。 参数的映射如下:参数0到2将自动映射到0:属性名称,1:类名,2:属性值。在参数3开始映射附加参数。
请注意,在最后的错误信息,该属性的标签将使用在message.properties文件中的定义。否则,将使用类中定义的属性名称。
当显式传递的错误代码,通常不需要使用"return"关键词返回的错误代码,因为如果从闭包返回时,它将检查错误是否已连接到错误的对象。
这可以看作特例,闭包中传递了第3个参数,预计错误的对象`Errors`将直接更新。