环境:weblogic8.1, J2EE1.3(Servlet2.3/JSP1.2)
    目的:编写一个分页Tag
    过程:编写Tag Handler类Pagination.java(代码见下面)及对应的TagExtralInfo类PaginationTEI.java,Tag描述文件pagination.tld,然后在JSP页面中导入使用.
    问题:no corresponding open tag for tag extension close: </july:page>
    代码:
        Tag Handler类Pagination.java(由于帖子长度有限制,我只能截掉部分了):
         public class Pagination extends BodyTagSupport {
private int currentPage ,interval, size, count;
        private List items;
        private String type , item; public int doAfterBody() throws JspException {
int currentIndex = this.currentPage * this.interval + this.count;
if(this.count >= this.interval || currentIndex >= this.size)
return Pagination.SKIP_BODY;
if (bodyContent != null) {
            writePrevious(this.pageContext, bodyContent.getString());
            bodyContent.clearBody();
        }
this.pageContext.setAttribute("item", this.items.get(currentIndex));
this.count ++;
return Pagination.EVAL_BODY_BUFFERED;
} public int doEndTag() throws JspException {
StringBuffer url = ((HttpServletRequest)this.pageContext.getRequest()).getRequestURL();
String quesMark = "";
if(url.indexOf("?") != -1)
quesMark = "?"; StringBuffer output = new StringBuffer();
try {
output.append("<style type=\"text/css\">" +
"ra {text-align:right}" +
     "</style>");
output.append("<div class=\"ra\">");
if(this.currentPage == 0){
output.append("首页&nbsp;&nbsp;上一页&nbsp;&nbsp;");
}
else{
output.append("<a href=\"url" + quesMark + "&currentPage=0\">首页</a>&nbsp;&nbsp;" +
"<a href=\"url" + quesMark + "&currentPage=" + (this.currentPage - 1) + "\">上一页</a>&nbsp;&nbsp;");
}
if( ( (this.currentPage + 1) * this.interval ) >= this.size )
output.append("下一页&nbsp;&nbsp;末页&nbsp;&nbsp;");
else
output.append("<a href=\"url" + quesMark + "&currentPage=" + (this.currentPage + 1) + "\">下一页</a>&nbsp;&nbsp;" +
"<a href=\"url" + quesMark + "&currentPage=" + (((this.size % this.currentPage) == 0 ) ? (this.size / this.currentPage - 1) : (this.size / this.currentPage)) + "\">末页</a>&nbsp;&nbsp;");
output.append("共有" + this.size + "条记录,现在是第" + this.currentPage + 1 + "页,每页" + this.interval + "行</div>"); 
this.writePrevious(this.pageContext, output.toString());
} catch (JspException e) {

e.printStackTrace();
}
return Pagination.EVAL_PAGE;
} public int doStartTag() throws JspException {
this.count = 0;
this.size = this.items.size();
String currentPageStr = this.pageContext.getRequest().getParameter("currentPage");
if(currentPageStr == null || currentPageStr.equals(""))
this.currentPage = 0;
else{
try{
this.currentPage = Integer.parseInt(currentPageStr);
}catch(NumberFormatException e){
System.out.println("Can't format the string \"" + currentPageStr + "\"!");
this.currentPage = 0;
}
}
return Pagination.EVAL_BODY_BUFFERED;
}

public void writePrevious(PageContext pageContext, String text) throws JspException {
JspWriter writer = pageContext.getOut();
if (writer instanceof BodyContent) {
writer = ((BodyContent) writer).getEnclosingWriter();
}
try {
writer.print(text);
} catch (IOException e) {
e.printStackTrace();
}
}
...Setters/Getters
}
     paginationtei.java
     public class PaginationTEI extends TagExtraInfo { public VariableInfo[] getVariableInfo(TagData data) {
String type = data.getAttributeString("type");
if(type == null)
type = "java.lang.String";
return new VariableInfo[]{
new VariableInfo(data.getAttributeString("item"), type, true, VariableInfo.NESTED)
};
}

}     pagination.tld
     <?xml version="1.0" ?>
<!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>july</short-name>
<tag>
<name>page</name>
<tag-class>nju.software.tags.Pagination</tag-class>
<tei-class>nju.software.tags.PaginationTEI</tei-class>
<body-content>JSP</body-content>
<attribute>
<name>interval</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.util.List</type>
</attribute>
<attribute>
<name>item</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>type</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>

</tag>
</taglib>    web.xml
   <?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">  
<web-app>
<taglib>
<taglib-uri>/july</taglib-uri>
<taglib-location>/WEB-INF/pagination.tld</taglib-location>
</taglib>
</web-app>
      JSP页面:
      [code=HTML]
