«1. Введение

Язык выражений (EL) — это язык сценариев, который используется во многих средах Java, таких как Spring с SpEL и JBoss с JBoss EL.

В этой статье мы сосредоточимся на реализации JSF этого языка сценариев — Unified EL.

В настоящее время EL находится в версии 3.0, крупном обновлении, позволяющем использовать механизм обработки в автономном режиме, например, на платформе Java SE. Предыдущие версии зависели от сервера приложений или веб-контейнера, совместимого с Jakarta EE. В этой статье обсуждается EL версии 2.2.

2. Немедленная и отложенная оценка

Основная функция EL в JSF — соединить представление JSF (обычно XHTML-разметку) и серверную часть на основе Java. Серверная часть может представлять собой управляемые компоненты, созданные пользователем, или объекты, управляемые контейнером, такие как сеанс HTTP.

Мы рассмотрим EL 2.2. EL в JSF существует в двух основных формах: непосредственный синтаксис EL и отложенный синтаксис EL.

2.1. Immediate Syntax EL

Известный также как JSP EL, это формат сценариев, пережиток времен JSP разработки веб-приложений на Java.

Выражения JSP EL начинаются со знака доллара ($), затем следует левая фигурная скобка ({), затем следует фактическое выражение и, наконец, закрывается правой фигурной скобкой (}):

${ELBean.value > 0}

~ ~~ Этот синтаксис:

  1. Is evaluated only once (at the beginning) in the lifecycle of a page. What this means is that the value that is. Being read by the expression in the example above must be set before the page is loaded.
  2. Provides read-only access to bean values.
  3. And as a result, requires adherence to the JavaBean naming convention.

В большинстве случаев эта форма EL не очень универсальна.

2.2. Deferred Execution EL

Deferred Execution EL — это EL, разработанный для собственно JSF. Его основное синтаксическое отличие от JSP EL заключается в том, что он помечен знаком «#» вместо «$».

#{ELBean.value > 0}

Deferred EL:

  1. Is in sync with the JSF lifecycle. This means that an EL expression in deferred EL is evaluated at different points in the rendering of a JSF page (at the beginning and the end).
  2. Provides read and write access to bean values. This allows one to set a value in a JSF backing-bean (or anywhere else) using EL.
  3. Allows a programmer to invoke arbitrary methods on an object and depending on the version of EL, pass arguments to such methods.

Unified EL — это спецификация, объединяющая как deferred EL, так и JSP EL, позволяя использовать оба синтаксиса на одной странице.

3. Унифицированный EL

Унифицированный EL допускает два основных вида выражений: выражения значений и выражения методов.

И небольшое примечание: в следующих разделах будут показаны некоторые примеры, которые доступны в приложении (см. ссылку на Github в конце), перейдя по адресу:

http://localhost:8080/jsf/el_intro.jsf

3.1. Выражения значений

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

Следующее выражение считывает свойство управляемого компонента на страницу:

Hello, #{ELBean.firstName}

Однако следующее выражение позволяет нам установить значение для пользовательского объекта:

<h:inputText id="firstName" value="#{ELBean.firstName}" required="true"/>

Переменная должна соответствовать соглашению об именах JavaBean. иметь право на такое лечение. Чтобы значение bean-компонента было зафиксировано, нужно просто сохранить закрывающую форму.

3.2. Выражения методов

Unified EL предоставляет выражения методов для выполнения общедоступных нестатических методов на странице JSF. Методы могут иметь или не иметь возвращаемых значений.

Вот краткий пример:

<h:commandButton value="Save" action="#{ELBean.save}"/>

Метод save(), о котором идет речь, определен в компоненте поддержки с именем ELBean.

Начиная с EL 2.2, вы также можете передавать аргументы методу, доступ к которому осуществляется с помощью EL. Это может позволить нам переписать наш пример следующим образом:

<h:inputText id="firstName" binding="#{firstName}" required="true"/>
<h:commandButton value="Save"
  action="#{ELBean.saveFirstName(firstName.value.toString().concat('(passed)'))}"/>

Здесь мы создали выражение привязки на уровне страницы для компонента inputText и напрямую передали атрибут value в выражение метода.

Обратите внимание, что переменная передается в метод без каких-либо специальных обозначений, фигурных скобок или escape-символов.

3.3. Неявные объекты EL

