DataGrid自定义标签剖析
Jeecg中定义了很多自定义标签,使用起来非常方便,而它们实际上就是对easyui的插件进行了一层封装。本文将以DataGrid标签为例,对自定义标签如何编写,如何定义处理类,前后台交互流程等进行剖析,从而让开发者更易于使用这些自定义标签。
如何自定义标签
自定义JSP标签有标准的语法格式,可参考链接:自定义标签。
Jeecg中datagrid
标签定义在easyui.tld文件中,有关datagrid
的部分定义如下:
<tag>
<name>datagrid</name>
<tag-class>org.jeecgframework.tag.core.easyui.DataGridTag</tag-class>
<body-content>JSP</body-content>
<description>数据列表</description>
<attribute>
<name>actionUrl</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>分页提交的路径</description>
</attribute>
<!-- update-begin author:xuelin date:20171116 for:TASK #2404 【平台UI改造】UI样式改造点 5.参考fineui,做下字段过滤功能效果 -->
<attribute>
<name>filter</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>是否启用过滤</description>
</attribute>
<!-- update-end author:xuelin date:20171116 for:TASK #2404 【平台UI改造】UI样式改造点 5.参考fineui,做下字段过滤功能效果 -->
<!-- update-begin-Author:xuelin Date:20170523 for:TASK #2002 【UI优化】列表上方button样式改造方案 -->
<attribute>
<name>btnCls</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>列表上方button样式class属性</description>
</attribute>
</tag>
从上述定义可以看出,datagrid
标签的处理类为DataGridTag
,稍后将对DataGridTag
类进行剖析。
自定义datagrid标签使用
编写一个测试的jsp页面datagrid.jsp,内容为:
<t:datagrid actionUrl="jeecgUiTagDemoController.do?datagrid"
name="jeecgDemoList" title="datagrid标签讲解">
<t:dgCol title="id" field="id" hidden="true" queryMode="group" width="120" />
<t:dgCol title="名称" hidden="false" field="name" query="true"
autocomplete="true" width="120" />
<t:dgCol title="部门" hidden="false" field="depId" queryMode="single"
dictionary="t_s_depart,id,departname" width="120" />
<t:dgCol title="性别" field="sex" showMode="checkbox" dictionary="sex"
width="120" />
<t:dgCol title="电话" query="true" field="phone" width="120" />
<t:dgCol title="工资" field="salary" queryMode="group" width="120" />
<t:dgCol title="创建日期" field="createDate" formatter="yyyy-MM-dd"
queryMode="group" />
</t:datagrid>
可以发现,datagrid
标签中的属性如actionUrl
就是在easyui.tld文件中定义的。dgCol
是一个新的标签,通过本文的思路即可对其进行分析,故不在此赘述。
DataGridTag类剖析
自定义的标签处理类都需要实现JspTag
接口。该接口有两个子接口,分别为Tag
和SimpleTag
。这两个接口又有两个直接的实现类:IterationTag
和SimpleTagSupport
,而TagSupport
继承了IterationTag
类。其关系如图所示:。
doStartTag()和doEndTag()
对于DataGridTag
类,它继承了TagSupport
类,该类中的两个关键函数为doStartTag()
和doEndTag()
。doStartTag()
是当Web容器解析到JSP中datagrid标签的开始处时调用,doEndTag()
则是解析到标签的闭合处时调用。重写这两个函数可以改变遇到该标签的解析策略,有如下四种:
- EVAL_BODY_INCLUDE 表示执行标签体内的内容,接着调用
doAfterBody()
方法。 - SKIP_BODY 表示跳过标签体的内容,直接执行
doEndTag()
方法。 - EVAL_PAGE 表示继续执行闭合标签后边的内容。
- SKIP_PAGE 表示跳过闭合标签后边的内容。
DataGridTag
中doEndTag()
方法的部分源码如下:
public int doEndTag() throws JspException {
JspWriter out = null;
try {
title = MutiLangUtil.doMutiLang(title, langArg);
out = this.pageContext.getOut();
if("bootstrap-table".equals(component)){
ComponentFactory componentFactory = new BootstrapTableComponent();
String content = componentFactory.invoke("/org/jeecgframework/tag/core/factory/ftl/component/bootstrapTable.ftl", getDataGridTag());
StringBuffer bst = new StringBuffer();
bst.append(content);
if(superQuery) {
addSuperQueryBootstrap(bst,btnCls,columnList);
}
out.print(bst.toString());
}else{
out.print(end().toString());
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(out!=null){
try {
out.clearBuffer();
// 清空资源
urlList.clear();
toolBarList.clear();
columnValueList.clear();
columnStyleList.clear();
columnList.clear();
fields = "";
searchFields = "";
} catch (Exception e) {
e.printStackTrace();
}
}
}
return EVAL_PAGE;
}
在浏览器端按F12
查看服务器返回的结果可知,上述代码走的是end().toString()
这处代码块。
属性赋值
在end()
方法中,所做的事情就是根据datagrid.jsp页面传递的值进行整合,拼接,并返回给浏览器。Web容器在解析自定义标签时,如果遇到了自定义的属性,就会调用DataGridTag
类中对应属性的set方法,给相关字段赋值,从而能在end()
方法中使用。接下来拿actionUrl
属性举例说明。
在datagrid.jsp中,有actionUrl="jeecgUiTagDemoController.do?datagrid"
。DataGridTag
类中,有如下方法:
public String getActionUrl() {
return actionUrl;
}
public void setActionUrl(String actionUrl) {
this.actionUrl = actionUrl;
}
在end()
方法中,actionUrl
的使用如下:
if(autoLoadData)
sb.append("url:\'" + actionUrl + "&field=" + fields + "\',");
else
sb.append("url:\'',");
正因为此,浏览器拿到的数据中有如下内容:
$('#jeecgDemoList').datagrid({
idField: 'id',
title: 'datagrid标签讲解',
url: 'jeecgUiTagDemoController.do?datagrid&field=id,name,depId,sex,phone,salary,createDate,'
···
jQuery EasyUI的DataGrid插件封装
Jeecg中对EasyUI常用的插件都有其对应的封装类,如DataGrid
类就是对DataGrid插件进行了封装。因为DataGrid插件访问的服务器地址为jeecgUiTagDemoController.do?datagrid
,同时附带了field=id,name,depId,sex,phone,salary,createDate
参数,所以DataGrid
类中必须有filed
字段。如果DataGrid插件使用了分页功能,插件自身会向后台传递page
和rows
这两个属性值,所以DataGrid
类也必须有这两个属性。正因为上述原因,我们的JeecgUiTagDemoController
类中对datagrid的访问拦截可以定义如下方法:
@RequestMapping(params = "datagrid")
public void datagrid(JeecgDemoEntity jeecgDemo, HttpServletRequest request, HttpServletResponse response, DataGrid dataGrid) {
}
其中JeecgDemoEntity
类不用在意,其只是对查询内容的一个封装,函数调用时该对象为null,在实际查询时为该对象赋值。如果调试源码可以发现,dataGrid对象中field字段被赋值为id,name,depId,sex,phone,salary,createDate
。jQuery中EasyUI的DataGrid插件数据传递和返回的格式可参考以下博文:jquery easyui中datagrid数据传递和返回的格式。
后记
至此,对Jeecg中DataGrid标签的剖析至此结束。了解了这些内容,相信大家对Jeecg中自定义标签的使用可以更加得心应手,也更容易进行二次开发。