项目需求:jsp页面自定义搜索行,点击a标签搜索分类,重新刷新页面,select标签加载数据后由js控制搜索请求链接。
内容:搜索行主要包括A标签 和select标签,a标签生成时带href,具体内容由request获取的属性和属性值生成。select标签实现页面刷新时加载初始化数据即可。
这里只需要实现三个自定义标签即可:
1.父标签:
selectlineTag,主要存放表示搜索指定分类的初始化值。
2.子标签:
ATag:a标签,搜索某类的指定值,点击后带上这个标签代表的查询分类值,请求后台查询。
SelectTag:select标签。
custom.tld 放在WEB-INF/文件夹下,自定义标签所需jar包:jsp-api.jar,servlet-api.jar
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>search row tld</short-name> <tag> <name>searchline</name> <tag-class>com.test.tag.SearchlineTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>defaulvalue</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>选择行的默认值(选择行包括a 和select标签,默认值包括这些标签对应的值)。缺省值:""。</description> </attribute> <attribute> <name>defaultcls</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>行选择其子项被选中时的class样式缺省值:""。</description> </attribute> <attribute> <name>basehref</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>子项a标签href搜索链接地址:""。</description> </attribute> <attribute> <name>defaultsplit</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>默认值分组符号,有时候默认值对应多个组件的值,多个select时用到:""。</description> </attribute> </tag> <tag> <name>select</name> <tag-class>com.test.tag.selectTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>type</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>select类型,值:num|""。num数值时数据可以传start下拉选框的开始范围,end,step每个下拉项步长。属性缺省值:""。</description> </attribute> <attribute> <name>displayField</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>缺省值:""。</description> </attribute> <attribute> <name>valueField</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>缺省值:""。</description> </attribute> <attribute> <name>defaultValNo</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>对应父标签defaultvalue中的值第几个值,"杭州-下城区",0:杭州,1:下城区。缺省值:""。</description> </attribute> <attribute> <name>defaultValNo</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>对应父标签defaultvalue中的值第几个值,"杭州-下城区",0:杭州,1:下城区。缺省值:""。</description> </attribute> <attribute> <name>cls</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>select标签本身需要带有的样式。缺省值:""。</description> </attribute> <attribute> <name>style</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>。缺省值:""。</description> </attribute> <attribute> <name>data</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>select标签数据内容。缺省值:""。</description> </attribute> <attribute> <name>show</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>初始化时是否展示这个select html标签,show可选值:select 有选中值时显示,all 显示,no 不显示。 缺省值:""。</description> </attribute> <attribute> <name>start</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>type属性为num时,如年份表示option中年份开始时间。 缺省值:""。</description> </attribute> <attribute> <name>end</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>type属性为num时,如年份表示option中年份结束时间。 缺省值:""。</description> </attribute> <attribute> <name>step</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>type属性为num时,表示option中年份值步长。 缺省值:""。</description> </attribute> <attribute> <name>prompText</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>下拉框不代表任何选中的值,一般放在下拉选框的第一个选项,如“请选择”</description> </attribute> </tag> <tag> <name>a</name> <tag-class>com.test.tag.ATag</tag-class> <body-content>scriptless</body-content> <attribute> <name>type</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>href标记的属性值。缺省值:""。</description> </attribute> <attribute> <name>cls</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>a标签的样式。缺省值:""。</description> </attribute> <attribute> <name>needhref</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>是否需要href标签,根据父标签的basehref生成。缺省值:""。</description> </attribute> <attribute> <name>text</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>a标签的文本内容。缺省值:""。</description> </attribute> <attribute> <name>key</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>查询中a标签代表的字段名,生成href时在basehref基础上修改。缺省值:""。</description> </attribute> <attribute> <name>value</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>a标签的值和其父标签的defaultvalue对应,且和key对应。缺省值:""。</description> </attribute> <attribute> <name>basehref</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>父级标签带了,这里就不需要了。搜索链接地址:""。</description> </attribute> </tag> </taglib>
父级标签:searchlineTag
package com.test.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class SearchlineTag extends SimpleTagSupport { private String label; private String basehref; private String defaultcls; private String defaulvalue; private String defaultsplit; public String getDefaultsplit() { if (defaultsplit == null || "".equals(defaultsplit)) { return "-"; } return defaultsplit; } //此处省略 get/set.... public void doTag() throws JspException, IOException { //SearchlineTag 标签作用显示标签体,以及作为其他两个标签的父标签; getJspBody().invoke(null); } }
子标签:A标签实现
public class ATag extends SimpleTagSupport { private String key; private String value; private String text; private String needhref; private String type; private String cls; private String basehref; //此处省略 get/set..... public void doTag() throws JspException, IOException { PageContext pageContext = (PageContext) this.getJspContext(); ServletRequest request = pageContext.getRequest(); JspFragment jspFragment = this.getJspBody(); String content = ""; if (this.text != null) { content = this.text; } SearchlineTag parent = null; if (getParent() instanceof SearchlineTag) { parent = (SearchlineTag) getParent(); } else { // 如果在父级和子标签中还嵌套了其他标签如<c:if>要访问父级以上的标签就用这个。 parent = (SearchlineTag) ATag.findAncestorWithClass(this, SearchlineTag.class); } String hrefstr = ""; String clsStr = ""; String adefaultv = ""; String defaultcls = ""; String pbasehref = ""; if (parent != null) { adefaultv = parent.getDefaulvalue(); defaultcls = parent.getDefaultcls(); pbasehref = parent.getBasehref(); } if (adefaultv.equals(this.value) && defaultcls != "") { clsStr = " class =‘" + (this.cls != null ? this.cls : "") + " " + defaultcls + "‘"; } else { clsStr = " class =‘" + (this.cls != null ? this.cls : "") + "‘"; } if ("false".equals(this.needhref)) { hrefstr = " href=‘javascript:void(0);‘ "; } else if ("true".equals(this.needhref)) { if (this.basehref != null) { pbasehref = this.basehref; } hrefstr = " href=‘" + replaceHref(pbasehref, this.key, this.value) + "‘ "; } JspWriter out = getJspContext().getOut(); String outstr = ""; outstr = "<a "; outstr += hrefstr + clsStr; outstr += ">" + content + "</a>"; out.println(outstr); } //替换搜索链接中标签代表的键和值 public String replaceHref(String baseHref, String replaceKey, String replaceValue) { if (replaceKey == null || "".equals(replaceKey)) { return baseHref; } if (replaceValue == null) { replaceValue = ""; } String[] bhref = baseHref.split("\\?"); String[] paramhref = null; List newParam = new ArrayList(); boolean ischecked = false; String newHref = ""; if (bhref.length > 1) { paramhref = bhref[1].split("&"); } if (paramhref != null) { int size = paramhref.length; for (int i = 0; i < size; i++) { String ps = paramhref[i]; String[] ins = ps.split("="); if (replaceKey.equals(ins[0])) { String inns = "" + ins[0] + "=" + replaceValue; newParam.add(inns); ischecked = true; } else { newParam.add(ps); } } } if (!ischecked) { newParam.add("" + replaceKey + "=" + replaceValue); } int newsize = newParam.size(); for (int k = 0; k < newsize; k++) { newHref += newParam.get(k).toString(); if (k < newsize - 1) { newHref += "&"; } } return bhref[0] + "?" + newHref; } }
select标签实现:
public class selectTag extends SimpleTagSupport { private String data; private String key; private String value; private String text; private String cls; private String style; private String valueField; private String displayField; private String defaultValNo; private String show; private String start; private String end; private String step; private String type; private String prompText; //此处省略get/set。。。 z这里吧属性和tld中的属性对应 public void doTag() throws JspException, IOException { PageContext pageContext = (PageContext) this.getJspContext(); ServletRequest request = pageContext.getRequest(); String selectdata = this.data != null ? this.data : "[]"; String content = ""; String clsStr = ""; Integer startsel = null; Integer endsel = null; Integer stepsel = null; if (this.start != null) { try { startsel = Integer.parseInt(this.start); } catch (Exception e) { } } if (this.end != null) { try { endsel = Integer.parseInt(this.end); } catch (Exception e) { } } if (this.step != null) { try { stepsel = Integer.parseInt(this.step); } catch (Exception e) { } } if (this.text != null) { content = this.text; } if (this.valueField == null) { this.valueField = "value"; } if (this.displayField == null) { this.displayField = "text"; } if (this.defaultValNo == null) { this.defaultValNo = "0"; } if (this.cls == null) { this.cls = ""; } else { clsStr = " class=‘" + this.cls + "‘"; } if (this.style == null) { this.style = ""; } if (this.show == null) { this.show = "all"; } if (this.type == null) { this.type = ""; } SearchlineTag parent = null; if (getParent() instanceof SearchlineTag) { parent = (SearchlineTag) getParent(); } else { parent = (SearchlineTag) ATag.findAncestorWithClass(this, SearchlineTag.class); } String optionstr = ""; String seloptionstr = ""; String adefaultv = ""; String defaultcls = ""; String pbasehref = ""; String defaultsplit = "-"; String[] adefaultvs = null; if (parent != null) { adefaultv = parent.getDefaulvalue(); defaultcls = parent.getDefaultcls(); pbasehref = parent.getBasehref(); defaultsplit = parent.getDefaultsplit(); } if (adefaultv != null && !"".equals(adefaultv)) { adefaultvs = adefaultv.split(defaultsplit);// defaultsplit:"-" int index = Integer.parseInt(this.defaultValNo); if (index < adefaultvs.length) { adefaultv = adefaultvs[index]; } else { adefaultv = null; } } if (!"".equals(selectdata)) { JSONArray datajson = JSONArray.fromObject(selectdata); int size = datajson.size(); for (int k = 0; k < size; k++) { Map map2 = (Map) datajson.get(k); String val = (String) map2.get(this.valueField); String textv = (String) map2.get(this.displayField); if (adefaultv != null && val.equals(adefaultv)) { seloptionstr = "<option value=‘" + val + "‘ selected>" + textv + "</option>"; } optionstr += "<option value=‘" + val + "‘ >" + textv + "</option>"; } } if ("num".equals(this.type) && ("[]".equals(selectdata) || "".equals(selectdata)) && startsel != null && endsel != null && stepsel != null) {// year // 的值是数值类型select。 Integer numV = null; try { numV = Integer.parseInt(adefaultv); } catch (Exception e) { numV = null; } if (stepsel < 0) { for (int k = startsel; k >= endsel; k = k + (stepsel)) { if (adefaultv != null && numV != null && k == numV) { seloptionstr = "<option value=‘" + k + "‘ selected>" + k + "</option>"; } optionstr += "<option value=‘" + k + "‘ >" + k + "</option>"; } } else if (stepsel > 0) { for (int k = startsel; k <= endsel; k = k + stepsel) { if (adefaultv != null && numV != null && k == numV) { seloptionstr = "<option value=‘" + k + "‘ selected>" + k + "</option>"; } optionstr += "<option value=‘" + k + "‘ >" + k + "</option>"; } } else { if (adefaultv != null && numV != null && startsel == numV) { seloptionstr = "<option value=‘" + startsel + "‘ selected>" + startsel + "</option>"; } optionstr += "<option value=‘" + startsel + "‘ >" + startsel + "</option>"; } } JspWriter out = getJspContext().getOut(); String outstr = ""; if ("no".equals(this.show) || ("select".equals(this.show) && "".equals(seloptionstr))) { clsStr += " style=‘" + this.style + ";display:none;‘"; } else if (!"".equals(this.style)) { clsStr += " style=‘" + this.style + "‘"; } if (this.prompText != null) { if ("".equals(seloptionstr)) {// 未有选中值,提示的内容默认选中。 seloptionstr = "<option value=‘请选择‘ selected>" + this.prompText + "</option>"; } else { seloptionstr += "<option value=‘请选择‘ >" + this.prompText + "</option>"; } } outstr = "<select "; outstr += clsStr; outstr += ">" + seloptionstr + optionstr + "</select>"; out.println(outstr); } }
jsp使用:
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <%@ taglib uri="/WEB-INF/custom.tld" prefix="cst" %> <%@page import="java.net.URLEncoder"%> <%@page import="java.util.*"%> <%@page import="java.text.*"%> <%@page import="net.sf.json.JSONArray"%> <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title></title> </head> <body > <% request.setCharacterEncoding("UTF-8"); //String key = java.net.URLEncoder.encode(request.getParameter("key"), "UTF-8"); String key ="a";//搜索关键字 String area = ""; String time= "";//生成时间 String issue_time ="2014-2017";//发布时间 String pageses= ""; String parentarea = ""; String subarea = ""; request.setAttribute("parentarea","[{\"name\":\"杭州\"},{\"name\":\"绍兴\"},{\"name\":\"湖州\"}]"); request.setAttribute("subarea","[{\"name\":\"拱墅区\"},{\"name\":\"西湖区\"},{\"name\":\"上城区\"}]"); String basehref="search?key="+key+"&area="+area+"&time="+time +"&issue_time="+issue_time+"&pageses="+pageses; String yeardata=""; Date myDate = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy"); String startyear= dateFormat.format(myDate.getTime()); request.setAttribute("start",startyear); request.setAttribute("end",Integer.parseInt(startyear)-100); String hasLogin = request.getAttribute("isLogin") != null ? request.getAttribute("isLogin").toString() : ""; %> <div class="area"> <span>地 区:</span> <cst:searchline defaultcls="onclick" defaulvalue="<%=area%>" defaultsplit="-" basehref="<%=basehref %>" > <cst:a needhref="true" key="area" value="" text="不限" ></cst:a> <cst:select prompText="请选择" cls="regon" defaultValNo="0" data="${parentarea}" displayField="text" valueField="value"> </cst:select> <cst:select prompText="请选择" cls="regonin" defaultValNo="1" show="select" data="${subarea}" displayField="text" valueField="value" > </cst:select> </cst:searchline> </div> <div class="issue_time"> <span>发布时间:</span> <cst:searchline defaultcls="onclick" defaulvalue="<%=issue_time%>" defaultsplit="-" basehref="<%=basehref %>" > <cst:a needhref="true" key="issue_time" value="" text="不限" ></cst:a> <cst:a needhref="true" key="issue_time" value="本月" text="本月" ></cst:a> <cst:a needhref="true" key="issue_time" value="本年" text="本年" ></cst:a> <cst:a needhref="true" key="issue_time" value="近三年" text="近三年" ></cst:a> <cst:a needhref="true" key="issue_time" value="近五年" text="近五年" ></cst:a> <cst:a needhref="true" key="issue_time" value="五年以上" text="五年以上" ></cst:a> <em class="confim"> <cst:select cls="yeah3" prompText ="请选择" defaultValNo="0" type="num" start="${start}" end="${end}" step="-1"> </cst:select> <cst:select cls="yeah4" prompText ="请选择" defaultValNo="1" type="num" start="${start}" end="${end}" step="-1" > </cst:select>年</em> <i id="confim">确认</i> </cst:searchline> </div> <div class="time"> <span>生成时间:</span> <cst:searchline defaultcls="onclick" defaulvalue="<%=time%>" defaultsplit="-" basehref="<%=basehref %>" > <cst:a needhref="true" key="time" value="" text="不限" ></cst:a> <cst:a needhref="true" key="time" value="本月" text="本月" ></cst:a> <cst:a needhref="true" key="time" value="本年" text="本年" ></cst:a> <cst:a needhref="true" key="time" value="近三年" text="近三年" ></cst:a> <cst:a needhref="true" key="time" value="近五年" text="近五年" ></cst:a> <cst:a needhref="true" key="time" value="五年以上" text="五年以上" ></cst:a> <em class="confim"> <cst:select cls="yeah1" prompText ="请选择" defaultValNo="0" type="num" start="${start}" end="${end}" step="-1"> </cst:select> <cst:select cls="yeah2" prompText ="请选择" defaultValNo="1" type="num" start="${start}" end="${end}" step="-1" > </cst:select>年</em> <i id="confim">确认</i> </cst:searchline> </div> </body> </html>
el表达式可参考:http://blog.csdn.net/zdwzzu2006/article/details/4672383
el存取变量数据,如${name},表示取出某一范围中名称为name的变量,如果未指定范围,它会从Page、request、session、application范围查找。
jsp2tag标签: http://www.ibm.com/developerworks/cn/java/j-lo-jsp2tag/