<%@page contentType="text/html; charset=GBK" import="java.util.List"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="july" uri="/july" %>.....省略部分代码,太长了.....
              <july:page items="<%=session.getAttribute("cps") %>" interval="2" item="cp" type="nju.software.entity.ConflictPractice" >
       <c:set var="id" value="${cp.id}"></c:set>
       <tr>
       <td align="center"><c:out value="${id}" ></c:out></td>
       <td align="center"><c:out value="${cp.time}"></c:out></td>
       <td align="center"><c:out value="${cp.conductor}"></c:out></td>
       <td align="center"><c:out value="${cp.participant}"></c:out></td>
       <td align="center"><c:out value="${cp.emergency}"></c:out></td>
       <td align="center"><c:out value="${cp.assist_Department}"></c:out></td>
       <td align=center>
       <c:if test="${rp.insert == 1}">
       <a href="ConflictPractice_Edit.jsp?id=<%=id %>&uid=<%=pageContext.getAttribute("id") %>">编辑</a>
       </c:if>
       <c:if test="${rp.del == 1}">
       <a href="ConflictPractice_Console.jsp?id=<%=id %>&fg=3&uid=<%=pageContext.getAttribute("id") %>" onclick="return Del();">删除</a>
       </c:if>
       </td>
       </tr>
       </july:page>
    声明几点:①关于目录结构以及类似的文件位置问题不存在,这个我是确定的
              ②这是针对JSP1.2的Tag编程,而且是Classic Tag.
            ③对于如何处理BodyContent我不是很了解它的机制,因为这里有个和body交互的问题.不知道我上面的代码有没有写对?
         
     

解决方案 »

  1.   

    不好意思, 裁剪时把JSP页面那段代码没弄好,重发下:JSP页面: 
          [code=HTML] 
    <%@page contentType="text/html; charset=GBK" import="java.util.List"%> 
    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> 
    <%@ taglib prefix="july" uri="/july" %> .....省略部分代码,太长了..... 
    <july:page items=" <%=session.getAttribute("cps") %>" interval="2" item="cp" type="nju.software.entity.ConflictPractice" > 
       <c:set var="id" value="${cp.id}"> </c:set> 
       <tr> 
          <td align="center"> <c:out value="${id}" > </c:out> </td> 
          <td align="center"> <c:out value="${cp.time}"> </c:out> </td> 
          <td align="center"> <c:out value="${cp.conductor}"> </c:out> </td> 
          <td align="center"> <c:out value="${cp.participant}"> </c:out> </td> 
          <td align="center"> <c:out value="${cp.emergency}"> </c:out> </td> 
          <td align="center"> <c:out value="${cp.assist_Department}"> </c:out> </td> 
          <td align=center> 
             <c:if test="${rp.insert == 1}"> <a href="ConflictPractice_Edit.jsp?id= <%=id %>&uid= <%=pageContext.getAttribute("id") %>">编辑 </a> 
             </c:if> 
             <c:if test="${rp.del == 1}"> 
                <a href="ConflictPractice_Console.jsp?id= <%=id %>&fg=3&uid= <%=pageContext.getAttribute("id") %>" onclick="return Del();">删除 </a> 
             </c:if> 
          </td> 
       </tr> 
    </july:page> 
      

  2.   

    O(∩_∩)O~,看来我这问题发的时间是不对的,大伙都休息去了
    其实也不是什么难的问题啦, 我再缩小下范围
    晚上那会我用排除法检查出来是属性items的赋值问题
    可我明明设置了rtexprvalue为true的,为什么没法接受动态赋值?
    <july:page items=" <%=session.getAttribute("cps") %>" interval="2" item="cp" type="nju.software.entity.ConflictPractice" > <attribute>
                <name>items</name>
                <required>true</required>
                <rtexprvalue>true</rtexprvalue>
                <type>java.util.List</type>
            </attribute>
      

  3.   

    恩, 差不多, 更准确地说法是, 没有开始标签, O(∩_∩)O~
    我现在怀疑会不会由于给items赋值为null时产生了问题? 不过现在身边没环境, 明天去机房试验下
      

  4.   

    差不多试验出来了
    的确是items的问题, 之前是用session.getAttribute("cps")没有返回我存储的东西. 不过既然session找不到cps从而返回null导致上面的错误, 为什么我直接在items中赋值为null却得到另一个错误---NullPointerException. 真是奇怪了.
    唉,这JSTL1.0真麻烦
    要是大伙没有问题了, 那我就结贴了
      

  5.   

    又进了一步了,O(∩_∩)O~
    现在session.getAttribute("cps")有数据了
    ①使用items="<%=session.getAttribute("cps")%>", no corresponding open tag错误
    ②使用items="<%=(List)session.getAttribute("cps")%>", 还是no corresponding open tag错误
    ③前面写一段script, <% List list = (List)session.getAttribute("cps")%>,然后使items="<%=list%>", 没有错误,页面正常显示,数据也有
    ④前面写一段script, <% Object list = session.getAttribute("cps")%>,然后使items="<%=list%>", CompilerException, 意思是与setItems(List)不匹配
    ⑤前面写一段script, <% Object list = (List)session.getAttribute("cps")%>,然后使items="<%=list%>", CompilerException, 意思是与setItems(List)不匹配刚看了下struts1.3.10的iterate标签的Tag Handler和tld, 发现在tld文件中,collection(相当于我这里的items)的type子元素值为java.lang.Object, Tag Handler中的setter的signature也是setCollection(Object ). 有点失望的味道...我知道,struts这么做是考虑了collection有多种类别,可以是List, Array, Map, Set等等. 就是不知道是否也存在不能直接用这些类别的可能. 可话又说回来, 上述第三种情况却是可以通过的, 真是搞不懂了....
      

  6.   

    刚用了struts的方法, 把List也换成Object了, 可是问题依旧.========================================================
    10分钟后....
    ========================================================当我正写着博客准备记录这个问题时, 不知道哪里得到的灵感让我觉得多重引号可能会导致这个问题.事实上,的确如此. 我也不想多说什么了, 若是想了解可以去我的文章看看JSP Tag属性动态赋值问题(终结)