Невозможно вернуть значение на экран из метода в Scriptlet - PullRequest
0 голосов
/ 25 марта 2012

Мне нужно отобразить на экране некоторые значения, которые читаются в методе, определенном в скрипте-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 ()%> <% .. также не компилируется. Может кто-нибудь подсказать, пожалуйста, как решить эту проблему? </p>

Ответы [ 3 ]

2 голосов
/ 25 марта 2012

Контейнеры сервлетов компилируют код JSP в классы сервлетов следующим образом:

  • При использовании символов скриптлета "<%! ...%>" вы определяете код, который станет частью самого класса сервлета, который позволяет вам определять функции.
  • При использовании символов скриптлета "<% ...%>" вы определяете код, который будет частью метода "service" самого сервлета.

Итак, вы делаете, смешивая код, который объявляется вне метода "service" со ссылкой на переменную, которая будет скопирована внутри метода "service".

Чтобы решить вашу проблему, я бы добавил еще один параметр в вашу функцию и заменил бы эту «перекрестную ссылку» (или как там она должна называться). Это будет выглядеть так:

<%!
    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);
            }
        }
    } 
  %>

При вызове этой функции в вашем другом скриптлете вы должны вставить ссылку на PrintWriter (которая является неявной переменной для скриплетов, которые идут внутри метода "service"):

displayRecursively(out, ke, era);

Просто обратите внимание, что для компиляции вам потребуется импорт страницы класса "JspWriter" в JSP.

1 голос
/ 25 марта 2012

Как отмечалось в руководстве по стилю JSP почти десятилетие назад:

Где возможно, избегайте JSP-скриптлетов, когда библиотеки тегов предоставляют эквивалентную функциональность. Это облегчает чтение и обслуживание страниц, помогает отделить бизнес-логику от логики представления и упрощает превращение ваших страниц в страницы в стиле 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" />.

0 голосов
/ 25 марта 2012

<%! ..%> называется декларативным тегом. Вы можете использовать объявленные переменные и методы, определенные в декларативном теге службы (<% ..%>), но не параметр метода из декларативного тега.

...