java taglib 的使用

本文探讨了Java TLD(Tag Library Descriptor)的使用,包括required参数、rtexprvalue属性的影响,以及在不同Servlet版本中对EL表达式的支持。通过实例展示了TLD中的TEI-CLASS和validator的作用,并分享了解决特定问题的过程,强调了遇到问题时自我学习和解决问题的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以前一哥们跟我说  他项目经理写的自定义标签可以 c:foreach 进行循环  感觉好高端的感觉啊 ! 呵呵呵~~ 当时觉得自己写的标签好像从来没有这种功能啊。。。

但是因为没有代码 我也不知道是怎么回事,也没有去细想!  今天忽然看 项目里面的代码 看到了 tld 就复习了下,百度了些资料!  发现知识得多复习啊,不用就忘了,也许是我学的不够好吧,呵呵,很多细节都不知道了! 比如今天翻开自己以前写的笔记,记录的是 enum跟Enum的关系,  一看根本没印象了  呵呵呵!


tld的 文章 很多 : 其实都差不多 因为tld的知识点就那么点  呵呵  因为大家都写了  我就不重复了  下面这个地址里面  写的很详细 http://blog.youkuaiyun.com/liaoxiaohua1981/article/details/6856307

这个文章也非常不错  特别详细:http://ar.newsmth.net/thread-5d499b1fbe9e50.html(这里有很多我们不知道,平时不会用到的细节知识,相当于taglib的文档)


我发现啊,很多时候还是太懒了,比如说现在,我看taglib的 文档 有些地方不是太清楚 他们文章上写的也有点不大好理解,其实只要自己写个例子就ok了~!


经过测试 发现 

<required>false</required><!--是否是必填选项 -->

如果参数的 required 为 true的时候如果你不填这个参数的话  那么编译器会告诉你错误的!


如果rtexprvalue  为false的话

<attribute><!---这里表示的是这个tag的一个参数 -->
			<name>test</name><!--这个参数的名字 -->
			<required>true</required><!--是否是必填选项 -->
			<rtexprvalue>false</rtexprvalue><!--这个参数的值是否可以写入,换句话说 就是这个参数是否可以动态赋值 -->
		</attribute>

jsp中 这么写

<%
	String str = "123";
%>
<test:test test="<%=str %>"/>


会爆如下错误:

org.apache.jasper.JasperException: /testTagLib.jsp (line: 14, column: 0) According to TLD or attribute directive in tag file, attribute test does not accept any expressions
	at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:42)
	at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:408)
	at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:149)
	at org.apache.jasper.compiler.Validator$ValidateVisitor.checkXmlAttributes(Validator.java:1240)
	at org.apache.jasper.compiler.Validator$ValidateVisitor.visit(Validator.java:875)
	at org.apache.jasper.compiler.Node$CustomTag.accept(Node.java:1539)
	at org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2376)
	at org.apache.jasper.compiler.Node$Visitor.visitBody(Node.java:2428)
	at org.apache.jasper.compiler.Node$Visitor.visit(Node.java:2434)
	at org.apache.jasper.compiler.Node$Root.accept(Node.java:475)
	at org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2376)
	at org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1795)
	at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:217)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:353)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:340)
	at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:646)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:357)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

说明  rtexprvalue 设置为false  表示不接受 表达式赋值 表达式  当然如下方式也不行

<%
	String str = "123";
request.setAttribute("test", "112");
%>
<%-- <test:test test="<%=str %>"/> --%>
<test:test test="${test}"/>


接下来让我头疼的问题来了!  既然  如果  rtexprvalue  设置为  false 是不接受  EL表达式 或者 直接小脚本写java代码传值的  可是  我们现在的项目里面  把c.tld 给拿出来了,放在  /WEB-INF/tag/jstl/ 下面

而且配置的 也是指向这里的:  

<%@ taglib uri="/WEB-INF/tag/jstl/c.tld" prefix="c" %>

可是为什么我用  EL表达式 却是可以的呢~? 

<tag>
    <name>forEach</name>
    <tag-class>org.apache.taglibs.standard.tag.el.core.ForEachTag</tag-class>
    <tei-class>org.apache.taglibs.standard.tei.ForEachTEI</tei-class>
    <body-content>JSP</body-content>
    <description>
	The basic iteration tag, accepting many different
        collection types and supporting subsetting and other
        functionality
    </description>
    <attribute>
	<name>items</name>
	<required>false</required>
	<rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
	<name>begin</name>
	<required>false</required>
	<rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
	<name>end</name>
	<required>false</required>
	<rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
	<name>step</name>
	<required>false</required>
	<rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
	<name>var</name>
	<required>false</required>
	<rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
	<name>varStatus</name>
	<required>false</required>
	<rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>

