Вызов метода с параметром внутри цикла JSTL - PullRequest
7 голосов
/ 20 июля 2011

У меня есть JSP, который должен напечатать некоторый текст, который получается путем взятия итератора цикла и передачи его другому объекту (Spring bean), что-то вроде:

<c:forEach var="myVar" items="${myVars}">
   <c:out value="anotherObject.getFoo(myVar)"/>
</c:forEach>

Очевидно, что приведенный выше код недопустим, так как оператор JSTL . допускает только вызовы без параметров. Я вижу следующие решения проблемы:

1) Скриптлеты

<c:forEach var="myVar" items="${myVars}">
  <%
    SomeType myVar = (SomeType) pageContext.getAttribute("myVar");
    SomeOtherType anotherObject = (SomeOtherType) pageContext.getAttribute("anotherObject");
    YetAnotherType result = anotherObject.getFoo(myVar);
    pageContext.setAttribute("result", result);
  %>
  <c:out value="${result}"/>
</c:forEach>

Очевидным минусом здесь является загрязнение кода JSP и общее уродство.

2) Написание тега, который делает все, что делается внутри скриптлетов. Типичный пример сверхинжиниринга, чёрт!

3) Разобрать коллекцию myVars и заменить каждый myVar динамическим прокси , InvocationHandler которого добавит дополнительный метод без параметров, чтобы все getFoo() вызовы через anotherObject. Все это будет сделано в контроллере, поэтому JSP останется чистым, а myVar останется прежним. Но по какой цене?

Я не могу добавить .getFoo() метод к myVar, потому что он там не помещается и нарушил бы разделение задач.

Похоже, что передача параметров будет возможна в JSP / EL 2.2, но я использую Tomcat 6.0.29, который включает только API EL 2.1.

Вопрос: Кто-нибудь может предложить самый чистый подход для этой ситуации?

Ответы [ 6 ]

7 голосов
/ 15 августа 2013

Простое только для Java "исправление ошибок", которое работает и в более старой версии JSTL. и не требует дополнительных taglibs / config / dependencies / frameworks и т. д. это "обернуть" функцию, которую вы хотите вызвать из JSTL в классе, который расширяет класс Map и переопределяет его метод get().

В качестве минимального примера, если вы, например, хотите вызвать функцию Math.sin() из JSTL, вы бы определили класс:

public class Sine extends HashMap<Double, Double> {
    private static final long serialVersionUID = 1L; // Avoids compiler-warning

    @Override
    public Double get(Object arg) {
        Double x = (Double) arg;
        return Math.sin(x);
    }
}

Затем в вашем методе Action execute () вы делаете:

...
request.setAttribute("sine", new Sine());
...

Тогда в JSP вы можете сказать:

  ${sine[0.75]}

для вычисления значения Math.sin(0.75)

JSTL будет обрабатывать переменную sine как Map, но вы можете вычислять и возвращать все что угодно из метода get ().

Полагаю, это немного сложнее, если у вас есть более одного аргумента для вашей функции, но для этого тоже должны быть обходные пути:)

2 голосов
/ 21 июля 2011

Вот как я это сделал в конце.

Вместо того, чтобы передавать коллекцию SomeType экземпляров, я передаю карту. Ключи карты одинаковы SomeType s, а значения являются экземплярами внутреннего класса для контроллера, назовем его SomeTypeSupplement.

SomeTypeSupplement добавляет необходимые гетерогенные геттеры и соединяет все вместе. JSP теперь перебирает записи на карте и может извлекать данные через JSTL.

Таким образом, я избегаю Proxy магии, ненужных TLD, сохраняю JSP чистыми и разумно безопасными для типов.

1 голос
/ 10 декабря 2013

Хотел добавить комментарий к последнему (по времени) ответу Ропа, но мне не хватает "репутации", поэтому вот я с ответом.

У меня вскоре была такая же идея с такой картой,но пытался сделать его более удобным для использования, имея интерфейс DynamicMap, DynamicMapCalculator и позволяя вам обернуть любой вызов метода в такую ​​карту (без необходимости каждый раз создавать новую реализацию карты, просто используя создание экземпляров анонимного класса).

Это будет тема, если вы заинтересованы: Кв.стиля: динамическая карта JSTL помогает обойти пропущенные вызовы функций параметров

И мне было бы интересно узнать там мнения: это то, что вы можете делать без совести?

1 голос
/ 28 июля 2011

Почему бы просто не составить список объектов в коде бэкэнда Java, а затем просто использовать JSP для его отображения?

1 голос
/ 20 июля 2011

Если вы не можете придерживаться скриптлетов (ваш вариант 1), я бы создал для него собственный тег (ваш вариант 2) или пользовательскую функцию EL.Я не согласен с тем, что это «чрезмерное проектирование», оно использует доступные инструменты по прямому назначению.

Ваш вариант 3, хотя мне не нравится.Во всяком случае, это чрезмерная инженерия плюс сделает вашу систему излишне сложной и трудной для других людей.Придерживайтесь намерений спецификаций и стандартов, в которых вы работаете.Ради этого не усложняй и не усложняй.

0 голосов
/ 15 февраля 2012

Другой вариант - использовать Скорость .Это намного приятнее, чем JSTL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...