您的位置:首页 > Web前端 > JavaScript

Jstl自定义标签及其生命周期、属性标签、及其读取文本练习、JspFragment输出标签体(2)

2016-09-02 00:50 531 查看
什么是自定义标签?

标签处理器可以做哪些操作呢?

属性标签

输出一个文件-利用自定义标签

利用JspFragment输出标签体的自定义标签

什么是自定义标签?





SimlpeTagSuPPort类的生命周期:

1.当jsp容器遇到自定义标签时。jsp容器会调用标签处理类的默认构造方法来建立一个标签处理类的实例。必须为每个标签都创建一个新的实例。

2.实例创建后,jsp容器会调用setJspContext()方法。并以一个JspContext实例提供上下文信息。如果是一个嵌套标签,还讲调用setParent()方法。

3.然后容器会调用该标签中所定义的每个属性的set方法,这样标签处理类实例就已经初始化完成了。

4.接着就由容器调用setJspBody()方法。将该标签的主题设置为JspFragment实例。如果标签主题是空的,则将null值传到setJspBody().JspFragment实例代表标签主题片段的引用。

5.接下来,由容器调用doTag()方法标签要实现的所有逻辑、循环、主体赋值等都在该方法中发生。

6.在doTag()方法返回后,标签处理类中所有的变量都是同步的。

如何创建自定义标签?

1、写一个标签处理类,实现SimpleTag接口方法

2、建议在WEB-INF下配置文件tld文件

3、在jsp中taglib导入标签库描述文件,使用即可

HelloSimpleTag

package com.safly;
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class HelloSimpleTag implements SimpleTag {
public void doTag() throws JspException, IOException {
System.out.println("doTag");
}
public JspTag getParent() {
System.out.println("getParent");
return null;
}
public void setJspBody(JspFragment jspBody) {
System.out.println("setJspBody");
}
public void setJspContext(JspContext pc) {
System.out.println("setJspContext");
}
public void setParent(JspTag parent) {
System.out.println("setParent");
}
}


mytld.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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

<description>MyTag 1.0 core library</description>
<display-name>MyTag core</display-name>
<tlib-version>1.0</tlib-version>

<short-name>safly</short-name>
<uri>http://www.safly.com/mytld/core</uri>

<tag>
<name>hello</name>
<tag-class>com.safly.HelloSimpleTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>


mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="http://www.safly.com/mytld/core" prefix="safly"%>
<html>
<body>
<!-- //prefix可用其他,但是<safly:hello/>相对应 -->
<safly:hello/>
</body>
</html>




标签处理器可以做哪些操作呢?

通过jsp引擎调用,把代表jsp页面的pageContext对象传入,由于pageContext可以获取jsp页面其他的8个隐含对象,所以凡是jsp页面可以做的,标签处理器都可以做

还是上例中mytld.tld、mytag.jsp不过变化

HelloSimpleTag 做如下修改

package com.safly;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;

public class HelloSimpleTag implements SimpleTag {

// 标签体逻辑实际编写到该方法中
public void doTag() throws JspException, IOException {
System.out.println("doTag");
pageContext.getOut().println("helloworld");
HttpServletRequest request = (HttpServletRequest) pageContext
.getRequest();
pageContext.getOut().print("Hello" + request.getParameter("name"));
}
public JspTag getParent() {
System.out.println("getParent");
return null;
}
public void setJspBody(JspFragment jspBody) {
System.out.println("setJspBody");
}
private PageContext pageContext;
// jsp引擎调用,把代表jsp页面的pagecontext对象传入
public void setJspContext(JspContext pc) {
System.out.println("setJspContext");
System.out.println(pc instanceof PageContext);
this.pageContext = (PageContext) pc;
}
public void setParent(JspTag parent) {
System.out.println("setParent");
}

}




属性标签

1.先在标签处理类中定义setter方法,建议属性都设置为String类型

2.在tld文件中来描述属性

mytld.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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

