Файл тега JSP, который либо выводит его тело, либо возвращает его в переменной

#jsp #jsp-tags

#jsp #jsp-теги

Вопрос:

У меня есть пользовательский тег в файле «.tag», который вычисляет и выводит значение. Поскольку я не могу опубликовать код здесь, давайте рассмотрим простой пример.

Содержимое файла mytag.tag:

 <@tag dynamic-attributes="dynamicParameters">
<%@attribute name="key" required="true"%> <%-- this works fine, in spite of dynamic-attributes --%>
<jsp:doBody var="bodyContent/">
<%-- ... here is some code to compute the value of variable "output" --%>
${output}
  

Вызывающий может легко вызвать его следующим образом:

 <prefix:mytag key="foo">Body content...</prefix:mytag>
  

Это приведет к вставке выходных данных тега. Но я бы также разрешил вызывающей стороне делать что-то вроде этого:

 <prefix:mytag key="foo" var="mytagOutput">Body content...</prefix:mytag>
  

В этом случае вывод фактически не был бы записан, а был бы присвоен переменной «mytagOutput», которую затем может использовать вызывающий.

Я знаю, что вызывающий может достичь этого, обернув пользовательский тег в c:set , но это менее элегантно, чем простое объявление «var». Я также знаю, что для достижения этой цели можно использовать @variable директиву с name-from-attribute . Но тогда я не знаю, был ли атрибут «var» задан вызывающим объектом или нет. (Если задано, я хочу присвоить ${output} этой переменной, в противном случае я хочу просто записать ${output} .)

Есть ли способ, как я могу узнать, был ли передан атрибут «var» или нет?

Другим вариантом было бы создать второй пользовательский тег, возможно, называемый «getMytag», который всегда ожидает атрибут «var» и просто оборачивает «mytag» в c:set . Если я не найду решение здесь, я воспользуюсь этим.

(Если этот вопрос задавался ранее, пожалуйста, укажите мне на него. Я выполнил быстрый поиск, но не нашел похожего вопроса.)

Ответ №1:

Немного поздно, но лучше поздно, чем никогда. Возможно, кому-то еще это покажется полезным

 <%@ attribute name="var" required="true" type="java.lang.String" rtexprvalue="false"%>
<%@ attribute name="date" required="true" type="java.sql.Timestamp" description="The date to format"%>
<%@ variable alias="formattedDate" name-from-attribute="var" scope="AT_BEGIN" variable-class="java.lang.String"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<c:set var="formattedDate">
    <fmt:formatDate value="${ date }" pattern="hh:mma " var="time" />
    ${fn:toLowerCase(time)}<fmt:formatDate value="${ date }" pattern="MMMMM d, y" />
</c:set>
  

Установите ваш атрибут var (он должен быть обязательным и не допускать rtexprvalue), затем установите псевдоним вашей переменной, который соответствует тому, как вы ссылаетесь на переменную в вашем пользовательском теге.

Вызовите свой пользовательский тег, предоставляющий переменную var

 <custom:dateFormat date="${ content.date }" var="formattedDate" />
<c:out value="${formattedDate}" />
  

Комментарии:

1. это хорошо, и это работает, но ‘var’ является обязательным атрибутом. таким образом, этот тег не сможет ни распечатать свои выходные данные, ни присвоить им значение переменной. он только установит его в переменную.

Ответ №2:

Столкнулся с этой же проблемой и нашел способ решить это без «жестко закодированного» имени переменной, которое должно совпадать между .jsp и .tag.

 <%@ taglib prefix="c"   uri="http://java.sun.com/jsp/jstl/core"%><%@ 
taglib prefix="s"       uri="http://www.springframework.org/tags" %>

<jsp:directive.attribute name="someInput" type="java.lang.Object" required="true" rtexprvalue="true" description="Input object" />
<jsp:directive.attribute name="var" type="java.lang.String" required="false" rtexprvalue="false" description="Optional return var name" />

<s:eval expression="@someService.someMethod(someInput)" var="someOutput" />

<c:choose>
    <c:when test="${not empty var}">
        ${pageContext.request.setAttribute(var, someOutput)}
    </c:when>
    <c:otherwise>
        ${someOutput}
    </c:otherwise>
</c:choose>
  

Этот тег можно использовать двумя способами:

 <%-- Option 1: renders the output of the tag directly to the page --%>
<some:tagname someInput="${yourVar}" />

<%-- Option 2: stores the output of the tag in variable called "result" and lets the caller render the output on his own --%>
<some:tagname someInput="${yourVar}" var="result" />
<c:out value="${result}"/>
  

Комментарии:

1. Неявный объект PageContext не определен при работе внутри тега. если только taglib Spring каким-то образом не определяет это? но я пробовал это решение без Spring, и оно не сработало.

Ответ №3:

Основываясь на другом ответе, псевдоним переменной кажется отличным обходным путем. Вот простой пример:

 <%@ attribute name="urlValue" required="true" type="java.lang.String" %>
<%@ attribute name="var" required="true" type="java.lang.String" rtexprvalue="false" %>
<%@ variable alias="varAlias" name-from-attribute="var" scope="AT_BEGIN" variable-class="java.lang.String"%>


<spring:url value="${urlValue}" var="varAlias"/>