深入 Table 配置
现在,打开我们的 WEB 服务器,并打开浏览器。访问我们的 user_demo 操作页面:
http://localhost:8080/cwin/cwin?_CWIN_ID=user_demo
_CWIN_ID 参数表示 Window 的 ID 。我们在前面提到过, Cwin 的核心是 Window 。而我们现在传递的参数却是表名。事实上,如果我们传入的参数不是一个已经定义的 Window ,那么 Cwin 会尝试查看这个 ID 是不是一个表名,如果是,则会生成默认的配置,并将这张表做为默认的 Window 来处理。现在,我们打开 table.xml ,学习它的配置。
验证的配置
找到 id 为 user_demo 的 table 元素,它的配置应该如下所是:
<table id="user_demo"> <field name="id" desc="id" validType="int" isKey="true"/> <field name="login_name" desc="login_name"/> <field name="email" desc="email"/> <field name="password" desc="password"/> <field name="type" desc="type"/> <field name="create_time" desc="create_time" validType="date"/> <field name="intro" desc="intro"/> </table>
有关于各个元素的配置的含义,可以查看我们提供的 XSD 文件。也可以查看我们的附件。这里,将这些默认生成的各个元素与属性做一个介绍。
在父元素 <table> 下面,有一系列的子元素 <field> ,这个很容易理解,就是每个字段的定义。 name 属性:字段名
desc 属性:字段描述
validType 属性:验证类型
字段名当然是不用修改的也是不允许修改的。
我们先修改 Desc 属性吧,因为我们在页面上看到的表头与输入提示都是字段名。
OK ,现在我们的 user_demo 配置变成了这样:
<table id="user_demo"> <field name="id" desc="ID" validType="int" isKey="true"/> <field name="login_name" desc=" 登录名 "/> <field name="email" desc=" 电子信箱 "/> <field name="password" desc=" 密码 "/> <field name="type" desc=" 用户类型 "/> <field name="create_time" desc=" 创建时间 " validType="date"/> <field name="intro" desc=" 个人说明 "/> </table>
我们加上了中文的说明。
现在刷新我们的页面,怎么还和以前一样??
这是因为 Cwin 对配置都缓存起来了。进入 Cwin 的控制页面 (/demo/demo.jsp) ,点击更新缓存的链接。接下来,刷新我们的 user_demo 页。注意到了吗,表头与输入提示都已经变成了中文的了!
但我们的 user_demo 表还没有任何的记录呢,好吧,让我们来添加一些记录。
点击页面上的 add record 链接。
我们可以试着为 ID 输入非数字。出现了验证,但错误信息显得很粗糙。对吗。但我们的 Email 选项呢。没有验证?是的,我们在上面的配置文件中没有看到对 Email 的验证类型定义。
OK ,我们现在为它们都加上验证类型。最后,配置文件变成这样。
<table id="user_demo"> <field name="id" desc="ID" validType="int" isKey="true"/> <field name="login_name" desc=" 登录名 " validType="signName"/> <field name="email" desc=" 电子信箱 " validType="email"/> <field name="password" desc=" 密码 " minLen="6" maxLen="20"/> <field name="type" desc=" 用户类型 " min="0" max="9"/> <field name="create_time" desc=" 创建时间 " validType="date"/> <field name="intro" desc=" 个人说明 " general="false"/> </table>
登录名: validType=”signName” signName 的规则与 JAVA 语言变量名的命名规则类似。
电子信箱: validType="email" 可限定他为 Email 。
用户类型: min="0" max="9" 限定为 0 – 9 之间的数字
密码: minLen="6" maxLen="20" 限定他为 6 到 20 位之间的字符。
个人说明: general="false" 表示允许这一项输入特殊字符。
这个选项默认为 true 。表示不允许输入特殊字符的。比如上面的密码,是不允许特殊字符的。
OK ,我们刷新缓存,刷新页面,试试。验证都生效了吗?
但我们现在有一个问题,就是我们的验证提示都很粗糙,有没有好的解决方案呢?那就是 <field> 的子元素, <comment> 。好的,我们现在为每个元素加上 Comment 子元素。
于是,我们的配置文件变成了这样:
<table id="user_demo"> <field name="id" desc="ID" validType="int" isKey="true"/> <field name="login_name" desc=" 登录名 " validType="signName"> <comment> 请输入正确的登录名 </comment> </field> <field name="email" desc=" 电子信箱 " validType="email"> <comment> 请输入正确的电子信箱 </comment> </field> <field name="password" desc=" 密码 " minLen="6" maxLen="20"> <comment> 请输入符合要求的密码, 6--20 位长 </comment> </field> <field name="type" desc=" 用户类型 " min="0" max="9"/> <field name="create_time" desc=" 创建时间 " validType="date"> <comment> 请输入正确的时间 </comment> </field> <field name="intro" desc=" 个人说明 " general="false"/> </table>
我们就可以看到我们所定义的验证信息了。
查询与排序的配置
一个简单的用户浏览功能好像马马虎虎可以使用了。但老板还需要分页查询并且可以按某些字段排序。那我们因为这个需要来为 Cwin 作扩展吗?正如你所想的,不需要!在每一个 <field> 中有几个属性是用来定义排序与查询的。
老板需要以登录名与 Email 来对用户进行查询并排序。
在 <field> 中有一个属性叫做 cond ,用来定义查询时的条件。
我们可以如下定义:
<field name="login_name" desc=" 登录名 " validType="signName" cond =”like”>
<field name="email " desc=" 电子信箱 " validType="signName" cond =”like”>
“like” 表示查询时将使用 like 匹配。另外 Cwin 还支持 < , > , = , between 等条件。
而我们排序的属性叫做 order 。
order 的值一般是一个字段名,某些情况下可能是一个函数。因为我们在比较复杂的场景下将会用到一些的排序条件。比如说按用户注册的月份来排序。
<field name="login_name" desc=" 登录名 " validType="signName" cond =”like” order=”login_name”>
<field name="email " desc=" 电子信箱 " validType="signName" cond =”like” order=”email”>
好了,最终的 XML 配置如下:
<table id="user_demo"> <field name="id" desc="ID" validType="int" isKey="true"/> <field name="login_name" desc=" 登录名 " validType="signName" order="login_name" cond="like"> <comment> 请输入正确的登录名 </comment> </field> <field name="email" desc=" 电子信箱 " validType="email" order="email" cond="like"> <comment> 请输入正确的电子信箱 </comment> </field> <field name="password" desc=" 密码 " minLen="6" maxLen="20"> <comment> 请输入符合要求的密码, 6--20 位长 </comment> </field> <field name="type" desc=" 用户类型 " min="0" max="9"/> <field name="create_time" desc=" 创建时间 " validType="date"> <comment> 请输入正确的时间 </comment> </field> <field name="intro" desc=" 个人说明 " general="false"/> </table>
现在请刷新缓存并刷新页面。看到查询表单了吗?
那么排序呢?您应该看到输出表格的箭头了,点击我们定义了排序的字段的表头吧。嗯,这一切是不是很简单呢?
有一个细节,如果定义的条件是 between ,比如说注册时间。因为我们有两个查询框,我的查询描述将输出什么? Cwin 有自己默认的输出。在这里,您最好使用 condDesc 做一下配置,两个描述使用逗号分隔,注意,是英文逗号。比如 condDesc=” 开始时间 , 结束时间 ” 。诸位可以试一试。
默认值与默认变量
除了数据库自身的默认值以外,可以为 <field> 配置两种变量值,一种是插入数据时的默认值(相当于数据库自己定义的 default 属性),一种是修改时的默认值。分别对应于 default 与 modifyValue 属性。
Cwin 提供了一种更灵活的默认值:变量。 Cwin 内置支持的变量只有一个: _CWIN_SYS_TIME (系统时间)。在数据输入时 Cwin 会将这个变量替换为当前的时间。另外, Cwin 也支持用户自定义的默认值变量。这需要用户继承一个类 (cn.antia.cwin.ValiableInjector) 来为这些变量赋值。需要覆盖其 protected Object parseValiableValue(String sv, HttpServletRequest request) 方法。然后在 table.xml 的 <constants> 中定义变量与 ValiableInjector 类。
比如,我们需要将用户的注册时间设定为系统时间。就可以定义如下:
<field name="create_time" desc=" 创建时间 " default=” _CWIN_SYS_TIME”>
主键生成器配置
Cwin 内置支持两种主键生成器: increment 和 uuid 。 Increment 将产生自增型主键。为 Cwin 的默认主键生成方式。 Uuid 将产生 UUID 串。另外如果用户需要有其它的主键生成方式,则需要用户自定义主键生成器。实现 cn.antia.cwin.db.tool. IdGenerator 接口。
默认主键生成器与用户自定义的主键生成器在 table.xml 的 <constants> 中指定。分别对应于 default_id_generator 与 id_generator 属性。 id_generator 用来指定用户自定义的主键生成器实现。
default_id_generator 有四个可选值: increment 、 uuid 、 appointed 、 foreignKey 。
针对每张表可以指定不同的主键生成器。利用 <field> 元素的 idGenerator 属性。 idGenerator 属性的值与 default_id_generator 的值一致。当 idGenerator 的值为 appointed 时, Cwin 将会使用 id_generator 定义的 IdGenerator 实现来获取主键。 foreignKey 一般用于一对一关系中的右边表。
存储类型
存储属性类型表示数据在数据库中的存储形式。通过 <field> 元素的 store 来定义。它有四个可选值:
normal: 正常存储
md5:md5 加密存储
encrypt: 加密存储, Cwin 提供的一种 md5 加密的一种衍生形式
binary: 二进制存储。用来存储大型文件。 ( 目前版本 (1.0pv1) 没有实现此功能 )
如果现在老板过来,要求我们将密码存储为 MD5 形式。 OK 。我们来做一下修改:
<field name="password" desc=" 密码 " minLen="6" maxLen="20" store=”md5”>
嗯,对,就是这样,老板的要求实现了了!
元素配置的引用
为了避免元素配置的重复。 Cwin 提供了元素引用功能。使用 ref 属性。
Ref 有两种语法,一种是直接引用,另一种则带有点 (.) 号。
直接引用类似这样: ref=”valid” ,引用从公共字段中定义的 valid 元素。
带点号的则是 ref=”user.create_time” ,表示引用在 Window ID 为 user 或表名为 user create_time 字段定义。
元素配置的覆盖:
如果在元素中引用了其它元素,而在这个元素中又定义了一些已经在被引用元素中已经定义属性。那么,被引用元素中的定义将被引用元素中的定义覆盖。
输入的配置
现在来看我们的编辑页面,还有些问题:
1. 主键字段不应出现在编辑页面。
2. 个人说明应使用 Textarea 来输入。
3. 用户类型需要以下拉列表形式展现。
好了,我们带着这些问题来了解输入的配置。
输入是 Field 的一个子节点:以下是一个输入框的示例。
<input type=”text” desc=” 登录名 ” size=”80” >
针对第一个问题,诸位读者认为将如何配置呢?对了,就是 hidden 。
<input type=”hidden”/> ,嗯,这样,我们的第一个问题就算是解决了。
那么,第二个问题就是:
<input type=”textarea” cols=”70” rows=”4”/>
那么第三个问题就是:
<input type=”select”/> 。
那么,下拉选项的配置呢?这稍有难度,因为我们需要引入一个新的子节点。 <options>
Options 的第一种配置很直接:
<options>
<option value=”1” desc=” 管理员 ”/>
<option value=”2” desc=” 普通用户 ”/>
</options>
另一种方式,则是通过 sql 。假定我们有一张表用来存储用户类型,则可以如下定义:
<options>
<sql>select id,name from user_type</sql>
</option>
其中 SQL 元素中定义的 SQL ,将以查询结果的第一列为 value ,第二列为 desc 。
现在,让我们来完成输入的配置:
<table id="user_demo"> <field name="id" desc="ID" validType="int" isKey="true"> <input type="hidden"/> </field> <field name="login_name" desc=" 登录名 " validType="signName" order="login_name" cond="like"> <comment> 请输入正确的登录名 </comment> </field> <field name="email" desc=" 电子信箱 " validType="email" order="email" cond="like"> <comment> 请输入正确的电子信箱 </comment> </field> <field name="password" desc=" 密码 " minLen="6" maxLen="20"> <comment> 请输入符合要求的密码, 6--20 位长 </comment> </field> <field name="type" desc=" 用户类型 "> <input type="select"/> <options> <option desc=" 管理员 " value="1"/> <option desc=" 普通用户 " value="0"/> </options> </field> <field name="create_time" desc=" 创建时间 " validType="date"> <comment> 请输入正确的时间 </comment> </field> <field name="intro" desc=" 个人说明 " general="false"> <input type="textarea" cols="70" rows="5"/> </field> </table>
老办法,刷新缓存,查看页面变化。
另外,您也可以试试将用户的个人说明将成 fckeditor 试试。定义如下:
<input type="fckeditor" cols="870" rows="195"/>
Fckeditor 可以上传图片哦。。。
等等,请注意这次表格数据发生的变化。
1. 用户类型列:变成了描述,而不是真实的值。这是 Cwin 在配置好 options 之后默认显示为描述,如果需要显示为值。当然也是可以的。
2. 个人说明: 显示为了 … ,而没有显示具体内容。这是为什么呢。这是 Cwin 做的一小小的工作,将长字段在表格中隐藏了。当然,您也可以在页面中配置它为隐藏。但这些都是下一节的内容了。
输出配置
输出配置相对来说要简单一些。输出的配置集中在 <output> 元素上。它的属性有: dispMode,desc,goat 等等,但这三个属性将是最基础的。
dispMode :定义在输出表格中的显示方式,它有几个可选值: none,hidden,pop,link,value, desc
其中 value 是默认值,将会把原始值输出在页面上。
none 表示不在表格中输入这一列。
desc 表示在元素拥有 options 值输出描述而不是值。
link 比较有用处,他将在表格中输出一个超链接。但为了要使 link 有效,我们必须定义另一个属性,叫做 href !这个大家都知道。如果需要定义链接的目标窗口,那么则需要再加一个属性,叫做 target……
hidden 表示在表格中隐藏,这样的话我们的输出表格中显示什么呢。对了是 goat 属性定义的值,如果 goat 没有定义值,那么会有一个自动赋予的值。而这个默认值则在 constants 中定义。
另外其它支持的属性有:
href,target,title, style, class,onclick, onmouseout, onmouseover:
这些属性将在表格输出时原样输出。
嗯,有一个很重要的功能:这些属性的值的定义是可以带变量定义的。这使得这些自定义属性变得很有用。比如我们定义一个 onclick 属性为 οnclick=”alert(‘userid:[id]’);” 或者这样定义 href=”cwin?_CWIN_ID=user_demo&_CWIN_ACTION=show&id=[id]” 。
这个 [id] 就是变量。
好啦,现在,老板要求在表格中点击登录名可以在新窗口查看用户的信息以便打印。并且需要将用户的个人说明以浮动层的方式展示。
针对这个需求,我们要做的是定义两个 output 元素,一个在登录名的 field 下,一个在个人说明的 field 下。定义如下:
<output dispMode="link" href="cwin?_CWIN_ID=user_demo&_CWIN_ACTION=show&id=[id]" target="_blank"/>
<output dispMode="pop"/>
这个版本的配置是这样:
<table id="user_demo"> <field name="id" desc="ID" validType="int" isKey="true"> <input type="hidden"/> </field> <field name="login_name" desc="登录名" validType="signName" order="login_name" cond="like"> <output dispMode="link" href="cwin?_CWIN_ID=user_demo&_CWIN_ACTION=show&id=[id]" target="_blank"/> <comment>请输入正确的登录名</comment> </field> <field name="email" desc="电子信箱" validType="email" order="email" cond="like"> <comment>请输入正确的电子信箱</comment> </field> <field name="password" desc="密码" minLen="6" maxLen="20"> <comment>请输入符合要求的密码,6--20位长</comment> </field> <field name="type" desc="用户类型"> <input type="select"/> <options> <option desc="管理员" value="1"/> <option desc="普通用户" value="0"/> </options> </field> <field name="create_time" desc="创建时间" validType="date"> <comment>请输入正确的时间</comment> </field> <field name="intro" desc="个人说明" general="false"> <input type="fckeditor" cols="870" rows="195"/> <output dispMode="pop"/> </field> </table>
好了,如果您刷新页面看到了界面上的效果,我们进入下一章。