Как избежать дублирования с помощью EL?

Я переписываю свой .jsp со скриптов на JSTL/EL и столкнулся с проблемой. Это, наверное, очень просто, но я новичок в EL и немного потерялся.

Вот что я делаю...

В сервлете/контроллере:

final List<Person> l = new ArrayList<Person>();
personList.add(...);
.
.
request.setAttribute( "personList", l );

И в моем .jsp:

<c:forEach var="person" items="${personList}">
    ${person.name}
</c:forEach>

Но я дублирую "personList", потому что использую его как в setAttribute, так и в forEach. Как избавиться от этого дублирования?

В идеале я хотел бы иметь константу, такую ​​как public static final String, на которую я мог бы ссылаться как из сервлета, так и из .jsp (используя EL, а не скриптлеты) .

Очевидно, причина, по которой я хочу устранить это дублирование, заключается в том, что если я решу переименовать personList, скажем, в persons (с буквой s), мне в настоящее время нужно изменить два вещи, и это подвержено ошибкам. Если бы у меня была константа, было бы только одно место, где мне нужно было бы внести это изменение.

EDIT кто-то заметил, что при использовании константы все равно нужно было бы изменить два места, если бы я изменил имя константы. Однако есть большая разница, если бы я мог это сделать:

request.setAttribute(Constants.PERSON_LIST, l );

затем решили переименовать *PERSON_LIST* и сделали опечатку, которая сломается во время компиляции.

Хотя, если я ошибаюсь:

request.setAttribute( "persnList", l ); // forgetting an 'o' here

Это неубедительно скомпилируется и завершится ошибкой во время выполнения, если .jsp использует "personList", а не "persnList" с ошибкой.


person Cedric Martin    schedule 10.03.2012    source источник


Ответы (3)


Это то, что вы получаете при работе с устаревшими/базовыми JSP/сервлетами. Вы вручную выполняете все задачи переднего контроллера самостоятельно.

Перейдите к настоящей структуре MVC. Например, JSF, Spring MVC, Wicket и т. д. Эти фреймворки имеют один сервлет (или фильтр), который действует как передний контроллер, выполняя всю неприятную работу по предварительной обработке по созданию bean-компонентов, помещая их в желаемую область действия и так далее. Вы заканчиваете работать только с javabeans в качестве моделей и файлами JSP/Facelets в качестве представлений. Например, в JSF все, что вам нужно, это следующий javabean (который будет "автоматически" установлен в области запроса самим JSF ):

@ManagedBean
@RequestScoped
public class Persons {

    private List<Person> list;

    @EJB
    private PersonService service;

    @PostConstruct
    public void init() {
        list = service.list();
    }

    public List<Person> getList() {
        return list;
    }

}

И этот вид Facelet:

<ui:repeat value="#{persons.list}" var="person">
    #{person.name}
</ui:repeat>

Никакого дублирования, и при использовании достойных инструментов IDE (например, Eclipse с инструментами JBoss) все они связаны друг с другом, так что вы можете без проблем выполнить Source > Refactor > Rename.

person BalusC    schedule 10.03.2012

Это точно не дублирование? Это просто объявление переменной и доступ к переменной в одной области видимости. Это прекрасно. Если вы пишете программу и объявляете переменную в одной строке, то позже в программе вы получаете доступ к переменной, и у вас возникает та же проблема... если вы измените имя переменной, как объявлено, тогда все виды использования должны быть найдены и изменены.

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

person Vincent Ramdhanie    schedule 10.03.2012
comment
Я не согласен с вашим ответом. Это определенно дублирование, и я объясню, почему в конце моего вопроса. Мне нужно что-то изменить в двух местах, в то время как с помощью скриптлетов совершенно тривиально не иметь этого дублирования. Это не то же самое, что переменная. - person Cedric Martin; 10.03.2012
comment
Если вы пишете программу и объявляете переменную в одной строке, то позже...... Немного неудобно сравнивать переменную в одной строке метода с имеющейся строкой, с одной стороны , в сервлете и, с другой стороны, в .jsp не так ли!? Опять же, при использовании скриптлетов не возникает такого дублирования. - person Cedric Martin; 10.03.2012
comment
Если вы объявите константу, чем она отличается? Вам все еще нужно исправить его использование, если вы решите переименовать константу, верно? - person Kevin; 10.03.2012
comment
@Kevin: если бы я мог объявить константу, то опечатка в имени константы либо в сервлете, либо в .jsp привела бы к поломке во время компиляции, а не во время выполнения. Здесь, если я изменю personList на persnList в своем сервлете (опечатка, забыв «о»), веб-приложение будет скомпилировано нормально, но сломается во время выполнения. Довольно большое изменение, не так ли? Кстати, EL 3.0 упростил обращение к константам, насколько я знаю (но я еще не на Jave EE 7). Я ничего не вижу здесь. - person Cedric Martin; 10.03.2012
comment
С JSP и сервлетами вы просто работаете с несколькими областями действия больше, чем с простой настольной программой. Но это одно и то же. setAttribute() просто создает переменную в области запроса, на которую вы ссылаетесь позже в той же области. Вот почему у нас есть автоматизированное тестирование. Там, где компилятор и IDE дают сбой, ваши тесты обнаружат проблему, и ваш неработающий код не будет запущен в производство. - person Vincent Ramdhanie; 10.03.2012
comment
@VincentRamdhanie: Вот почему у нас автоматизированное тестирование. Там, где компилятор и IDE терпят неудачу, ваши тесты выявят проблему, и ваш сломанный код не пойдет в производство... О, пожалуйста, общее, вы полностью уклоняетесь от вопроса и переносите обсуждение сюда. То, что я хочу сделать, это ТРИВИАЛЬНО сделать с помощью скриптлетов и доступа к константам из EL МОЖЕТ БЫТЬ СДЕЛАНО в EL 3.0 / Java EE 7. Поэтому, пожалуйста, прекратите это. Либо вы знаете, как предотвратить дублирование здесь, либо вы останавливаетесь, чтобы попытаться сместить дискуссию и сделать вид, что здесь нет дублирования. - person Cedric Martin; 10.03.2012

Возможно, я ошибаюсь, но я думаю, что стандартная проблема с jsps заключается в том, что вы не видите ошибок, пока страница не загрузится. Даже если константы каким-то образом исправляют это, то, что вы описываете, является не дублированием, а недостатком переменных EL в целом (т.е. они динамически просматриваются во время выполнения)

person Kevin    schedule 10.03.2012
comment
но любая достойная IDE предупредит вас, если вы попытаетесь сослаться, скажем, из скриптлета, на несуществующую константу... И, начиная с EL 3.0, вы можете ссылаться на константы :( (к сожалению, я еще не на Java EE 7) - person Cedric Martin; 10.03.2012