模板中可以通过模板标签和el表达式及函数用来获取动态数据,控制模板执行流程
在此文中我们介绍如何自定义模板标签和表达式函数
1.自定义标签
标签具有标签名、标签属性、标签体
标签可以控制呈现内容,执行流程
实现步骤
流程控制方法:
I. doStartTag
: 标签开始执行的时候调用,
返回值:
EVAL_BODY_INCLUDE
-表示执行标签体(默认
)
EVAL_BODY_BUFFERED
-执行标签体,并将执行结果放在buffer缓存中
SKIP_BODY
-跳过标签体
SKIP_PAGE
-跳过页面
II.doAfterBody
:标签体执行完成时调用,
返回值
EVAL_PAGE
执行标签后面的页面内容(默认
)
EVAL_BODY_AGAIN
重新执行标签体
III.doEndTag
:整个标签执行完成时调用
一般在此处获取buffer中的内容,对buffer进行处理
返回值
SKIP_PAGE
EVAL_PAGE
(默认
)
AbstractTag
常用属性和方法
context
:模板执行上下文
常用方法:
addDataVariable
:添加一个变量数据,可以在标签体范围内使用el表达式和变量名获取到变量值
addRootVariable
: 向模板执行上下文中添加一个变量,可以在页面范围内使用el表达式和变量名获取到变量值
getOut
:返回当前的TemplateWriter实例,可以用该对象输出内容或获取缓存内容
eval
: 执行一段表达式(一般为el表达式或变量名)
示例:
在该示例中实现了一个执行自定义sql并使用标签体循环呈现查询结果的标签
package com.zving.demo.tag;
import java.util.ArrayList;
import java.util.List;
import com.zving.demo.DemoPlugin;
import com.zving.framework.data.DataTable;
import com.zving.framework.data.DataTypes;
import com.zving.framework.data.QueryBuilder;
import com.zving.framework.template.AbstractTag;
import com.zving.framework.template.TagAttr;
import com.zving.framework.template.exception.TemplateRuntimeException;
import com.zving.framework.utility.StringUtil;
public class SQLInvokeTag extends AbstractTag {
protected String sql;
protected int pageIndex;
protected int pageSize;
protected DataTable dt;
protected int index;
public SQLInvokeTag() {
super();
System.out.println("SQLInvokeTag 构造执行!!!!");
}
@Override
public String getDescription() {
return "执行SQL语句,循环输出结果到标签体";
}
@Override
public String getExtendItemName() {
return "SQLInvokeTag";
}
@Override
public String getPluginID() {
return DemoPlugin.ID;
}
@Override
public String getPrefix() {
return "z";
}
@Override
public String getTagName() {
return "sqlInvoke";
}
@Override
public List<TagAttr> getTagAttrs() {
List<TagAttr> list = new ArrayList<TagAttr>();
list.add(new TagAttr("sql", false, DataTypes.STRING, "要执行的SQL语句"));
list.add(new TagAttr("pageIndex", false, DataTypes.INTEGER, "当前页码"));
list.add(new TagAttr("pageSize", false, DataTypes.INTEGER, "分页大小"));
return list;
}
@Override
public int doStartTag() throws TemplateRuntimeException {
System.out.println("Do start Tag!~!!");
QueryBuilder qb = new QueryBuilder(sql);
if (StringUtil.isNotEmpty(getAttribute("pageSize"))) {
dt = qb.executePagedDataTable(pageSize, pageIndex);
} else {
dt = qb.executeDataTable();
}
if (dt.getRowCount() > 0) {
index = 0;
context.addDataVariable("Value", dt.getDataRow(0));
context.addDataVariable("Index", index);
return EVAL_BODY_INCLUDE;
} else {
return SKIP_BODY;
}
}
@Override
public int doAfterBody() throws TemplateRuntimeException {
System.out.println("Do doAfterBody!~!!");
index = index + 1;
if (index >= dt.getRowCount()) {
return EVAL_PAGE;
} else {
context.addDataVariable("Value", dt.getDataRow(index));
context.addDataVariable("Index", index);
return EVAL_BODY_AGAIN;
}
}
@Override
public int doEndTag() throws TemplateRuntimeException {
return super.doEndTag();
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public int getPageIndex() {
return pageIndex;
}
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
代码1. 实现SQLInvokeTag类,实现标签逻辑
<hr>
sqlInvoke start:
<ul>
<z:sqlInvoke sql="select * from ZDUser" pageIndex="0" pageSize="5">
<li> ${Index }:${Value.UserName} </li>
</z:sqlInvoke>
</ul>
sqlInvoke end!
代码2. 标签使用测试,查询ZDUser 前5行数据
2.自定义页面函数
函数具有方法名、参数列表、返回值
实现步骤
示例:
该示例中实现了反射调用传入对象指定方法的表达式函数
package com.zving.dynamic.function;
import java.lang.reflect.Method;
import com.zving.framework.expression.AbstractFunction;
import com.zving.framework.expression.ExpressionException;
import com.zving.framework.expression.IVariableResolver;
public class Invoke extends AbstractFunction {
@Override
public String getFunctionPrefix() {
return "";
}
@Override
public String getFunctionName() {
return "invoke";
}
@Override
public Class<?>[] getArgumentTypes() {
return new Class<?>[] { Object.class, Object.class };
}
@Override
public Object execute(IVariableResolver resolver, Object... args) throws ExpressionException {
if (args == null || args.length == 0) {
return null;
}
if (args.length == 1) {
return null;
} else if (args.length >= 2) {
Object o = args[0];
String method = (String) args[1];
Class<?>[] paramTypes = new Class<?>[args.length - 2];
Object[] params = new Object[args.length - 2];
for (int i = 2; i < args.length; i++) {
paramTypes[i - 2] = args[i].getClass();
params[i - 2] = args[i];
}
Class<?> clazz = o.getClass();
try {
Method m = clazz.getMethod(method, paramTypes);
return m.invoke(o, params);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
代码3. 实现Invoke类
客户端IP:${invoke(Request,"getClientIP")}
<hr>
客户端:${invoke(Request,"getHeaders")['user-agent']}
代码4. 测试页面代码
所有评论仅代表网友意见