redcreen
用XML创建可排序、分页的数据显示页面
在
Web
开发中,我们经常会遇到分页显示和排序数据记录集的情况,这在服务器端使用服务器端的代码和数据库技术是件很轻松的事情,比如:
ASP
、
PHP
、
JSP
等。然而,如果要在客户端显示多条记录并且排序是一件很令人头疼的事情。下面,我们利用
Extensible Markup Language
(
XML
,可扩展标记语言)和
Extensible Stylesheet Language Transformations
(
XSLT
,可扩展样式单语言转换),并结合
XML Path Language
(
XPath
,
XML
路径语言),只需要编写简单的代码,就可轻松实现。这种方法避免了与服务器频繁打交道的过程,节省了数据显示的时间,浏览者无须等待就可以看到结果,也可以减少服务器的负担。另外。由于
XML
和
XSLT
技术,使数据存储和数据显示分离,还可以让我们的代码能够重复利用,大大减轻了程序员编写代码的负担。
下面,我们一步一步地来实现我们的功能。
首先:创建
XSLT
XSLT
样式单的第一行标明该
XML
所遵照的
XML
规范版本,然后是标明该样式单使用的名称空间,这里,我们以
XSL
规范的正式版本来进行编写,而不采用
XSL
的草案的写法:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
注意:两者在功能和写法上有很大的差异。
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
接下来,我们定义
XSLT
里的模板标记:
<xsl:template match="/">
<xsl:apply-templates select="/
客户关系表
"/>
</xsl:template>
<xsl:template match="/
客户关系表
"></xsl:template>
我们把要显示的样式写到模板里面。我们使用
HTML
的数据岛来存放我们的数据,这些数据可以利用
SQL Server 2000
的
XML
查询来得到,对于不支持
XML
的数据库,我们可以自己编写组件把数据转换成
XML
格式,然后在放到数据岛里。在
HTML
里使用数据岛有两种方法:
一是直接嵌入数据,如下所示:
<XML id='Data'>
<
客户关系表
>
<
客户
>
每条数据
</
客户
>
</
客户关系表
>
</XML>
二是通过
SRC
属性引用外部文件,如下所示:
<XML id='Data' src='Data.xml'></XML>
要使用数据岛里的数据,必须通过
id
名来引用它,当然,由于
XSLT
文件也是
XML
格式文件的一种,也可以通过这种方法来实现:
<XML id='Style' src='Style.xsl'></XML>
我们在页面中加入标记
DIV
来显示我们的转换的结果:
<div id="DisplayArea"></div>
使用
XSLT
转换数据岛里的数据,采用
DOMDocument
的
transNode()
方法,并把结果通过
DIV
的
innerHTML
属性来展现出来:
DisplayArea.innerHTML = Data.transformNode(Style.DocumentElement)
第二步:实现客户端排序的功能
我们先设定一个默认的排序字段,这里选择
“
序号
”
作为默认的排序关键字,并且是按递增的顺序排列,在
XSLT
里加入
sort
标记:
<xsl:for-each select="
客户
">
<xsl:sort select="
序号
" order="descending" data-type="number"/>
</xsl:for-each>
接下来,我们为样式表增加排序的功能,以便可以响应用户的操作,我们在表头的每个列上添加
onClick
事件,该事件调用
sort()
函数,允许用户通过单击该表头来进行对该列的排序。
<td onClick="sort('
序号
')">
序号
</td>
Sort()
函数的语句如下所示:
Function Sort(strField)
Dim sortField
Dim sortOrderAttribute
'
得到原来排序字段的属性值
Set sortField = Style.XMLDocument.selectSingleNode("//xsl:sort/@select")
'
得到原来排序的顺序属性值
Set sortOrderAttribute = Style.XMLDocument.selectSingleNode("//xsl:sort/@order")
'
如果我们已经按所点击的列的字段排序,我们必须改变排序的顺序;
'
否则,我们只需要按新所点击的列字段按默认的顺序进行排序
If sortField.Value = strField Or sortField.Value = "./*[0]" Then
If sortOrderAttribute.Value = "descending" Then
sortOrderAttribute.Value = "ascending"
Else
sortOrderAttribute.Value = "descending"
End If
Else
sortField.Value = strField
sortOrderAttribute.Value = "ascending"
End If
Set sortField = Nothing
Set sortOrderAttribute = Nothing
'
输出排序后的结果
DisplayArea.innerHTML = Data.transformNode(Style.DocumentElement)
End Function
下面,我们实现每页面显示的记录数和设定前页、后页的功能。使用
span
标记显示目前显示的是第几页、共多少页和记录的总数。我们默认每页显示
6
条记录,用变量
intRecordsPerPage
保存该值:
<table width="100%" border="0" style="font-size:9pt">
<tr>
<td align="left"><b>
第
<span id="CurrentPage"></span>
页
总
<span id="PageCount"></span>
页
共有
<span id="RecordCount"></span>
条记录
</b></td>
<td align="right"><b>
每页记录数:
<input onblur="setRecordsPerPage()" id="RecordsPerPage" style="vertical-align:middle;height:15pt;width:30px"/></b></td>
<td align="right">
<span id="Paging">
<input type="button" OnClick="FirstPage()" value="
第一页
"/>
<input type="button" OnClick="previousPage(1)" value="
上一页
"/>
<input type="button" OnClick="nextPage(1)" value="
下一页
"/>
<input type="button" OnClick="LastPage()" value="
最末页
"/>
</span>
</td>
</tr>
</table>
下面以
“
下一页
”
按钮执行的操作为例子,说明转换不同页面的处理过程。该函数根据参数
intPage
来决定要显示的记录的条数和相应的页面,每个按钮
Value
值的变化是通过动态改变
XSL DOM
的内容来实现的:
Function nextPage(intPage)
Dim strDisplay
Dim strDateRange
If CInt(CStr(intPage) * intRecordsPerPage) < _
Data.selectNodes("/
客户关系表
/
客户
").length Then
intPage = CInt(intPage) + 1
Style.XMLDocument.selectNodes("//@OnClick") _
(1).Value = "previousPage(" & intPage & ")"
Style.XMLDocument.selectNodes("//@OnClick") _
(2).Value = "nextPage(" & intPage & ")"
Style.XMLDocument.selectNodes _
("//xsl:for-each/@select")(1).Value = _
"./
客户
[position() <= " & (CStr(intPage) _
* intRecordsPerPage) & " and position() > " _
& (CInt(intPage) - 1) * intRecordsPerPage & _
"]"
redisplay (intPage)
End If
End Function
下面,我们来看看设置每个页面记录条数的函数
setRecordsPerPage()
,该函数通过动态修改
xsl:for-each
的
select
属性值来实现的,使用
XPath
来遍历那些符合节点位置大于
0
并且节点位置小于每页记录数加
1
的那些节点。其中主要的语句是下面的一行:
Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1). _
value = "./
客户
[position() < " & intRecordsPerPage + 1 & " and "& " position() > 0]"
到目前为止,我们的页面既可以实现排序,也实现动态改变每页显示记录条数的功能了,为了实现可重用的要求,我们还可以进行进一步的改进。
XPath
是进行
XML/XSLT
应用开发的一个强有力的工具,
XPath
中可以使用通配符,使
XSLT
样式单文件完全不依赖于你的数据节点名称。因此,我们在改变
XML
数据的时候,只要不改变节点的层次关系,可以不必改动
XSLT
就可以直接使用。比如:在本例中,你可以添加或者删除某些字段、或添加删除一些记录,直接使用本例中的
XSLT
,不但可以在表格里正常显示出数据,而且还能正常排序和分页。
下面我们就分析一下是如何实现的。比如下面的层次关系:
<
客户关系表
>
<
客户
>
<
序号
></
序号
>
<
姓名
></
姓名
>
<
电子邮件
></
电子邮件
>
</
客户
>
</
客户关系表
>
假如我们的
XSLT
中有这样一个选择模板的句子:
<xsl:apply-templates select="/
客户关系表
"/>
为了实现通用性的要求,我们可以使用通配符:
<xsl:apply-templates select="/*"/>
这里我们使用了子运算符
"/"
,它选择了根下的所有节点,两者的不同点在于:
"/
客户关系表
"
选择的是根下的客户关系表子节点,而
"/*"
选择的是根下所有的直接子节点,在上面的
XML
数据格式中,二者是完全等价的。
对于下面的
for-each
循环来说:
<xsl:for-each select="
客户
">
<xsl:sort select="
序号
" order="ascending"/>
</xsl:for-each>
我们可以改变成这样的形式:
<xsl:for-each select="./*">
<xsl:sort select="./*[1]" order="ascending"/>
</xsl:for-each>
这里
"./*"
表示你应当包含进去当前节点下所有的一级子节点,语法
"./*[1]"
表示的是选择当前节点中的第一个子节点。
另外还有一个地方可以改进的是
<xsl:value-of select="
序号
"/>
,我们可以把它改成
<xsl:value-of select="."/>
,表示在每一次循环中选择当前节点。
在我们的函数中,还使用了一些硬代码,如果不做改动的话,我们的通用性还是实现不了,因此,我们下面就看看如何替换硬代码中的语句。
在创建表头的时候,我们使用了
<td onClick="sort('
序号
')">
序号
</td>
的语句,如果
XML
数据里没有序号节点的话,这里显然会出现错误的,为了实现通用性,我们自定义了一个函数
getName
,来取得所要显示的节点的名称:
<td>
<xsl:attribute name="onClick">
Sort('<xsl:value-of select="user:getName(.)"/>')
</xsl:attribute>
<xsl:value-of select="user:getName(.)"/>
</td>
自定义函数是
XSLT
的一个突出的功能,要使用这个特性,我们得用
msxml:script
元素来定义,同时,必须在样式单定义的时候指定一个用户定义的名字空间。下面就是我们使用自定义函数的全部内容:
<xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://lucky.myrice.com"
version="1.0">
<msxsl:script language="VBScript" implements-prefix="user">
<![CDATA[
function getName(node)
getName = node.item(0).nodeName
end function
]]>
</msxsl:script>
在我们的
XSLT
文件中,使用了两个循环,我们分别进行相应的更改,第一处:显示表头的地方改为
<xsl:for-each select="./*[1]/*">
,它等同于
<xsl:for-each select="
客户关系表
/
客户
[1]/*">
;第二处循环是显示每行记录,改成
<xsl:for-each select="./*">
。还有其他的地方需要更改的,请参见后面的完整源代码部分。这样我们就完成了通用的
XSLT
文件,不管你的
XML
数据有多少字段,也不管节点名称是什么,我们都无需更改
XSLT
文件,就可以实现我们的功能了。最终的浏览效果将会象下图所示:
以下是完整的
Style.xsl
文件的内容:
<?xml version="1.0" encoding="gb2312"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="http://lucky.myrice.com" version="1.0">
<msxsl:script language="VBScript" implements-prefix="user">
<![CDATA[
Function getName(node)
getName = node.Item(0).nodeName
End Function
]]>
</msxsl:script>
<xsl:template match="/">
<xsl:apply-templates select="/*"/>
</xsl:template>
<xsl:template match="/*">
<table width="100%" border="0" style="font-size:9pt">
<tr>
<td align="left"><b>
第
<span id="CurrentPage"></span>
页
总
<span id="PageCount"></span>
页
共有
<span id="RecordCount"></span>
条记录
</b></td>
<td align="right"><b>
每页记录数:
<input onblur="setRecordsPerPage()" id="RecordsPerPage" style="vertical-align:middle;height:15pt;width:30px"/></b></td>
<td align="right">
<span id="Paging">
<input type="button" OnClick="FirstPage()" value="
第一页
"/>
<input type="button" OnClick="previousPage(1)" value="
上一页
"/>
<input type="button" OnClick="nextPage(1)" value="
下一页
"/>
<input type="button" OnClick="LastPage()" value="
最末页
"/>
</span>
</td>
</tr>
</table>
<Table WIDTH="100%" BORDER="0" cellpadding="0" cellspacing="1" style="font-size:11pt" bgcolor="#0099ff">
<tr bgcolor="#FF6600" style="cursor: hand;padding:5px">
<xsl:for-each select="./*[1]/*">
<td align="center">
<xsl:attribute name="onclick">
Sort('<xsl:value-of select="user:getName(.)"/>')
</xsl:attribute>
<font color="#EEEEEE"><b><u><xsl:value-of select="user:getName(.)"/></u></b></font>
</td>
</xsl:for-each>
</tr>
<xsl:for-each select="./*[position() < 6 and position() > 0]">
<xsl:sort select="./*[1]" order="ascending"/>
<tr bgcolor="#FFCCFF">
<xsl:for-each select="./*">
<td> <xsl:value-of select="."/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</Table>
</xsl:template>
</xsl:stylesheet>
以下是进行输出的
Exam.htm
文件:
<HTML>
<Head>
<META http=equiv="Content-Type" Content="text/html;charset=gb2312">
<STYLE>
body { font-family:
宋体
; font-size:9pt;}
th { font-family:
宋体
; font-size:11pt; font-weight:bold;}
</STYLE>
<Script language="vbscript">
Option Explicit
Dim intRecordsPerPage '
每个页面显示的记录数
intRecordsPerPage = 6 '
每个页面显示的记录数,默认设定为
6
'
更新显示页面的函数
Function window_onload()
'
显示设定的记录数
Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).Value = "./*[position() < " & intRecordsPerPage + 1 & " and position() > 0]"
transform()
setPageCount()
End Function
'
进行
XML-XSLT
转换,并显示当前记录的一些信息
Function transform()
DisplayArea.innerHTML = Data.transformNode(Style.DocumentElement)
RecordsPerPage.Value = intRecordsPerPage
End Function
'
重新转换
XML
,并显示一个状态信息
Function redisplay(intPage)
Dim strDisplay
Dim intPageCount
Dim intRecordCount
'
保存状态信息
intPageCount = PageCount.innerHTML
intRecordCount = RecordCount.innerHTML
transform()
'
显示状态信息
PageCount.innerHTML = intPageCount
RecordCount.innerHTML = intRecordCount
CurrentPage.innerHTML = intPage
End Function
'
重新排序和显示
Function Sort(strField)
Dim sortField
Dim sortOrderAttribute
'
得到排序属性值
Set sortField = Style.XMLDocument.selectSingleNode("//xsl:sort/@select")
Set sortOrderAttribute = Style.XMLDocument.selectSingleNode("//xsl:sort/@order")
'
改变排序的方式
If sortField.Value = strField Or sortField.Value = "./*[0]" Then
If sortOrderAttribute.Value = "descending" Then
sortOrderAttribute.Value = "ascending"
Else
sortOrderAttribute.Value = "descending"
End If
Else
sortField.Value = strField
sortOrderAttribute.Value = "ascending"
End If
Set sortField = Nothing
Set sortOrderAttribute = Nothing
redisplay (CurrentPage.innerHTML)
End Function
'
重新设置每页的记录数
Function setRecordsPerPage()
If IsNumeric(RecordsPerPage.Value) Then
intRecordsPerPage = CInt(RecordsPerPage.Value)
window_onload
End If
End Function
'
显示页数信息
Function setPageCount()
Dim intTotalRecords
PageCount.innerHTML = getNumberOfPages(intTotalRecords)
RecordCount.innerHTML = intTotalRecords
CurrentPage.innerHTML = 1
End Function
'
计算总页数和总记录数
Function getNumberOfPages(intTotalRecords)
Dim intPages
intTotalRecords = Data.XMLDocument.selectNodes("/*/*").length
intPages = intTotalRecords / intRecordsPerPage
If InStr(intPages, ".") > 0 Then
intPages = CInt(Left(intPages, InStr(intPages, "."))) + 1
End If
getNumberOfPages = intPages
End Function
' “
下一页
”
的处理
Function nextPage(intPage)
Dim strDisplay
Dim strDateRange
If CInt(CStr(intPage) * intRecordsPerPage) < Data.selectNodes("/*/*").length Then
intPage = CInt(intPage) + 1
Style.XMLDocument.selectNodes("//@OnClick")(1).Value = "previousPage(" & intPage & ")"
Style.XMLDocument.selectNodes("//@OnClick")(2).Value = "nextPage(" & intPage & ")"
Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).Value = "./*[position() <= " & (CStr(intPage) * intRecordsPerPage) & " and position() > " & (CInt(intPage) - 1) * intRecordsPerPage & "]"
redisplay (intPage)
End If
End Function
'
处理
“
上一页
”
Function previousPage(intPage)
Dim strDisplay
Dim strDateRange
If intPage > 1 Then
intPage = CInt(intPage) - 1
Style.XMLDocument.selectNodes("//@OnClick")(1).Value = "previousPage(" & intPage & ")"
Style.XMLDocument.selectNodes("//@OnClick")(2).Value = "nextPage(" & intPage & ")"
Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).Value = "./*[position() <= " & (CStr(intPage) * intRecordsPerPage) & " and position() > " & (CInt(intPage) - 1) * intRecordsPerPage & "]"
redisplay (intPage)
End If
End Function
' “
第一页
”
的处理
Function FirstPage()
Style.XMLDocument.selectNodes("//@OnClick")(1).Value = "previousPage(1)"
Style.XMLDocument.selectNodes("//@OnClick")(2).Value = "nextPage(1)"
Style.XMLDocument.selectNodes("//xsl:for-each/@select")(1).Value = "./*[position() < " & intRecordsPerPage + 1 & " and position() > 0]"
transform()
setPageCount()
End Function
' “
最末页
”
的处理
Function LastPage()
Dim intTotalPages
Dim intTotalRecords
intTotalPages = getNumberOfPages(intTotalRecords)
nextPage (intTotalPages - 1)
End Function
</Script>
</Head>
<body>
<p align="center" style="font-weight:bold;font-size:12pt;color:#0000FF;border-bottom:3px double red;padding-bottom:5px">
客户关系表
</p>
<XML id='Data'>
<
客户关系表
xmlns:dt="urn:schemas-microsoft-com:datatypes">
<
客户
><
序号
dt:dt="int">01</
序号
><
姓名
>Mi</
姓名
><
电子邮件
>water@21cn.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">02</
序号
><
姓名
>uyi</
姓名
><
电子邮件
>Lily@sina.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">03</
序号
><
姓名
>uiyu</
姓名
><
电子邮件
>John@21cn.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">04</
序号
><
姓名
>Doug</
姓名
><
电子邮件
>Karry@163.net</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">05</
序号
><
姓名
>Ellen</
姓名
><
电子邮件
>vivki@sina.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">06</
序号
><
姓名
>Frank</
姓名
><
电子邮件
>net_lover@mengxianhui.com.cn</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">07</
序号
><
姓名
>Greg</
姓名
><
电子邮件
>meng@mengxianhui.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">08</
序号
><
姓名
>Harry</
姓名
><
电子邮件
>sunny@xianhui.net</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">09</
序号
><
姓名
>Ingrid</
姓名
><
电子邮件
>cathy@hotmail.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">10</
序号
><
姓名
>Jeff</
姓名
><
电子邮件
>your@mxh.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">11</
序号
><
姓名
>Kelly</
姓名
><
电子邮件
>Iloveyou@mengxianhui.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">12</
序号
><
姓名
>Larry</
姓名
><
电子邮件
>smilling@mengxianhui.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">13</
序号
><
姓名
>Mark</
姓名
><
电子邮件
>money@21cn.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">14</
序号
><
姓名
>Nancy</
姓名
><
电子邮件
>www@yahoo.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">15</
序号
><
姓名
>Peter</
姓名
><
电子邮件
>dotnet@aol.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">16</
序号
><
姓名
>Rachel</
姓名
><
电子邮件
>billgates@microsoft.com</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">17</
序号
><
姓名
>Seth</
姓名
><
电子邮件
>flying@yous.net</
电子邮件
></
客户
>
<
客户
><
序号
dt:dt="int">18</
序号
><
姓名
>Tim</
姓名
><
电子邮件
>agooyboy@lovegirl.com</
电子邮件
></
客户
>
</
客户关系表
>
</XML>
<XML id='Style' src='Style.xsl'></XML>
<div id="DisplayArea"></div>
<table border="0" width="100%" style="font-size:11pt;">
<tr>
<td align="right">
资料来源:【
<a href="http://lucky.myrice.com">
孟宪会之精彩世界
</a>
】
</td>
</tr>
</table>
</body>
</HTML>
把上面的内容拷贝到本地计算机上,分别保存为相应的文件,在
IE5+
和
XML3.0+
的环境下即可看到效果!
posted on 2006-09-30 08:55
charles
阅读(250)
评论(0)
编辑
收藏
所属分类:
xml
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
Chat2DB
C++博客
博问
管理
相关文章:
[转]客户端JScript+XSLT+XML Data Islands排序
资源下载
[转]A XSLT Sample
用XML创建可排序、分页的数据显示页面
js对xml的解析。
My Links
BlogJava
首页
联系
聚合
管理
Blog Stats
Posts - 0
Stories - 25
Comments - 1
Trackbacks - 0
留言簿
给我留言
查看公开留言
查看私人留言
文章分类
java(4)
(RSS)
jdbc(1)
(RSS)
jdk(1)
(RSS)
junit
(RSS)
oracle(1)
(RSS)
tomcat(4)
(RSS)
xml(5)
(RSS)
正则表达式(1)
(RSS)
文章档案
2007年8月 (1)
2006年10月 (1)
2006年9月 (23)
收藏夹
ajax(5)
(RSS)
ant (3)
(RSS)
apache(5)
(RSS)
dom4j
(RSS)
js(2)
(RSS)
jsonrpc(2)
(RSS)
junit(1)
(RSS)
log(2)
(RSS)
oracle(2)
(RSS)
spring(1)
(RSS)
tomcat(2)
(RSS)
windows(1)
(RSS)
xml(3)
(RSS)
xslt(2)
(RSS)
eclipse
Proxy服务器
FCKeditor——强大的HTML文本编辑插件
Hashtable,挺爽的一个东西,大家都用烂了吧,我再画蛇添足一下。
J2EE开发之Eclipse集成开发工具使用篇
Lucene 的学习
prototype 源码解读 之 prototype.js
prototype.js 1.4版开发者手册(强烈推荐)
Squid配置详解+认证完全版
Squid配置详解+认证完全版
使用 Eclipse 平台进行调试
使用XPathExpression类对XML进行排序
利用Squid反相代理缓存实现网站内容静态发布
利用反向代理保护WEB服务器
在项目中,用到的关于时间操作的一些常用方法!!
基于反向代理的Web缓存加速——可缓存的CMS系统设计
我是一个民工
比较好的Java 网站
浅析大型网站的架构
HTML静态化 图片服务器分离 数据库集群和库表散列 缓存 镜像 负载均衡 硬件四层交换 软件四层交换
lucene
Lucene学习笔记一(Lucene结构及其简单使用)
spring
blog 超越黎明
habernate
hibernate中几个包的简介
spring中文论坛
晶晶的space
编程宝典
spring
tools
web开发的浏览器(工具)插件
搜索
最新评论
1. re: 将文件包打包成 jar 文件
asf
--asdf