Механизм JSF EL обеспечивает доступ к нескольким объектам, управляемым контейнером. Некоторые из них:

    «#{Application}: также доступен как #{servletContext}, это объект, представляющий экземпляр веб-приложения #{applicationScope}: карта переменных, доступных для всего веб-приложения #{Cookie}: карта переменных HTTP Cookie # {facesContext}: текущий экземпляр FacesContext #{flash}: объект области JSF Flash #{header}: карта заголовков HTTP в текущем запросе #{initParam}: карта переменных инициализации контекста в Интернете приложение #{param}: карта параметров запроса HTTP-запроса #{request}: объект HTTPServletRequest #{requestScope}: карта переменных в области запроса #{sessionScope}: карта переменных в области сеанса #{session} : объект HTTPSession #{viewScope}: карта переменных области представления (страницы)

В следующем простом примере перечислены все заголовки и значения запроса путем доступа к неявному объекту заголовков:

<c:forEach items="#{header}" var="header">
   <tr>
       <td>#{header.key}</td>
       <td>#{header.value}</td>
   </tr>
</c:forEach>

4. Что вы делаете Может делать в EL

Благодаря своей универсальности, EL может использоваться в коде Java, разметке XHTML, Javascript и даже в Файлы конфигурации JSF, такие как файлfaces-config.xml. Давайте рассмотрим некоторые конкретные варианты использования.

4.1. Использование EL в разметке страницы

EL можно использовать в стандартных тегах HTML:

<meta name="description" content="#{ELBean.pageDescription}"/>

4.2. Использование EL в JavaScript

EL будет интерпретироваться, если встречается в тегах Javascript или \u003cscript\u003e:

<script type="text/javascript"> var theVar = #{ELBean.firstName};</script>

Переменная компонента поддержки будет установлена ​​здесь как переменная javascript.

4.3. Оценка булевой логики в EL с использованием операторов

EL поддерживает довольно продвинутые операторы сравнения:

    оператор равенства eq, эквивалентный оператору «==.» lt less than оператор, эквивалентный «\u003c.» le less больше или равно оператору, эквивалентному «\u003c=». gt большему оператору, эквивалентному «\u003e». ge большему или равному, эквивалентному «\u003e=».

4.4. Вычисление EL в компоненте поддержки

Из кода компонента поддержки можно оценить выражение EL с помощью приложения JSF. Это открывает целый мир возможностей при подключении страницы JSF к компоненту поддержки. Вы можете легко получить неявные объекты EL или фактические компоненты HTML-страницы или их значение из вспомогательного компонента:

FacesContext ctx = FacesContext.getCurrentInstance(); 
Application app = ctx.getApplication(); 
String firstName = app.evaluateExpressionGet(ctx, "#{firstName.value}", String.class); 
HtmlInputText firstNameTextBox = app.evaluateExpressionGet(ctx, "#{firstName}", HtmlInputText.class);

Это дает разработчику большую гибкость при взаимодействии со страницей JSF.

5. Чего нельзя делать в EL

EL \u003c 3.0 имеет некоторые ограничения. В следующих разделах обсуждаются некоторые из них.

5.1. Без перегрузки

EL не поддерживает использование перегрузки. Таким образом, в резервном компоненте со следующими методами:

public void save(User theUser);
public void save(String username);
public void save(Integer uid);

JSF EL не сможет правильно оценить следующее выражение

<h:commandButton value="Save" action="#{ELBean.save(firstName.value)}"/>

JSF ELResolver проанализирует определение класса компонента и выберет первый метод возвращаемый java.lang.Class#getMethods (метод, который возвращает методы, доступные в классе). Порядок возвращаемых методов не гарантируется, и это неизбежно приведет к неопределенному поведению.

5.2. Нет перечислений или постоянных значений

JSF EL \u003c 3.0, не поддерживает использование постоянных значений или перечислений в скрипте. Таким образом, наличие любого из следующих

public static final String USER_ERROR_MESS = "No, you can’t do that";
enum Days { Sat, Sun, Mon, Tue, Wed, Thu, Fri };

означает, что вы не сможете сделать следующее

<h:outputText id="message" value="#{ELBean.USER_ERROR_MESS}"/>
<h:commandButton id="saveButton" value="save" rendered="bean.offDay==Days.Sun"/>

5.3. Нет встроенной нулевой безопасности

JSF EL \u003c v3.0 не обеспечивает неявный нулевой безопасный доступ, что некоторым может показаться странным в современном механизме сценариев.

Итак, если человек в приведенном ниже выражении равен нулю, все выражение терпит неудачу с неприглядным NPE

Hello Mr, #{ELBean.person.surname}"

6. Заключение

Мы рассмотрели некоторые основы JSF EL, сильные стороны и ограничения.

Это в значительной степени универсальный язык сценариев, который можно улучшить; это также клей, который связывает представление JSF с моделью и контроллером JSF.

Исходный код, сопровождающий эту статью, доступен на GitHub.