一,对JSP自定义标签的简单概述
开发者自己定义的标签库,用于在JSP页面中扩展HTML标记和Java标记。 JSP自定义标签的功能类似HTML自定义标签或组件,可以起到复用和模块化代码的作用,使代码更加清晰、易于维护。引入自定义标签之后,开发人员可以将一个繁琐的功能简化为一个标签,并且可以多次重复使用它们。
二,自定义foreach标签
在实体类foeach标签中定义的两个属性:
- items 定义List集合(数据源)
- var 定义字符串
2.1继承助手类
定义Foeach类并继承BodyTagSupport标签助手类,提供get set方法。重写doStartTag();方法及doAfterBody();方法
代码如下:
package com.LiuBing.text; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; public class ForeachTag extends BodyTagSupport { //数据源 private List<Object> items = new ArrayList<Object>(); //指针 获取单个对象 private String var; public void setItems(List<Object> items) { this.items = items; } public void setVar(String var) { this.var = var; } @Override public int doAfterBody() throws JspException { // TODO Auto-generated method stub return super.doAfterBody(); } @Override public int doStartTag() throws JspException { // TODO Auto-generated method stub return super.doStartTag(); } }
2.2 判断items数据源
package com.LiuBing.text; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; public class ForeachTag extends BodyTagSupport { //数据源 private List<Object> items = new ArrayList<Object>(); //指针 获取单个对象 private String var; public void setItems(List<Object> items) { this.items = items; } public void setVar(String var) { this.var = var; } @Override public int doAfterBody() throws JspException { Iterator<Object> it = (Iterator<Object>) pageContext.getAttribute("it"); if(it.hasNext()) { //pageContext获取上下文信息 根据var获取遍历迭代器it的下一条 pageContext.setAttribute(var, it.next()); return EVAL_BODY_AGAIN; } return SKIP_BODY; } @Override public int doStartTag() throws JspException { //进行一个集合判断 if(items==null || items.size() ==0) return SKIP_BODY;//跳过主体 //迭代器遍历list Iterator<Object> it = items.iterator(); //pageContext获取上下文信息 根据var获取遍历迭代器it的下一条 pageContext.setAttribute(var, it.next()); pageContext.setAttribute("it", it); return EVAL_BODY_INCLUDE; } }
重写方法中的返回值这跟JSP自定义标签生命周期有关!
SKIP_BODY | 跳过主体 |
EVAL_BODY_INCLUDE | 计算主体内容并输出 |
EVAL_BODY_AGAIN | 再次计算主体一次 |
EVAL_PAGE | 计算后续内容 |
SKIP_PAGE | 跳过页面后续内容 |
2.3 定义.tld标签库
在foreach一个标签两个属性,所有在tld标签库中只需要定义那两个属性即可items和var
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <description>JSTL 1.1 core library</description> <display-name>JSTL core</display-name> <tlib-version>1.1</tlib-version> <short-name>c</short-name> <uri>http://foreach</uri> <tag> <name>foreach</name> <tag-class>com.LiuBing.text.ForeachTag</tag-class> <body-content>JSP</body-content> <attribute> <name>items</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>var</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> </taglib>
2.4 JSP页面引入标签库实现遍历数据
通过tagilb引入标签库 uri地址即是在自定义标签库中自定义的地址,再通过实列实体类School创建几条模拟数据,再最后通过foreach遍历通过el表达式存储数据,用指针var获取数据
<%@page import="java.util.ArrayList"%> <%@page import="com.LiuBing.text.School"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <!--引入标签库自定义 --> <%@ taglib prefix="z" uri="http://foreach"%> </head> <body> <% List<School> list = new ArrayList<>(); list.add(new School(1,"教学部")); list.add(new School(2,"保安部")); list.add(new School(3,"美术部")); list.add(new School(4,"摸鱼部")); request.setAttribute("list", list); %> <z:foreach items="${list }" var="l"> ${l } </z:foreach> </body> </html>
运行结果:
三,数据标签获取数据
3.1概述:
数据标签获取通常是指通过各种手段获取已经被标注的数据集。标注是指将数据中的某些信息以标签的形式进行明确地注释,在JSP页面中直接获取已标注的数据
3.2步骤:
定义School类继承助手类并定义var属性方便存储值,提供set get方法。重写doStartTag方法,在方法中创建List集合 匿名School模拟几条数据,将数据存储到setAttribute中,再去tld中自定义School标签库(如下面代码), 最后就是定义JSP页面引入刚所写的tld自定义标签库
tld代码:
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <description>JSTL 1.1 core library</description> <display-name>JSTL core</display-name> <tlib-version>1.1</tlib-version> <short-name>c</short-name> <uri>http://School</uri> <tag> <name>School</name> <tag-class>com.LiuBing.text.SchoolTag</tag-class> <body-content>JSP</body-content> <attribute> <name>var</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> </taglib>
最后就是定义JSP页面引入刚所写的tld自定义标签库
jsp代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <%@ taglib prefix="z" uri="http://School" %> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <z:School var="lis"></z:School> 摸鱼部门:${lis } </body> </html>
运行结果:
四,select标签
将之前所写的代码优化起来,像之前的select标签下需要option标签又要value值才能显示下拉框的值,优化select只需要一行代码即可完成,而且并不需要进行一个if判断能进行默认选择
代码展示:
同foreach标签步骤
注意:在字符串拼接与StringBuffer区别:
String字符串的拼接会更加消耗服务器的内存 StringBuffer并不会消耗太多且效率较高
package com.LiuBing.text; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; public class SelectTag extends BodyTagSupport { // 下拉框数据源 private List<Object> items = new ArrayList<Object>(); // 下拉框option中的value值 private String optionval;//前端id // 下拉框option的标签体的内容 private String optiontext; public List<Object> getItems() { return items; } public void setItems(List<Object> items) { this.items = items; } public String getOptionval() { return optionval; } public void setOptionval(String optionval) { this.optionval = optionval; } public String getOptiontext() { return optiontext; } public void setOptiontext(String optiontext) { this.optiontext = optiontext; } @Override public int doStartTag() throws JspException { //获取pageContext上下文信息 返回out对象根据out回显数据 JspWriter out = pageContext.getOut(); try { out.print(toHTML()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.doStartTag(); } private String toHTML() throws Exception { //StringBuffer可以进行原地拼接字符串,而不是每次都拼接新的字符串对象。 StringBuffer sb= new StringBuffer(); //开始标签 sb.append("<select>"); for (Object object : items) { String val=getOjectattrValue(object,"optionVal"); String text=getOjectattrValue(object,"optiontext"); sb.append("<option value='"+val+"'>"+text+"</option>"); } //结束标签 sb.append("</select>"); return sb.toString(); } /** * 获取某个对象的属性值 * @param object 实体对象 * @param string 传的id/name * @return * @throws SecurityException * @throws NoSuchFieldException */ private String getOjectattrValue(Object object, String attr) throws Exception, SecurityException { //获取类类 Class clz = object.getClass(); Field f = clz.getDeclaredField(attr); f.setAccessible(true); return f.get(object).toString(); } }