可是

 <c:forEach items="${strs}" var="str2">
        <c:out value="${str2}"></c:out>
    </c:forEach>

这样写是没有任何问题的!! !   项目是在  idea里面跑的   我把 c.tld 拉到我 自己的一个 小项目 里面去  报错了, 因为一直用的  idea  基本没怎么用eclipse  所以我还以为是eclipse坑爹了呢~   但是  如果写成 :

 

<c:forEach items="<%=request.getAttribute("strs")%>" var="str2">
        <c:out value="${str2}"></c:out>
    </c:forEach>

这是要报错的!!!


碰到问题! 越想越想不通! 所以想找人问问!  我看到我们公司的架构师在,我就去问他  我说我碰到个问题!! 哎    他一副很不愿搭理的样子说 “碰到问题自己查啊,我哪记得那么多啊!“   我又是自尊心很强的人!  看到他这样子  二话不说 直接走了! 自己解决就自己解决 有啥好拽的,我只是觉得他经验丰富也许以前碰到过类似的问题!    其实还是我自己心理有问题了, 这有啥好不爽的呢,他帮我 我要谢谢他,不帮我 也无可厚非了!  而且也许是我自尊心太强了吧,他也许就是这样的性格!  算了 不管了! 回去之后 自己一头扎进去猛搞了一顿! 终于搞清楚了!


首先得感想网上的几篇好文章:

http://www.cnblogs.com/panjun-Donet/articles/1179262.html

http://www.iteye.com/topic/155354

http://www.iteye.com/topic/231840


web.xml  的  doctype的申明  申明的是  servlet 的版本 !

如下:

servlet 2.2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/dtd/web-app_2_2.dtd">

servlet 2.3

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

servlet 2.4

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


servlet 2.5

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">


在2.3及其以前的版本 是不支持 EL 表达式!

除非加了下面代码

<%@ page isELIgnored="false" %>

现在就可以解释那些怪异现象了:

我们项目里面配置的 是:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">

也就是2.3版本了!

系统把  EL 表达式当做一个  普通字符串了!   

当我加上

<%@ page isELIgnored="false" %>

果然报错了!! 哈哈哈!


现在的问题又来了

为什么作为   字符串 还能够正常的循环呢! ?

因为 我们用  jstl的 版本是1.2的 里面 有这么一句话:

Object r = ExpressionEvaluatorManager.evaluate("begin", this.begin_, Integer.class, this, this.pageContext);

这个话 干嘛的呢 就是 解释 EL表达式的!! !

这下终于真相大白了!!!



接下来讲讲   tld 中的  TEI-CLASS  是啥玩意

这个就是用来验证的    在编译期 或者说写代码的时候 就能够知道 传递的是不是有问题 这样就可以   将错误 扼杀在 摇篮里!!!

如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>
	<tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>test-tag</short-name>
    <uri>/WEB-INF/tag/test.tld</uri>
    <description>
		A simple tag library
	</description>
	
    <validator>
        <validator-class>com.ausky.taglib.TestValidator</validator-class>
    </validator>
    
	<tag>
		<name>test</name><!--tag的名字 -->
		<tag-class>com.ausky.taglib.TestTag</tag-class><!--tag对应的java类的名字 -->
		<tei-class>com.ausky.taglib.TestTEI</tei-class>
		<body-content>empty</body-content>

		<attribute><!---这里表示的是这个tag的一个参数 -->
			<name>test</name><!--这个参数的名字 -->
			<required>true</required><!--是否是必填选项 -->
			<rtexprvalue>true</rtexprvalue><!--这个参数的值是否可以写入,换句话说 就是这个参数是否可以动态赋值 -->
		</attribute>

	</tag>

</taglib>


package com.ausky.taglib;

import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * 
 * @author xn-hyao-01
 * 
 */
public class TestTag extends TagSupport {

	private static final long serialVersionUID = 7385843353583961842L;

	private String test;

	public String getTest() {
		return test;
	}

	
	
	public void setTest(String test) {
		System.out.println("test value is " + test);
        try{
//       Object o= ExpressionUtil.evalNotNull("test","test","${i}",Object.class,this,this.pageContext);
//            ExpressionEvaluatorManager.evaluate("test", "${i}", Object.class,this,this.pageContext);
        }catch (Exception ex){

        }
        this.test = test;
	}