<description>MyTag 1.0 core library</description>
<display-name>MyTag core</display-name>
<tlib-version>1.0</tlib-version>

<short-name>safly</short-name>
<uri>http://www.safly.com/mytag/core</uri>

<tag>
<name>hello</name>
<tag-class>com.safly.HelloSimpleTag</tag-class>
<body-content>empty</body-content>

<attribute>
<name>value</name>
<required>true</required>
<!-- 当前属性是否可以接受运行时表达式的动态值 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>count</name>
<required>true</required>
<!-- 当前属性不可以接受运行时表达式的动态值 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>


mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="http://www.safly.com/mytag/core" prefix="safly"%>
<html>
<body>
<safly:hello value="${param.name}" count="5"/>
</body>
</html>


HelloSimpleTag

package com.safly;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class HelloSimpleTag implements SimpleTag {
//建议把所有的属性定义成String类型
private String value;
private String count;
public void setValue(String value) {
this.value = value;
}
public void setCount(String count) {
this.count = count;
}
// 标签体逻辑实际编写到该方法中
public void doTag() throws JspException, IOException {
System.out.println("doTag");
JspWriter out = pageContext.getOut();
int c = 0;
c = Integer.parseInt(count);
for (int i = 0; i < c; i++) {
out.print(i + ":" + value);
out.print("<br>");
}
}
public JspTag getParent() {
System.out.println("getParent");
return null;
}
public void setJspBody(JspFragment jspBody) {
System.out.println("setJspBody");
}
private PageContext pageContext;
// jsp引擎调用,把代表jsp页面的pagecontext对象传入
public void setJspContext(JspContext pc) {
System.out.println("setJspContext");
System.out.println(pc instanceof PageContext);
this.pageContext = (PageContext) pc;
}
public void setParent(JspTag parent) {
System.out.println("setParent");
}
}




输出一个文件-利用自定义标签

mytld.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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

<description>MyTag 1.0 core library</description>
<display-name>MyTag core</display-name>
<tlib-version>1.0</tlib-version>

<short-name>safly</short-name>
<uri>http://www.safly.com/mytag/core</uri>

<tag>
<name>readerFile</name>
<tag-class>com.safly.ReadFileTag</tag-class>
<body-content>empty</body-content>

<attribute>
<name>src</name>
<required>true</required>
<!-- 当前属性是否可以接受运行时表达式的动态值 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>


mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="http://www.safly.com/mytag/core" prefix="safly"%>
<html>
<body>
<safly:readerFile src="/WEB-INF/abc.txt"/>

</body>
</html>


ReadFileTag

package com.safly;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class ReadFileTag extends SimpleTagSupport {
private String src;
public void setSrc(String src){
this.src = src;
}
@Override
public void doTag() throws JspException, IOException {
super.doTag();
PageContext pageContext = (PageContext) getJspContext();
InputStream in = pageContext.getServletContext().getResourceAsStream(src);
BufferedReader reader = new BufferedReader(new InputStreamReader(in) );
String str = null;
while ((str=reader.readLine())!=null) {
pageContext.getOut().write(str);
pageContext.getOut().write("<br>");
}
}
}


看下目录结构:



浏览器输出结果如下:



利用JspFragment输出标签体的自定义标签

public void setJspBody(JspFragment jspBody) {
System.out.println("setJspBody");
}


它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段

WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示:

getJspContext方法用于返回代表调用页面的JspContext对象.

public abstract voidinvoke(java.io.Writer out)

用于执行JspFragment对象所代表的JSP代码片段,参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)

mytld.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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

<description>MyTag 1.0 core library</description>
<display-name>MyTag core</display-name>
<tlib-version>1.0</tlib-version>

<short-name>safly</short-name>
<uri>http://www.safly.com/mytag/core</uri>

<tag>
<name>testJspFragment</name>
<tag-class>com.safly.ReadFileTag</tag-class>
<body-content>scriptless</body-content>
</tag>
</taglib>


mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="http://www.safly.com/mytag/core" prefix="safly"%>
<html>
<body>
<safly:testJspFragment>HelloWorld</safly:testJspFragment>
</body>
</html>


ReadFileTag

package com.safly;
import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class ReadFileTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
//自己定义的方法getJspBody
JspFragment bodyContent= getJspBody();
//参数为字符流,若为null则输出getJspContext().getOut()到页面上
StringWriter sw = new StringWriter();
bodyContent.invoke(sw);
String content = sw.toString().toUpperCase();
getJspContext().getOut().print(content);
}
}




带标签体的自定义标签练习

mytld.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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

<description>MyTag 1.0 core library</description>
<display-name>MyTag core</display-name>
<tlib-version>1.0</tlib-version>

<short-name>safly</short-name>
<uri>http://www.safly.com/mytag/core</uri>

<tag>
<name>printUpper</name>
<tag-class>com.safly.PrintUpperTag</tag-class>
<body-content>scriptless</body-content>

<attribute>
<name>time</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>

<tag>
<name>forEach</name>
<tag-class>com.safly.PrintUpperTag</tag-class>
<body-content>scriptless</body-content>

<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>

<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>


Customer

package com.safly;

public class Customer {

private Integer id;
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Customer(Integer id, String name) {
super();
this.id = id;
this.name = name;
}

public Customer() {
// TODO Auto-generated constructor stub
}

}


PrintUpperTag

package com.safly;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collection;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class PrintUpperTag extends SimpleTagSupport {
private String time;

public void setTime(String time) {
this.time = time;
}

private Collection<?>items;
private String var;
public void setItems(Collection<?> items) {
this.items = items;
}
public void setVar(String var) {
this.var = var;
}

/////////////////////////////////////////
@Override
public void doTag() throws JspException, IOException {
JspFragment bodyContent = getJspBody();
StringWriter sw = new StringWriter();
bodyContent.invoke(sw);

String content = sw.toString();
content = content.toUpperCase();

int count = 1;
try {
count = Integer.parseInt(time);
} catch (Exception e) {
}
for (int i = 0; i < count; i++) {
getJspContext().getOut().print(content+"<br>");

}

if (items!=null) {
for (Object obj: items) {
getJspContext().setAttribute(var, obj);
getJspBody().invoke(null);
}
}
}
}


mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@page import="com.safly.Customer"%>
<%@taglib uri="http://www.safly.com/mytag/core" prefix="safly"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<safly:printUpper time="5"> hello</safly:printUpper>

<%
List<Customer> customers = new ArrayList<Customer>();
customers.add(new Customer(1,"AAA"));
customers.add(new Customer(2,"BBB"));
customers.add(new Customer(3,"CCC"));
request.setAttribute("customers",customers);

Map<String,Customer> customerMap = new HashMap<String,Customer>();
customerMap.put("a",customers.get(0));
customerMap.put("b",customers.get(1));
customerMap.put("c",customers.get(2));
request.setAttribute("customerMap",customerMap);
%>

<c:forEach items="${customerMap }" var ="cust">
${pageScope.cust.key }--${cust.value.id }---${cust.value.name }
</c:forEach>

<safly:forEach items="${customers }" var ="cust">
${pageScope.cust.id }--${cust.name }
</safly:forEach>
</body>
</html>


浏览器输入http://localhost:8080/day01/mytag.jsp

输出结果如下:

&NBSP;HELLO
&NBSP;HELLO
&NBSP;HELLO
&NBSP;HELLO
&NBSP;HELLO
b--2---BBB c--3---CCC a--1---AAA --
1--AAA 2--BBB 3--CCC


主要来说下

<safly:forEach items="${customers }" var ="cust">
${pageScope.cust.id }--${cust.name }
</safly:forEach>


如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)

在PrintUpperTag进行了如下操作:

if (items!=null) {
for (Object obj: items) {
getJspContext().setAttribute(var, obj);
getJspBody().invoke(null);
}
}


然后在jsp页面中进行获取即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: