0

我需要在屏幕上显示一些在 script-let 中定义的方法中读取的值。下面的代码无法编译:

<%!
    void displayRecursively(KnowledgeElement ke, ExtendsRelationshipService ers){
        List<ExtendsRelationship> erList = null;
        %><%=ke.getName()%><br /><%!
        try {
            erList = ers.findIncomingExtendsKERelationships(ke);
        } catch (Exception e) {}
        if (erList!=null){
            for (ExtendsRelationship er : erList){
                KnowledgeElement startKe = er.getStartKE();
                displayRecursively(startKe,ers);
            }
        }
    } 
%>  

<%
    KnowledgeElement ke = null;
    ke = (KnowledgeElement)request.getAttribute("knowledgeElement");
    ExtendsRelationshipService ers = (ExtendsRelationshipService)request.getAttribute("ers");
    displayRecursively(ke,ers);             
%>

编译错误是:

PWC6199: Generated servlet error:
cannot find symbol
  symbol:   variable ke
  location: class org.apache.jsp.WEB_002dINF.ke_jsp

使用 .. %><%=ke.getName()%><% .. 也不会编译。有人可以建议如何解决这个问题吗?

4

3 回答 3

2

Servlet 容器按照以下方法将 JSP 代码编译成 servlet 类:

  • 当使用“<%! ... %>”脚本符号时,您定义的代码将成为 servlet 类本身的一部分,它允许您定义函数。
  • 当使用“<% ... %>”脚本符号时,您定义的代码将成为 servlet 本身的“服务”方法的一部分。

因此,您正在做的是将在“服务”方法之外声明的代码与将要在“服务”方法内部复制的变量的引用混合在一起。

为了解决您的问题,我将在您的函数中添加另一个参数并替换该“交叉引用”(或应调用的任何内容)。它看起来像这样:

<%!
    void displayRecursively(JspWriter out, KnowledgeElement ke, ExtendsRelationshipService ers){
        List<ExtendsRelationship> erList = null;
        out.print(ke.getName());
        out.println("<br />");
        try {
            erList = ers.findIncomingExtendsKERelationships(ke);
        } catch (Exception e) {}
        if (erList!=null){
            for (ExtendsRelationship er : erList){
                KnowledgeElement startKe = er.getStartKE();
                displayRecursively(out, startKe,ers);
            }
        }
    } 
  %>

在您的其他 scriptlet 中调用该函数时,您必须传递对 PrintWriter 的引用(这是进入“服务”方法内部的 scriptlet 的隐式变量):

displayRecursively(out, ke, era);

请注意,您需要在 JSP 中导入“JspWriter”类的页面才能进行编译。

于 2012-03-25T03:00:45.167 回答
1

正如近十年前的 JSP 风格指南所指出的:

只要标签库提供等效功能,就尽可能避免使用 JSP scriptlet。这使页面更易于阅读和维护,有助于将业务逻辑与表示逻辑分开,并使您的页面更容易演变为 JSP 2.0 样式的页面......

使用模板进行递归很棘手,但可以做到。

这是一个表示层对象,它使您的对象适应 EL 可以使用的东西,可以处理异常等:

public class RelationshipPresentation {
  private final ExtendsRelationshipService service;
  private final ExtendsRelationship relationship;

  public RelationshipPresentation(ExtendsRelationshipService service, 
                                  ExtendsRelationship relationship) {
    this.service = service;
    this.relationship = relationship;
  }

  public String getName() { return relationship.getName(); }

  public List<RelationshipPresentation> getRelated() {
    List<RelationshipPresentation> list =
                                   new ArrayList<RelationshipPresentation>();
    try {
      for (ExtendsRelationship er :
           service.findIncomingExtendsKERelationships(relationship)) {
        list.add(new RelationshipPresentation(service, er));
      }
    } catch (Exception e) { /*Catching Exception?!*/ }
      return list;
  }
}

将这种类型与您的标记隔离开来进行单元测试也很容易。

这在分派到 JSP 之前被置于范围内:

RelationshipPresentation relationshipPresentation =
                         new RelationshipPresentation(ers, knowledgeElement);
request.setAttribute("relationshipPresentation", relationshipPresentation);
getServletContext().getRequestDispatcher("/ercontainer.jsp")
                   .forward(request, response);

这是一个 JSP 片段 ( er.jsp),它在无序列表中显示名称:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:out value="${relationshipPresentation.name}" />
<ul>
    <c:forEach var="relationshipPresentation"
               items="${relationshipPresentation.related}">
        <c:set var="relationshipPresentation"
               value="${relationshipPresentation}" scope="request"/>
        <li><jsp:include page="er.jsp"/></li>
    </c:forEach>
</ul>

这可以通过 JSP 操作包含在您的主页中<jsp:include page="er.jsp" />

于 2012-03-25T12:07:32.007 回答
0

<%!..%> 被称为声明性标签。您可以使用 service(<%..%>) 中声明性标记下声明的变量和定义的方法,但不能使用声明性标记中的方法的参数。

于 2012-03-25T03:46:43.800 回答