使用 Dojo 和 Grails 快速实现数据的增删改查(CRUD)
选择 Grails 和 Dojo 的原因
随着 web 的广泛应用,web application 的开发项目越来越多,而大部分的 web 开发归根结底都是对数据库的增删改查。对于一张数据库表的增删改查,采用基于 MVC(模型 - 视图 - 控制器)设计模式的开发往往需要 Domain class、 Controller、4 个增删改查的页面、form 输入数据的校验等。这样就免不了大量类似功能的复制粘贴修改。 如果你想从重复劳动中解放出来,Grails 是一个很好的选择。 使用 Grails 只需要写一个 domain class 就可以自动生成 CRUD 4 个页面和对应的 controller 方法来实现对数据库的增删改查,并实现服务器端的数据校验,从而大大地提高了开发效率。
类似的 web 快速开发框架还有 Rails、Django 和 TurboGears 等,与它们相比 Grails 有如下优势:
采用 Grails 的默认模板生成的 CRUD 页面有些简陋,实际项目中往往需要功能更加丰富,外观更加漂亮,使用更加方便的控件。例如页面布局控件,Tab 控件,树,菜单,日历,编辑器,进度条等等。现在有很多 JS 框架致力于 web UI, 例如 Dojo, Extjs, Jquery, YUI 等。我们之所以选择 Dojo, 因为 Dojo 具有以下的优势:
回页首
快速搭建 CRUD 的框架 (MVC)
开发环境配置
首先需要安装 JDK,并设置好 JAVA_HOME。本文使用的是 JDK 1.6。
?命令行创建 web application
??可以看出这个 list 页面已经具备分页和排序功能了。
再来看看 Employee 的 Create 页面,如图 4 所示:
图 4. Scaffold 默认的 create 页面?
从图中可以看出添加后,服务器端会返回数据验证的结果,比如员工号必须唯一,名字不能为空,年龄必须是数字等。
再来看看 Product 的 Edit 页面 , 如图 5:
图 5. Product 的 Edit 页面?
这里我们主要关注 owner 字段 , scaffold 自动生成一个列出所有员工的下拉框,让用户从中选择出产品的负责人。
另外值得一提的是,这个 web application 已经拥有了国际化多语言的支持,只需要对 grails-app/i18n/messages_zh_CN.properties 文件进行修改,就可以汉化整个 web 界面了。
Grails 的 Scaffold 脚手架是不是很强大呢,一句 def scaffold = true 就实现了如此丰富的功能。
在命令行输入 grails generate-all com.shuo.Employee,grails 会根据默认模板在 EmployeeController 中生成 CRUD 的对应的 method 代码,并在 grails-app/views/employee 下生成 4 个 CRUD 的 gsp 页面。这些就是 scaffold 背后的代码。后面我们将对这些代码进行修改,引入 Dojo,来增强 CRUD 的用户体验。
回页首
使用 Dojo 增强 CRUD 用户体验
引入 Dojo
到 dojotoolkit.org 网站下载最新版本的 Dojo Toolkit Release。 本文用的是 dojo-release-1.6.1。
解压后将其拷入 web-app/js 中,目录结构如图 6:
?在 grails-app/views/layouts/main.gsp 中添加以下代码,见清单 4:
使用 EnhancedGrid 增强 List 表格Grails scaffold 默认的 List 表格(如图 3)功能较为简单,例如它不能像 excel 那样的跨行列合并单元格、冻结表头、单击单元格转成编辑状态等。而 Dojo 为我们提供了这样的控件:Dojox 的 DataGrid 像一个基于 Web 的 Excel 组件,足可以应付非常复杂的数据展示及数据操作。下面列出了 DataGrid 的一些特性:
其中 DataGrid 有一个非常重要的特性就是虚拟滚动(Virtual Scroll),DataGrid 对付大数据源的时候,在滚动事件触发后才请求后面的数据并创建 DOM 结点,因此每次只需要显示很少的几行,从而加快了 Grid 的加载。 不得不承认这是一种很精巧的做法,在用户体验上也很自然,就好像所有数据本来就在那里一样。但它也有缺点,当数据源真的比较大的时候,滚动条就会非常小,再加上行高参差不齐的情况,要精确地滚动到某个位置就比较困难。这时候简单直观的分页机制就足够了。最新的 Dojo 1.6 版里,继承自 DataGrid 的 EnhancedGrid 引入了几个新的插件,其中就有 Pagination(分页浏览)插件。
首先在 list.gsp 中使用 EnhancedGrid, 见清单 5:
在 employeeController 中加入方法,见清单 6:
清单 6. EnhancedGrid 对应的控制器代码?以上代码有两点需要注意:
- 从图 3 可以看出默认的日期格式是 yyyy-MM-dd HH:mm:ss z,这是由 messages.properties 中的 default.date.format 定义的。而对于 JSON 中的日期数据,格式化需要在 config.groovy 中加入如清单 7 的代码:?
清单 7. JSON 的日期格式化代码使用 FilteringSelect 增强下拉框Grails scaffold 为外键关联的对象做了下拉框供用户选择,而这个下拉框是个简单的 HTML select 控件(如图 5),用户只能从一堆下拉选项中肉眼找出要选的关联对象。本文例子中,用户就需要从一大堆的企业员工中肉眼找出要选的产品负责人。企业员工常常是成百上千人,要从 select 下拉框中找出一个很难,而且一次性从数据库读取所有员工的姓名到下拉框也很耗时。Dojo 为我们提供了一个类似于 HTML 的 select 控件:FilteringSelect,但它可以动态输入,并且按照输入值列出匹配的可选项,甚至可以按需设置加载选项的数量,下拉列表的选项可以从数据库动态获取。这样用户就能通过输入关键字,让程序帮我们找出要选的对象。
Dojo 的 ComboBox 跟 FilteringSelect 非常类似,不过 FilteringSelect 不允许用户输入可选项之外的值,而 ComboBox 可以输入任意值。所以这里我们选择 FilteringSelect。
首先对 create.gsp 和 edit.gsp 做修改,如清单 8:
清单 8. Dojo 的 FilteringSelect 代码再为 employeeController 增加方法,从数据库获取下拉选项,如清单 9:
清单 9. FilteringSelect 对应的控制器代码?使用 DatePicker 增强日期选择
Grails scaffold 提供下拉框让用户选择年月日(如图 4),从下拉框中选较为麻烦。常常我们喜欢直接输入日期或者是查看日历找到想填的日期。如图 9 的日期选择控件就满足了我们的需要。这个界面漂亮操作简单的日期选择控件就是 Dojo 的 DatePicker,我们可以通过在页面加入以下代码来实现,见清单 10:
图 9. DatePicker 界面?
清单 10. Dojo 的 DateTextBox 代码因为默认的 scaffold 时间控件的年月日是分 3 个字段分别上传,和我们用一个字段上传的数据结构是不同的,所以 controller 中需要对其做特殊转换,见清单 11:
清单 11. 使用 DateTextBox 后,save 方法添加的日期转换代码客户端数据校验Grails 的脚手架已经具备了服务器端数据校验的功能,但是每次都将数据提交到服务器再进行校验,性能太低了。为减轻服务器的负载,在浏览器端做 Javascript 校验,就非常必要。Dojo 正好提供了一个很好的数据检验框架。
用户输入数据的同时 Dojo 就会进行数据检验,一旦出错立即高亮显示出错信息。
例如用 dijit.form.NumberTextBox 可以进行数字的校验,下面的代码要求价格是大于等于 0 的数字,见清单 12:
清单 12. NumberTextBox 的数据验证另外,当表单提交时可以判断表单是否有效,如果包含无效数据将不提交表单。见清单 13:
清单 13. 表单的数据验证以上代码的效果类似于图 8(左下)中的红边框及出错提示。
?
结束语
从前面的文章我们已经能窥见 Dojo 结合 Grails 开发 web application 的强大能力以及效率。此外 Dojo 还有很多优秀的布局控件,对话框,图表,菜单,多文件上传控件等等,能够实现非常复杂的企业级应用。即将发布的 Grails2.0 也添加了很多很好的特性。我们有理由相信 Dojo 结合 Grails 的前途非常广阔。如果你们觉得文中的代码有更好的实现方法,欢迎与我联系(zhyjzhan@cn.ibm.com)。