Grails开发:数据验证、表关系管理与Web服务实现
1. 自定义默认模板
在Grails中,可以完全自定义脚手架视图的外观和控制器的默认行为。操作步骤如下:
1. 在命令行输入
grails install-templates
。
2. 查看
src/templates
目录,这里包含了可用于按需调整的起始材料。
2. 数据验证
2.1 静态约束块的使用
以下是一个
Book
类的示例,展示了静态约束块的使用:
class Book {
static constraints = {
title(blank:false, maxSize:50)
author(blank:false)
cover(inList:["Hardback", "Paperback", "PDF"])
pages(min:0, max:1500)
category(inList:["", "Technical", "Fiction", "Non-fiction"])
excerpt(maxSize:5000)
}
String title
String author
Integer pages
String cover = "Paperback"
String category
String excerpt
String toString(){
"${title} by ${author}"
}
}
静态约束块不仅可以控制动态脚手架视图的字段顺序,还能对数据输入进行验证。
2.2 常见验证设置
| 设置 | 值 | 作用 |
|---|---|---|
| blank | true | false | 防止字段为空 |
| true | false | 检查是否为格式正确的电子邮件地址 | |
| inList | [“a”, “b”, “c”] | 显示一个下拉框 |
| min, max | number | 数字字段的最小值和最大值 |
| minSize, maxSize | number | 文本字段的最小和最大长度 |
| unique | true | false | 防止数据库中出现重复值 |
2.3 验证方法
在保存对象之前,像
book.save()
这样的方法会对对象进行验证。也可以使用
book.validate()
方法在不保存到数据库的情况下手动检查验证结果,示例代码如下:
if(book.validate()) {
// do something
}
else {
book.errors.allErrors.each {
println it
}
}
2.4 错误显示
在
grails-app/views/book/create.gsp
中,有一段代码用于查找错误并在网页上显示:
<g:hasErrors bean="${book}">
<div class="errors">
<g:renderErrors bean="${book}" as="list" />
</div>
</g:hasErrors>
2.5 自定义验证消息
可以在
grails-app/i18n/messages.properties
中添加自定义错误消息,示例如下:
default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}]
book.pages.min.notmet=Who are you trying to kid? No book could have [{2}] pages.
所有标准错误消息都已国际化并存储在
grails-app/i18n
中的Java属性文件中。可以通过安装
i18n-templates
插件进一步实现应用程序的国际化,命令为
grails install-plugin i18n-templates
。
3. 表关系管理
3.1 一对多关系
以下是
Publisher
和
Book
类的示例,展示了一对多关系的实现:
// grails-app/domain/Publisher.groovy
class Publisher{
static constraints = {
name()
}
static hasMany = [books:Book]
String name
String toString(){
return name
}
}
// grails-app/domain/Book.groovy
class Book {
static constraints = {
title()
author()
pages()
publisher()
}
static belongsTo = [publisher:Publisher]
String title
String author
Integer pages
String toString(){
"${title} by ${author}"
}
}
在
Publisher
类中使用
static hasMany
声明,在
Book
类中使用
static belongsTo
声明,即可创建一对多关系。如果要强制执行级联删除和更新,可以在
Book
类中指定
static belongsTo = Publisher
。
3.2 一对一关系
以下是
Author
和
Address
类的示例,展示了一对一关系的实现:
// grails-app/domain/Author.groovy
class Author{
static constraints = {
name()
address()
}
String name
Address address
String toString(){
return name
}
}
// grails-app/domain/Address.groovy
class Address{
static constraints = {
street()
city()
state()
zipcode()
}
String street
String city
String state
String zipcode
String toString(){
return "${street}, ${city}, ${state}, ${zipcode}"
}
}
给
Author
类添加一个
Address
字段即可创建一对一关系。为了确保真正的一对一关系,可以添加唯一约束。如果想将
Author
和
Address
保存到同一表中,可以在
Author
类中添加
static embedded = ["address"]
。
3.3 多对多关系
以下是
Book
和
Author
类的示例,展示了多对多关系的实现:
// grails-app/domain/Book.groovy
class Book {
static belongsTo = Author
static hasMany = [authors:Author]
String title
Author author
}
// grails-app/domain/Author.groovy
class Author {
static hasMany = [books:Book]
String name
}
GORM会创建一个关联表,并添加外键关联到
Book
和
Author
表。但动态脚手架不会在HTML中显示这种关系,需要手动编写GSP页面。
3.4 映射类到遗留数据库
在处理遗留应用程序时,可以使用静态映射块将类名和属性名映射到表名和列名。示例如下:
class Magazine{
String title
String editorInChief
static mapping = {
table 'periodical'
columns {
id column:'periodical_id'
title column:'publication_name'
editorInChief column:'person_in_charge'
}
}
}
4. Grails与Web服务
4.1 返回XML
4.1.1 单个书籍的XML返回
import grails.converters.*
class BookController {
// return a single book as xml
def showXml = {
render Book.get( params.id ) as XML
}
}
4.1.2 书籍列表的XML返回
// return a list of books as xml
def listXml = {
def list = Book.list(params)
render(contentType:"text/xml"){
books{
for(b in list){
book(id:b.id){
title(b.title)
author(b.author)
pages(b.pages)
unescaped << "<!-- coverPrice is coming in the next version -->"
}
}
}
}
}
如果需要自定义XML输出,可以使用
StreamingMarkupBuilder
。
4.2 返回JSON
4.2.1 单个书籍的JSON返回
import grails.converters.*
class BookController {
// return a single book as json
def showJson = {
render Book.get( params.id ) as JSON
}
}
4.2.2 书籍列表的JSON返回
// return a list of books as json
def listJson = {
def list = Book.list(params) as Book[]
render list as JSON
}
使用
as JSON
转换器可以将POGO对象或数组转换为JSON格式。
4.3 返回Excel电子表格
class BookController {
def listExcel = {
def list = Book.list(params)
render(contentType:"application/vnd.ms-excel") {
html{
body{
h1("Books")
table{
// table header
tr{
th("ID")
th("Title")
th("Author")
th("Pages")
}
//table body
for(b in list) {
tr{
td(b.id)
td(b.title)
td(b.author)
td(b.pages)
}
}
}
}
}
}
}
}
通过设置
contentType
为
application/vnd.ms-excel
,可以让浏览器将响应作为Excel文档处理。如果想让浏览器显示“另存为”对话框,可以设置
Content-Disposition
头:
def listExcel = {
def list = Book.list(params)
response.setHeader("Content-Disposition", "attachment; filename=foo.xls")
render(contentType:"application/vnd.ms-excel") {
// ...
}
}
4.4 设置Atom Feed
以下是一个设置Atom Feed的示例:
class ItemController {
def atom = {
def itemList = Item.list( params )
def df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'-07:00'")
// feed header
def updated = df.format(itemList[0].datePosted)
def feedHeader = """<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">aboutGroovy.com</title>
<link rel="alternate" type="text/html" href="http://aboutGroovy.com"/>
<link rel="self" type="application/atom+xml" href="http://aboutGroovy.com/item/atom" />
<updated>${updated}</updated>
<author><name>Scott Davis</name></author>
<id>tag:aboutgroovy.com,2006-12-18:thisIsUnique</id>
<generator uri="http://aboutGroovy.com" version="0.0.2">
Hand-rolled Grails code
</generator>
"""
// feed body
StringBuffer feed = new StringBuffer()
itemList.each{item ->
def sw = new java.io.StringWriter()
def x = new groovy.xml.MarkupBuilder(sw)
x.entry(xmlns:"http://www.w3.org/2005/Atom"){
author{name("Scott Davis")}
published(df.format(item.datePosted))
updated(df.format(item.datePosted))
link(href:"http://aboutGroovy.com/item/show/${item.id}", rel:"alternate", title:item.title, type:"text/html")
id("tag:aboutgroovy.com,2006:/item/show/${item.id}")
title(type:"text", item.title)
content(type:"xhtml"){
div(xmlns:"http://www.w3.org/1999/xhtml"){
p("Category: ${item.type}")
p{a(href:item.url, "Original Source")}
p(item.shortDescription)
p(item.description)
}
}
}
feed.append(sw.toString() + "\n")
}
// feed footer
def feedFooter = "</feed>"
response.setContentType("application/atom+xml")
render "${feedHeader}${feed}${feedFooter}"
}
}
设置Atom Feed的流程如下:
1. 从表中提取
Item
并排序。
2. 格式化日期。
3. 生成Feed头部。
4. 遍历
Item
列表生成Feed主体。
5. 生成Feed尾部。
6. 设置响应的内容类型并渲染Feed。
通过以上内容,我们了解了Grails中数据验证、表关系管理以及各种Web服务的实现方法,这些功能可以帮助开发者更高效地构建强大的Web应用程序。
5. 总结与拓展
5.1 关键技术点回顾
-
数据验证
:通过静态约束块
constraints对数据进行验证,支持多种验证设置,如blank、email、inList等。验证方法有save()和validate(),还能自定义验证消息。 -
表关系管理
:利用
hasMany和belongsTo实现一对多、一对一和多对多关系。在处理遗留数据库时,可使用静态映射块进行类与表的映射。 -
Web服务实现
:能返回XML、JSON、Excel电子表格和设置Atom Feed。返回XML和JSON时,使用
as XML和as JSON转换器;返回Excel表格利用HTML和HTTP技巧;设置Atom Feed需按特定流程生成头部、主体和尾部。
5.2 技术应用场景
| 技术 | 应用场景 |
|---|---|
| 数据验证 | 表单提交时确保数据的有效性,如注册表单、订单表单等。 |
| 表关系管理 | 构建数据库模型,如电商系统中的商品与分类、用户与订单关系。 |
| 返回XML | 与其他系统进行数据交互,如RESTful API。 |
| 返回JSON | 前端与后端的数据交互,如单页面应用(SPA)。 |
| 返回Excel电子表格 | 数据导出,如报表生成。 |
| 设置Atom Feed | 内容发布,如博客文章、新闻资讯的订阅。 |
5.3 拓展建议
- 性能优化 :在处理大量数据时,可考虑使用缓存技术,如Redis,减少数据库查询次数。
- 安全性提升 :对返回的XML和JSON数据进行加密处理,防止数据泄露。在处理用户输入时,进行严格的输入验证和过滤,防止SQL注入和XSS攻击。
- 功能扩展 :结合第三方插件,如Spring Security实现用户认证和授权,提高应用的安全性和功能完整性。
5.4 流程图总结
graph LR
A[Grails开发] --> B[数据验证]
A --> C[表关系管理]
A --> D[Web服务实现]
B --> B1[静态约束块]
B --> B2[验证设置]
B --> B3[验证方法]
B --> B4[自定义消息]
C --> C1[一对多关系]
C --> C2[一对一关系]
C --> C3[多对多关系]
C --> C4[映射到遗留数据库]
D --> D1[返回XML]
D --> D2[返回JSON]
D --> D3[返回Excel]
D --> D4[设置Atom Feed]
5.5 操作步骤总结
5.5.1 数据验证操作步骤
-
在类中定义
static constraints块,设置验证规则。 -
使用
save()或validate()方法进行验证。 -
在
grails-app/i18n/messages.properties中添加自定义验证消息。
5.5.2 表关系管理操作步骤
-
一对多关系
:在“一”方类中使用
static hasMany,在“多”方类中使用static belongsTo。 - 一对一关系 :在一方类中添加另一方类的字段,可添加唯一约束确保关系唯一性。
-
多对多关系
:在双方类中使用
static hasMany。 -
映射到遗留数据库
:在类中使用
static mapping块进行映射。
5.5.3 Web服务实现操作步骤
-
返回XML
:导入
grails.converters.*,使用render方法和as XML转换器。 -
返回JSON
:导入
grails.converters.*,使用render方法和as JSON转换器。 -
返回Excel电子表格
:设置
contentType为application/vnd.ms-excel,使用StreamingMarkupBuilder构建HTML表格。 - 设置Atom Feed :从表中提取数据并排序,格式化日期,生成头部、主体和尾部,设置响应内容类型并渲染。
通过对Grails开发中数据验证、表关系管理和Web服务实现的深入学习和实践,开发者可以更好地利用这些技术构建出功能强大、稳定可靠的Web应用程序。同时,不断拓展和优化这些技术的应用,能够满足更多复杂的业务需求。
超级会员免费看
55

被折叠的 条评论
为什么被折叠?