	@Override
	public int doAfterBody() throws JspException {
		// TODO Auto-generated method stub
		
		return super.doAfterBody();
	}

	@Override
	public int doEndTag() throws JspException {
		// TODO Auto-generated method stub
		return super.doEndTag();
	}

	@Override
	public int doStartTag() throws JspException {
		// TODO Auto-generated method stub
		return super.doStartTag();
	}

	@Override
	public void release() {
		// TODO Auto-generated method stub
		super.release();
	}

}


package com.ausky.taglib;

import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.ValidationMessage;
import javax.servlet.jsp.tagext.VariableInfo;

public class TestTEI extends TagExtraInfo {

	@Override
	public boolean isValid(TagData data) {
		Object o = data.getAttribute("test");
		return o!=null;
	}

	@Override
	public VariableInfo[] getVariableInfo(TagData data) {
		// TODO Auto-generated method stub
		return super.getVariableInfo(data);
	}

	@Override
	public ValidationMessage[] validate(TagData data) {
		// TODO Auto-generated method stub
		return super.validate(data);
	}
	
}


这下 tei-class 也理解了!


接下来 讲讲

tld 中的 validator

这个是做啥的呢 :

上面有篇文章里面讲解了! 这个我也没怎么具体搞 呵呵呵~~ 就稍微看了下

下面是 原文里面的一段 原话  http://tech.ccidnet.com/art/3737/20030715/459917_1.html

JSP1.2 
 JSP1.2中引入一个新的标记检验方法,定义了一个新类TagLibraryValidator,并且可以由此派生出检验标志的类,大多数情况下仅使用这个类的validate()方法,它有三个参数:prefix(在taglib指令中定义的前缀);uri(TLD文件中的URI);page(JSP页的PageData XML版本),validate()方法返回值为null时表示验证成功,否则返回的String类型将是一个错误信息。
当validator在TLD文件中定义时,它应该放在<tag>元素定义的外面,因为它是用来处理验证标记库中的所有标记的。
<validator><validator-class></validator-class></validator>。


比较JSP1.2和JSP1.1中的方法:
TagLibraryValidator比TEI类更全面,可以用来检测整个网页,而不仅仅是标记本身,可以用来处理标记间的合作,并且这种方法可以用来通知程序员错误出在哪里,但是同时它的方法也比TEI类的方法复杂多了,因为它需要遍历整个XML版本的JSP(完成getAttributeValue方法)。

就是说 它就是  TEI-CLASS 的 升级版! 

我写了个 小测试:

package com.ausky.taglib;

import javax.servlet.jsp.tagext.PageData;
import javax.servlet.jsp.tagext.TagLibraryValidator;
import javax.servlet.jsp.tagext.ValidationMessage;

/**
 * Created with IntelliJ IDEA.
 * User: xn-hyao-01
 * Date: 14-2-21
 * Time: 上午11:22
 * To change this template use File | Settings | File Templates.
 */
public class TestValidator extends TagLibraryValidator {
    @Override
    public ValidationMessage[] validate(String prefix, String uri, PageData page) {
        return super.validate(prefix, uri, page);    //To change body of overridden methods use File | Settings | File Templates.
    }
}


我打个断点  看了下 page 里面到底是啥

<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root
  version="2.0"
  xmlns:c="urn:jsptld:/WEB-INF/tag/jstl/c.tld"
  xmlns:ww="urn:jsptld:/WEB-INF/tag/wildwolf/wildwolf.tld"
  xmlns:ww-el="http://www.sinitek.com/wildwolf/el"
  xmlns:accounttool="urn:jsptld:/WEB-INF/tag/account/accounttool.tld"
  xmlns:fund-tools="urn:jsptld:/WEB-INF/tag/trade/fundinfo_el.tld"
  xmlns:fmt="urn:jsptld:/WEB-INF/tag/jstl/fmt.tld"
  xmlns:BankInfo="urn:jsptld:/WEB-INF/tag/bank/bankinfo.tld"
  xmlns:query-tools="urn:jsptld:/WEB-INF/tag/trade/query.tld"
  xmlns:capital="urn:jsptld:/WEB-INF/tag/mycapital/capitalcommon.tld"
  xmlns:bulletin="urn:jsptld:/WEB-INF/tag/bulletin/bulletin.tld"
  xmlns:test="urn:jsptld:/WEB-INF/tag/test.tld"
  xmlns:jsp="http://java.sun.com/JSP/Page"
  jsp:id="0"
