公司框架学习之JSP布局之自定义查询标签《四》
一、效果
图1

图2

二、源码
<query:form name="Form"> <query:selectx name="QUES_TYPE" label="题型" source="SYS.TLX" value=""/> <query:selectx name="QUES_CONFIG" label="题标识" source="SYS.TBS" value=""/> </query:form>
三、源码分析
最外层是easyui的Form表单,源码上已经看不出easyui代码,全用自定义标签封装了,此处的标签内容全是作为输入,为后面封装做参数的。SYS.TLX和SYS.TBS两个参数是从数据库字典中获取的。
1.自定义标签
query标签库:
<%@ taglib uri="http://dev.feiwei.cn/tags/query" prefix="query"%>
query.tld
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org
/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2e
e web-jsptaglibrary_2_0.xsd" version="2.0">
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>query tag</short-name>
<uri>http://dev.feiwei.cn/tags/query</uri>
<tag>
<name>form</name>
<tag-class>com.feiwei.framework.web.tag.query.FormTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>action</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>target</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>onBeforeSubmit</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>cols</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>style</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>validate</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>queryCode</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>dataOptions</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>layout</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>queryParams</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>selectx</name>
<tag-class>com.feiwei.framework.web.tag.query.SelectxTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>placeholder</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>bind</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>event</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>bean</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>label</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>value</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>source</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>style</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>className</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>readonly</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>disabled</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>format</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>multiple</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>colspan</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>fill</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>required</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>validType</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>missingMessage</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>invalidMessage</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>formatter</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>parse</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>choose</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>chooseText</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>includes</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>excludes</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>merge</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>dataOptions</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>panelWidth</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>panelHeight</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>queryParams</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>showOperator</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>operators</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>autoQuery</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>tooltip</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
FormTag.java
package com.feiwei.framework.web.tag.query; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.feiwei.framework.config.QueryConfig; import com.feiwei.framework.pojo.SysQuery; import com.feiwei.framework.util.JSONUtils; import com.feiwei.framework.util.StringUtils; import com.feiwei.framework.web.html.QueryHtml; import com.feiwei.framework.web.html.query.ButtonHtml; import com.feiwei.framework.web.html.query.HiddenHtml; import com.feiwei.framework.web.tag.AbstractTag; import com.feiwei.framework.web.tag.FormContainer; import com.feiwei.framework.web.tag.util.PageUtils; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class FormTag extends AbstractTag implements FormContainer<QueryHtml> { private static final Log log = LogFactory.getLog(FormTag.class); public static final String FORM_INSTANCE = "FORM_INSTANCE"; private List<QueryHtml> inputs = new ArrayList(); private int cols = 3; private String id; private String name; private String action; private String target; private String onBeforeSubmit; private String style; private boolean validate = true; private String queryCode; private String dataOptions; private String layout = "table"; private String queryParams; public void setId(String id) { this.id = id; if (this.name == null) { this.name = id; } } public void setName(String name) { this.name = name; if (this.id == null) { this.id = name; } } public void setAction(String action) { this.action = action; } public void setTarget(String target) { this.target = target; } public void setOnBeforeSubmit(String onBeforeSubmit) { this.onBeforeSubmit = onBeforeSubmit; } public void setCols(int cols) { this.cols = cols; } public void setStyle(String style) { this.style = style; } public void setQueryCode(String queryCode) { this.queryCode = queryCode; } public void setValidate(boolean validate) { this.validate = validate; } public void setDataOptions(String dataOptions) { this.dataOptions = dataOptions; } public void setLayout(String layout) { this.layout = layout; } public void setQueryParams(String queryParams) { this.queryParams = queryParams; } protected void init() { this.jspContext.setAttribute("FORM_INSTANCE", this); } //添加QueryHtml类或其子类入list<QueryHtml>容器中 public void add(QueryHtml item) { this.inputs.add(item); } public void doTag() throws JspException { try { StringBuilder html = getHtml(); this.out.write(html.toString()); this.out.flush(); } catch (Exception e) { log.error(e); e.printStackTrace(); e.printStackTrace(new PrintWriter(this.out)); } finally { this.jspContext.setAttribute("FORM_INSTANCE", null); } } private StringBuilder getHtml() throws Exception { JspFragment body = getJspBody(); //初始化时 layout = "table" if ("table".equals(this.layout)) { if (body != null) { //标签体对象的invoke()用于执行JspFragment对象所代表的JSP代码片段 //参数用于指定将JspFragment对象的执行结果写入到哪个输出流对象中 //执行标签体中标签<query:selectx></query:selectx>,执行完之后将添加两个QueryHtml对象到List中 body.invoke(this.out); } return getTableHtml(); } if ("float".equals(this.layout)) { if (body != null) { body.invoke(this.out); } return getFloatHtml(); } if ("custom".equals(this.layout)) { this.jspContext.setAttribute("FORM_INSTANCE", null); } return new StringBuilder(); } //拼接整个easyui-From表单 public StringBuilder getTableHtml() throws Exception { List<QueryHtml> inputs = getQueryInputs(); List<QueryHtml> params = getParams(getLayoutInputs(inputs)); List<QueryHtml> hiddens = getHiddens(inputs); List<QueryHtml> buttons = getButtons(inputs); StringBuilder html = new StringBuilder(2048); //拼接html,根据jsp页面属性-值 html.append("<form id='" + this.id + "' class='query-form' " + getAction() + getTarget() + getStyle() + getValidate() + getDataOptions() + onBeforeSubmit() + " method='post'> \n"); //拼接input类型为hidden标签 html.append(getHiddenHtml(hiddens)); html.append("\t<table class='query-table' style='width:auto;height:32px;'> \n"); int i = 0; for (int k = 1; i < params.size(); k++) { QueryHtml builder = (QueryHtml) params.get(i); if (k == 1) { html.append("<tr>\n"); } //拼接标签体中子标签html html.append(getParamHtml(builder)); //拼接查询按钮标签 if (k == this.cols) { if (i <= this.cols) { html.append("<td style='text-align:right;white-space:nowrap;'>\n"); for (QueryHtml button : buttons) { html.append(button.getHtml(false)); } html.append("<a type='button' name='_search' class='button query-btn'>查询</a>\n"); html.append("</td>\n"); } else { html.append("<td></td>\n"); } html.append("</tr>\n"); k = 0; } i++; } //收尾 html.append("\t</table> \n"); html.append(getQueryParamsHidden()); html.append("</form> \n"); return html; } public StringBuilder getFloatHtml() throws Exception { List<QueryHtml> params = getQueryInputs(); List<QueryHtml> hiddens = getHiddens(this.inputs); StringBuilder html = new StringBuilder(2048); html.append("<form id='" + this.id + "' class='query-form' " + getAction() + getTarget() + getStyle() + getValidate() + getDataOptions() + " method='post'> \n"); html.append(getHiddenHtml(hiddens)); html.append("<ul style='height:30px;'> \n"); for (int i = 0; i < params.size(); i++) { QueryHtml builder = (QueryHtml) params.get(i); if (builder != null) { String item = builder.getHtml(false); html.append("<li style='margin:5px;float:left'>"); html.append(item); html.append("</li>"); } } html.append("</ul> \n"); html.append(getQueryParamsHidden()); html.append("</form> \n"); return html; } private List<QueryHtml> getQueryInputs() { //初始化 this.queryCode=null 返回原本list集合,有效元素:2 if (this.queryCode != null) { SysQuery query = QueryConfig.getQuery(this.queryCode); List<QueryHtml> list = PageUtils.parseQueryParamJSON(query.getParams()); this.inputs.addAll(list); } return this.inputs; } //判断是否有request private String getAction() { return this.action != null ? " action='" + this.ctx + this.action + "'" : ""; } //判断是否在此页面打开url(response) private String getTarget() { return this.target != null ? " target='" + this.target + "'" : ""; } //判断提交前是否有其他操作 private String onBeforeSubmit() { return this.onBeforeSubmit != null ? " onBeforeSubmit='" + this.onBeforeSubmit + "'" : ""; } private String getStyle() throws Exception { //初始this.style=null,so返回"" if (StringUtils.isValid(this.style)) { return " style='" + this.style + "'"; } return ""; } protected String getDataOptions() { StringBuffer html = new StringBuffer(32); //初始this.dataOptions=null,so返回空字符串 if (StringUtils.isValid(this.dataOptions)) { html.append(" data-options=\"" + this.dataOptions + "\""); } return html.toString(); } //判断是否要验证,默认要验证 private String getValidate() { return " validate='" + this.validate + "'"; } //判断QueryHtml是否null,不会null就调用该QueryHtml的子类的getHtml实现html拼接 //本案例中QueryHtml的子类为SelectxHtml private String getParamHtml(QueryHtml builder) throws Exception { if (builder == null) { return "<td></td><td></td><td></td>"; } return builder.getHtml(true); } private List<QueryHtml> getParams(List<QueryHtml> items) { //初始化时 items.size=2 ,this.cols=3 int more = items.size() % this.cols; if (more > 0) { //more=1 more = this.cols - more; } //在原基础上追加一个null元素 for (int i = 0; i < more; i++) { items.add(null); } return items; } private List<QueryHtml> getLayoutInputs(List<QueryHtml> items) { List<QueryHtml> visibles = new ArrayList(); //标签体中子标签返回list类型QueryHtml,本方法返回2个有效元素的List集合 for (QueryHtml input : items) { if ((!(input instanceof HiddenHtml)) && (!(input instanceof ButtonHtml))) { visibles.add(input); } } return visibles; } private StringBuilder getHiddenHtml(List<QueryHtml> items) throws Exception { List<QueryHtml> hiddens = getHiddens(items); StringBuilder html = new StringBuilder(128); //hiddens为空集合,so返回空字符串 for (QueryHtml hidden : hiddens) { html.append(hidden.getHtml(false)); } return html; } private List<QueryHtml> getHiddens(List<QueryHtml> items) { List<QueryHtml> hiddens = new ArrayList(); //items类型为QueryHtml,so返回空集合 for (QueryHtml input : items) { if ((input instanceof HiddenHtml)) { hiddens.add(input); } } return hiddens; } private List<QueryHtml> getButtons(List<QueryHtml> items) { List<QueryHtml> hiddens = new ArrayList(); //items类型为QueryHtml,so返回空集合 for (QueryHtml input : items) { if ((input instanceof ButtonHtml)) { hiddens.add(input); } } return hiddens; } private StringBuilder getQueryParamsHidden() { StringBuilder html = new StringBuilder(128); if (StringUtils.isEmpty(this.queryParams)) { return html; } JSONArray array = null; if (this.queryParams.startsWith("[")) { array = JSONArray.fromObject(this.queryParams); } else { JSONObject object = (JSONObject) JSONUtils.parse(this.queryParams); array = JSONUtils.toNameValueJSONArray(object); } for (int i = 0; i < array.size(); i++) { JSONObject object = array.getJSONObject(i); String name = JSONUtils.getString(object, "name"); String value = JSONUtils.getString(object, "value", ""); String op = JSONUtils.getString(object, "op"); html.append("<input type='hidden' id='" + name + "' name='" + name + "' value='" + value + "'/>\n"); if (StringUtils.isValid(op)) { html.append("<input type='hidden' id='" + name + "_OP' name='" + name + "_OP' value='" + op + "'/>\n"); } } return html; } }
SelectxTag.java
package com.feiwei.framework.web.tag.query; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.feiwei.framework.web.html.QueryHtml; import com.feiwei.framework.web.html.query.QueryHtmlFactory; import com.feiwei.framework.web.util.TagParam; import com.feiwei.framework.web.util.TagParamSupport; /** * 本类中没有重写doTag()方法,so要到父类QueryTag中去找 * @author hongloumeng * */ public class SelectxTag extends QueryTag implements TagParamSupport { private static final Log log = LogFactory.getLog(SelectxTag.class); public void setOnSelect(String onSelect) { this.context.set("onSelect", onSelect); } public void setSource(String source) { this.context.set("source", source); } public void setMultiple(String multiple) { this.context.set("multiple", multiple); } public void setIncludes(String includes) { this.context.set("includes", includes); } public void setExcludes(String excludes) { this.context.set("excludes", excludes); } public void setPanelHeight(String height) { this.context.set("panelHeight", height); } public void setPanelWidth(String width) { this.context.set("panelWidth", width); } protected QueryHtml getItem() { //this.request和this.cotext是父类AbstractTag中的属性return QueryHtmlFactory.getSelectx(this.request, this.context); } public void addTagParam(TagParam parameter) { if ("sql".equals(parameter.getName())) { this.context.set("source", "sql:\n" + parameter.getValue()); } else { this.context.set(parameter.getName(), parameter.getValue()); } } }
QueryTag.java
package com.feiwei.framework.web.tag.query; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.feiwei.framework.web.html.QueryHtml; import com.feiwei.framework.web.html.bean.ParamContext; import com.feiwei.framework.web.tag.AbstractTag; import com.feiwei.framework.web.tag.FormContainer; import com.feiwei.framework.web.util.TagParam; public abstract class QueryTag extends AbstractTag { private static final Log log = LogFactory.getLog(QueryTag.class); protected ParamContext context = new ParamContext(); protected String id; protected String name; public void setId(String id) { this.context.set("id", id); this.context.set("name", id); } public void setName(String name) { this.context.set("name", name); } public void setLabel(String label) { this.context.set("label", label); } public void setValidate(String validate) { this.context.set("validate", validate); } public void setReadonly(String readonly) { this.context.set("readonly", readonly); } public void setStyle(String style) { this.context.set("style", style); } public void setParse(String parse) { this.context.set("parse", parse); } public void setFormat(String format) { this.context.set("format", format); } public void setClassName(String className) { this.context.set("className", className); } public void setValue(String value) { this.context.set("value", value); } public void setRequired(String required) { this.context.set("required", required); } public void setOptions(String options) { this.context.set("options", options); } public void setOperators(String operators) { this.context.set("operators", operators); } public void setOnChange(String onchange) { this.context.set("onChange", onchange); } public void setOnClick(String onClick) { this.context.set("onClick", onClick); } public void setValidType(String validType) { this.context.set("validType", validType); } public void setDataOptions(String dataOptions) { this.context.set("dataOptions", dataOptions); } public void setCustom(String custom) { this.context.set("custom", custom); } public void setBind(String bind) { this.context.set("bind", bind); } public void setEvent(String event) { this.context.set("event", event); } public void setPlaceholder(String placeholder) { this.context.set("placeholder", placeholder); } public void setShowOperator(String showOperator) { this.context.set("showOperator", showOperator); } public void setAutoQuery(String autoQuery) { this.context.set("autoQuery", autoQuery); } public void setTooltip(String tooltip) { this.context.set("tooltip", tooltip); } //判断是否在form标签体中 public boolean isInForm() { return getFormInstance() != null; } //获取Form标签对象 public FormTag getFormInstance() { //Tag文件为了给JSP页面返回一个对象,就必须将对象的名字以及该对象的引用存储到TomCat引擎提供的内置对象jspContext中, //这样,jsp页面才能使用该对象。 FormTag instance = (FormTag) this.jspContext.getAttribute("FORM_INSTANCE"); return instance; } public void addTagParam(TagParam bean) { super.addTagParam(bean); this.context.set(bean.getName(), bean.getValue()); } //本类只是定义方法,实现在子类中完成,本案例是在Selectx类中重写 protected abstract QueryHtml getItem(); public void doTag() throws IOException, JspException { //判断是否在form标签体中 boolean inForm = isInForm(); //获取标签体内容 JspFragment body = getJspBody(); if (body != null) { //执行标签体JSP代码,将结果写入输出流中,本案例中该标签的标签体为空,so没有任何处理 body.invoke(this.out); } //获取QueryHtml对应的子类对象 QueryHtml builder = getItem(); //判断是否在form标签体中 if (inForm) { //是则将该子标签对象添加进List<QueryHtml>容器中 FormContainer<QueryHtml> form = getFormInstance(); form.add(builder); } else { //不是则将该标签当作独立标签处理 Writer out = getWriter(); try { String html = builder.getHtml(false); out.write(html); } catch (Exception e) { log.error(e); e.printStackTrace(new PrintWriter(out)); } } } }
QueryHtmlFactory.java
package com.feiwei.framework.web.html.query; import com.feiwei.framework.web.html.QueryHtml; import com.feiwei.framework.web.html.bean.ParamContext; import javax.servlet.http.HttpServletRequest; public class QueryHtmlFactory { //返回QueryHtml其下子类,本案例返回SelectxHtml类,ParamContext类用作将标签中属性和值按照键值对存入容器中 public static QueryHtml getSelectx(HttpServletRequest request, ParamContext param) { return new SelectxHtml(request, param); } }
SelectxHtml.java
package com.feiwei.framework.web.html.query; import com.feiwei.framework.config.DictConfig; import com.feiwei.framework.pojo.SysDict; import com.feiwei.framework.util.BeanUtils; import com.feiwei.framework.util.Option; import com.feiwei.framework.util.StringUtils; import com.feiwei.framework.web.html.bean.ParamContext; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class SelectxHtml extends AbstractQueryHtml { public static final String CHOOSE_TEXT = "chooseText"; public SelectxHtml(HttpServletRequest request, ParamContext param) { super(request, param); } //拼接selectx public String getHtml(boolean wrap) throws Exception { StringBuilder html = new StringBuilder(1024); String uid = String.valueOf(System.nanoTime()); List<Option> options = (List) getSource(); int defPanelHeight = options.size() * 25 > 200 ? 200 : options.size() * 25; String value = StringUtils.asString(getValue()); append(html, new String[] { "<input class='easyui-selectx' " + getStyle("width:120px;") + " id='" + this.name + "' name='" + this.name + "' uid='" + uid + "' parse='true' input='true' value='" + value + "'" }); append(html, new String[] { getEvent(), getBind(), getPlaceholder(), getTooltip(), getDataOptions(), getLabel(), getMultiple(), getRequired(), getValidType(), getReadonly(), getDict(), getIncludes(), getExcludes(), getAutoQuery(), "/> \n" }); String sourceId = "source-" + uid; String templateId = "template-" + uid; append(html, new String[] { getSource(options, sourceId) }); append(html, new String[] { getTemplate(templateId) }); return wrap(this.label, html.toString(), wrap); } //从数据库字典中加载数据 protected String getSource(List<Option> options, String dataId) throws Exception { Set<String> excludes = BeanUtils.toSet(this.excludes); Set<String> includes = BeanUtils.toSet(this.includes); JSONArray array = new JSONArray(); for (Option bean : options) { JSONObject object = new JSONObject(); String value = StringUtils.asString(bean.getValue()); if ((!excludes.contains(value)) && ((includes.isEmpty()) || (includes.contains(value))) && (!"0".equals(bean.getStatus()))) { String text = StringUtils.asString(bean.getText()); object.put("value", value); object.put("text", text); array.add(object); } } return toScriptTextPlain(array.toString(), dataId); } }
还有AbstractQueryHtml.java、QueryHtml.java、Html.java没写,根据名称,大概也能猜出他们的作用了。
源码编译后html代码:
<form id="Form" class="query-form" validate="true" method="post">
<table class="query-table" style="width:auto;height:32px;">
<tbody>
<tr>
<td class="label">题型:</td>
<td class="condition" colspan="2"><input class="easyui-selectx" style="width:120px;" id="QUES_TYPE" name="QUES_TYPE" uid="672797880083098" parse="true" input="true" value="" data-event="" data-bind="value:QUES_TYPE" placeholder="" label="题型" dict="SYS.TLX" includes="" excludes="" /> <script id="source-672797880083098" type="text/plain">[{"value":"1","text":"Java基础"},{"value":"2","text":"Java多线程"},{"value":"3","text":"Java集合"},{"value":"4","text":"Http协议与Socket以及网络编程"},{"value":"5","text":"JavaWeb基础"},{"value":"6","text":"spring与spring mvc"},{"value":"7","text":"Hibernate与Mybatis"},{"value":"8","text":"Maven与Linux常用命令"},{"value":"9","text":"项目相关知识"}]</script> </td>
<td class="label">题标识:</td>
<td class="condition" colspan="2"><input class="easyui-selectx" style="width:120px;" id="QUES_CONFIG" name="QUES_CONFIG" uid="672797881060657" parse="true" input="true" value="" data-event="" data-bind="value:QUES_CONFIG" placeholder="" label="题标识" dict="SYS.TBS" includes="" excludes="" /> <script id="source-672797881060657" type="text/plain">[{"value":"0","text":"单选题"},{"value":"1","text":"多选题"}]</script> </td>
<td></td>
<td></td>
<td></td>
<td style="text-align:right;white-space:nowrap;"> <a type="button" name="_search" class="button query-btn">查询</a> </td>
</tr>
</tbody>
</table>
</form>
整个源码阅读过来,只要清楚自定义标签基本流程,按照流程阅读源码,即使再多封装、继承以及其他设计模式、debug一步步追踪,整个流程走一遍,基本就清楚了。
总结:用自定义标签来封装easyui_form表单,form标签下可以有多种查询标签,用一个Query来包含所有query类型的子类标签,每种query标签展示用工厂设计模式来同一展示,省去多余代码。
为何要封装原始html代码?如何每个页面都写手写easyui代码,存在大量重复代码,比如基本页面布局、css样式、js文件引入,在加上一种标签有很多属性,没种属性都有不同用法,导致代码庞大,代码没有规范等。一旦封装了,代码量大幅下降,代码编写也规范,性能也提高。至于为何公司要自己写内部框架?个人认为,通用框架搭建,在实现生产中会出现产能过剩或不够用等麻烦,而架构师就需要根据需求去平衡,到达性能最优(用最少的代码实现更优秀的功能)。
浙公网安备 33010602011771号