>
<jsp:directive.page
  jsp:id="1"
  pageEncoding="UTF-8"
  contentType="text/html;charset=UTF-8"
/>
<jsp:directive.page
  jsp:id="2"
  import="java.util.ArrayList"
/>
<jsp:text
  jsp:id="3"
>
<![CDATA[

]]>
</jsp:text>
<jsp:directive.page
  jsp:id="4"
  import="java.util.List"
/>
<jsp:text
  jsp:id="5"
>
<![CDATA[

]]>
</jsp:text>
<jsp:directive.page
  jsp:id="6"
  language="java"
/>
<jsp:text
  jsp:id="7"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="8"
>
<![CDATA[

]]>
</jsp:text>
<jsp:directive.page
  jsp:id="9"
  language="java"
/>
<jsp:text
  jsp:id="10"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="11"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="12"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="13"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="14"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="15"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="16"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="17"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="18"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="19"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="20"
>
<![CDATA[

]]>
</jsp:text>
<jsp:scriptlet
  jsp:id="21"
>
<![CDATA[

    String trade_title = "电信合作项目";
]]>
</jsp:scriptlet>
<jsp:text
  jsp:id="22"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="23"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="24"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="25"
>
<![CDATA[
<html>
]]>
</jsp:text>
<jsp:text
  jsp:id="26"
>
<![CDATA[
<head>
    ]]>
</jsp:text>
<jsp:text
  jsp:id="27"
>
<![CDATA[
<title>]]>
</jsp:text>
<jsp:expression
  jsp:id="28"
>
<![CDATA[
trade_title]]>
</jsp:expression>
<jsp:text
  jsp:id="29"
>
<![CDATA[

    ]]>
</jsp:text>
<jsp:text
  jsp:id="30"
>
<![CDATA[
</title>
    ]]>
</jsp:text>
<jsp:directive.page
  jsp:id="31"
  language="java"
/>
<jsp:text
  jsp:id="32"
>
<![CDATA[

]]>
</jsp:text>
<jsp:directive.page
  jsp:id="33"
  import="com.sinitek.sfm.trade.chinatele.bean.ICTLoginBean"
/>
<jsp:scriptlet
  jsp:id="34"
>
<![CDATA[

    ICTLoginBean loginBean = (ICTLoginBean) session.getAttribute(ICTLoginBean.sessionID);
    if (loginBean == null)
    {
]]>
</jsp:scriptlet>
<jsp:text
  jsp:id="35"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="36"
>
<![CDATA[
<script>
    alert("用户已登出,或超时,请重新登录");
    location.href = "login.jsp";
]]>
</jsp:text>
<jsp:text
  jsp:id="37"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:scriptlet
  jsp:id="38"
>
<![CDATA[

    }
]]>
</jsp:scriptlet>
<jsp:text
  jsp:id="39"
>
<![CDATA[

    ]]>
</jsp:text>
<jsp:text
  jsp:id="40"
>
<![CDATA[
<script type="text/javascript" src="../framework/js/jquery.js" charset="utf-8">]]>
</jsp:text>
<jsp:text
  jsp:id="41"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="42"
>
<![CDATA[
<script type='text/javascript' src='../dwr/engine.js'>]]>
</jsp:text>
<jsp:text
  jsp:id="43"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="44"
>
<![CDATA[
<script type="text/javascript" src="../framework/js/placeholder.js">]]>
</jsp:text>
<jsp:text
  jsp:id="45"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="46"
>
<![CDATA[
<script type="text/javascript" src="../framework/js/jquery.bgiframe.js">]]>
</jsp:text>
<jsp:text
  jsp:id="47"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="48"
>
<![CDATA[
<script type="text/javascript" src="../framework/js/loading.js">]]>
</jsp:text>
<jsp:text
  jsp:id="49"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="50"
>
<![CDATA[
<script type="text/javascript" src="../framework/js/jquery.cookie.js">]]>
</jsp:text>
<jsp:text
  jsp:id="51"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="52"
>
<![CDATA[
<script type="text/javascript" src="../framework/js/common.js">]]>
</jsp:text>
<jsp:text
  jsp:id="53"
>
<![CDATA[
</script>
]]>
</jsp:text>
<jsp:text
  jsp:id="54"
>
<![CDATA[
<script type="text/javascript" src="../dwr/interface/ChinaTeleDwr.js">]]>
</jsp:text>
<jsp:text
  jsp:id="55"
>
<![CDATA[
</script>]]>
</jsp:text>
<jsp:text
  jsp:id="56"
>
<![CDATA[

    ]]>
</jsp:text>
<jsp:text
  jsp:id="57"
>
<![CDATA[
<script type="text/javascript" src="../dwr/interface/UserLoginDwr.js">]]>
</jsp:text>
<jsp:text
  jsp:id="58"
>
<![CDATA[
</script>
    ]]>
</jsp:text>
<jsp:text
  jsp:id="59"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="60"
>
<![CDATA[
</head>
]]>
</jsp:text>
<jsp:text
  jsp:id="61"
>
<![CDATA[
<body>
]]>
</jsp:text>
<jsp:scriptlet
  jsp:id="62"
>
<![CDATA[


    List<String> strs = new ArrayList<String>();
    strs.add("1");
    strs.add("2");
    strs.add("3");
    strs.add("4");
    String test = "11";
    int i = 1;
    request.setAttribute("strs", strs);
    request.setAttribute("i", i);
    request.setAttribute("strs2", "111");

]]>
</jsp:scriptlet>
<jsp:text
  jsp:id="63"
>
<![CDATA[

临时首页
]]>
</jsp:text>
<jsp:text
  jsp:id="64"
>
<![CDATA[
<button onclick="$('#logoutForm').submit()">退出]]>
</jsp:text>
<jsp:text
  jsp:id="65"
>
<![CDATA[
</button>
]]>
</jsp:text>
<jsp:text
  jsp:id="66"
>
<![CDATA[
<form id="logoutForm" action="UserLoginAction.do?method=logout" method="post">
    11111121
    111
    ]]>
</jsp:text>
<jsp:text
  jsp:id="67"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="68"
>
<![CDATA[
</form>
]]>
</jsp:text>
<test:test
  test="${i}"
  jsp:id="69"
/>
<jsp:text
  jsp:id="70"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="71"
>
<![CDATA[

]]>
</jsp:text>
<jsp:text
  jsp:id="72"
>
<![CDATA[
</body>
]]>
</jsp:text>
<jsp:text
  jsp:id="73"
>
<![CDATA[
</html>]]>
</jsp:text>
</jsp:root>

果然是要遍历怎么jsp啊!! !!


对了 最后说一点  validator 或者 TEI-CLASS 都是只执行一次!!!


差点忘记时候 开始时的问题了~~:

类似于下面的功能:

<test:list id="books" name="yuwen"/>

<c:foreach items="${books}" var="book"></c:foreach>  


其实这个 也不需要 variable  属性了  直接pageContext.getReqest().setAttribute();


那什么时候 需要呢 ~~ 

<jsp:getProperty property="name" name="test2"/>


这个就需要使用 variable 属性了 不然它都不知道  test2 在什么时候定义的!!

<tag>
		<name>test</name><!--tag的名字 -->
		<tag-class>com.ausky.taglib.TestTag</tag-class><!--tag对应的java类的名字 -->
		<tei-class>com.ausky.taglib.TestTEI</tei-class>
		<body-content>empty</body-content>

       <!--  <variable>
            <name-from-attribute>params</name-from-attribute>
            <variable-class>com.ausky.taglib.TestBean</variable-class>
            <scope>AT_BEGIN</scope>
        </variable> -->

		<attribute><!---这里表示的是这个tag的一个参数 -->
			<name>test</name><!--这个参数的名字 -->
			<required>true</required><!--是否是必填选项 -->
			<rtexprvalue>true</rtexprvalue><!--这个参数的值是否可以写入,换句话说 就是这个参数是否可以动态赋值 -->
		</attribute>
        <attribute><!---这里表示的是这个tag的一个参数 -->
            <name>params</name><!--这个参数的名字 -->
            <required>true</required><!--是否是必填选项 -->
            <rtexprvalue>false</rtexprvalue><!--这个参数的值是否可以写入,换句话说 就是这个参数是否可以动态赋值 -->
        </attribute>
	</tag>

<test:test test="122" params="test2"/>
	
	<jsp:getProperty property="name" name="test2"/>

TestBean test = new TestBean();
        test.setAddress("111");
        test.setName("1112");
        pageContext.getRequest().setAttribute(params,test);

呵呵  后面说的有点语无伦次了!! 反正后面的也不大需要!! 就是说  variable 属性说明了的话 这样jsp编译的时候 就可以知道了!!!  而 我们 c:foreach 的时候  是不需要预编译知道的所以有没有 variable 都一样!!


OK  结束!


 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值