Описание тега el
Вступление
EL (язык выражений) обеспечивает динамическое разрешение объектов и методов Java на страницах JSP и Facelets. Выражения EL имеют форму${foo}
а также #{bar}
. Доллар (${}
) и хеш (#{}
) определяют выражения немедленной оценки и выражения отложенной оценки соответственно. Спецификация позволяет другим доменам применять свое собственное значение. В основном${}
может только "получить", в то время как #{}
может делать "получить" и "установить". Особенно "набор" является обязательным при использовании JSF фреймворка MVC. Таким образом, JSF может связать входные компоненты в представлении непосредственно с классом JavaBean в модели без необходимости в вашем собственном сервлете. ВFacesServlet
затем сделает всю работу.
До JSP 2.0 (выпущенного в ноябре 2003 г.) EL был частью JSTL. Начиная с JSP 2.0, стандартный EL был перемещен из JSTL в JSP и поддерживается как часть спецификации JSP. JSTL 1.1 был первой версией, поставляемой без EL и использующей JSP EL. JSF также поддерживает собственную версию EL с отложенной оценкой.#{}
. Начиная с JSP 2.1, отложенный EL был унифицирован со стандартным EL и поддерживается как отдельная спецификация, даже если они принадлежат одному и тому же JSR ( JSR 245). JSF 1.2 был первой версией, поставляемой без EL и использующей унифицированный EL. В EL 3.0 представлен даже новый автономный API процессора EL, так что его можно использовать автономно в простых проектах Java SE.
Текущая спецификация EL - JSR 341: Expression Language 3.0. В отличие от предыдущих версий EL, эта спецификация была размещена в собственном JSR.
См. Также разницу между JSP EL, JSF EL и Unified EL.
JavaBeans
Когда дело касается доступа к свойствам, EL полагается на спецификацию JavaBeans. В JSP следующее выражение
${user.name}
выполняет в основном то же самое, что и следующий код в "необработанном" коде скриптлета (приведенный ниже пример для простоты, в действительности API отражения используется для получения методов и их вызова):
<%
User user = (User) pageContext.findAttribute("user");
if (user != null) {
String name = user.getName();
if (name != null) {
out.print(name);
}
}
%>
где PageContext#findAttribute()
сканирует атрибуты соответственно PageContext
(объем страницы), HttpServletRequest
(объем запроса), HttpSession
(объем сеанса) и ServletContext
(область применения), пока не будет найдено первое ненулевое значение. Обратите внимание, что таким образом он не печатает"null"
когда значение null
ни бросает NullPointerException
в отличие от использования скриптлетов. Другими словами, EL нулевой.
Сделать объекты доступными для EL
Чтобы подготовить объекты для доступа к ним в JSP с помощью EL, все, что вам нужно сделать, это установить его как атрибут в желаемой области с помощью setAttribute()
метод. Например, в сервлете предварительной обработки:
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Make available by ${user} in session scope.
response.sendRedirect("userhome");
} else {
request.setAttribute("message", "Unknown login, try again"); // Make available by ${message} in request scope.
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
В случае успешного входа в систему User
объект в сеансе доступен ${user}
в EL на протяжении всего сеанса. Все свойства стиля JavaBean доступны через${user.name}
, ${user.email}
, так далее.
<c:if test="${user != null}">
<p>Welcome, ${user.name}</p>
</c:if>
В случае сбоя входа в систему сообщение доступно для ${message}
в EL только в текущем запросе. Перенаправленный JSP может получить к нему доступ и отобразить его следующим образом.
<span class="error">${message}</span>
Это значение исчезнет во всех последующих запросах, если сервлет не будет снова задан.
В JSTL есть <c:set>
тег, который позволяет вам устанавливать атрибуты в желаемой области со стороны просмотра (а также был <c:remove>
чтобы удалить его, но это было удалено). Например,
<c:set var="language" value="${not empty param.language ? param.language : not empty language ? language : pageContext.request.locale}" scope="session" />
Это в основном следующее:
- Если язык был указан как параметр запроса, он будет установлен.
- В противном случае, если язык уже был установлен в сеансе, придерживайтесь его.
- В противном случае используйте указанный пользователем языковой стандарт в заголовке запроса.
Пример взят из статьи Как интернационализировать веб-приложение Java?
Неявные объекты EL
В EL доступно несколько неявных объектов.
EL Scriptlet (out.print и нулевые проверки опущены!) ---------------------------------- ---------------- ----------------------------- ${param.foo} request.getParameter("foo"); ${paramValues.foo} request.getParameterValues ("foo"); ${header['user-agent']} request.getHeader("user-agent"); ${pageContext.request.contextPath} request.getContextPath(); ${cookie.somename} Слишком подробно (начните с request.getCookies())
В JSF (и большинстве других фреймворков MVC) запрос сервлета HTTP, сеанс и другие доступны напрямую через ${request}
, ${session}
и т. д. без необходимости получать их PageContext
.
Также доступны неявные сопоставления атрибутов для каждой области: ${pageScope}
, ${requestScope}
, ${sessionScope}
а также ${applicationScope}
. Это полезно в случае, когда у вас есть атрибуты с одним и тем же именем в разных областях (что само по себе на самом деле является плохим дизайном, но это в стороне). Например, если у вас есть"user"
атрибут, который доступен как в области запроса, так и в области сеанса, тогда ${user}
вернет тот, который находится в области запроса. Чтобы в любом случае явно получить доступ к тому, который находится в области сеанса, вам понадобится${sessionScope.user}
.
В JSF доступно гораздо больше неявных объектов. Вы можете найти их все здесь.
Обозначение скобок
Вы можете использовать так называемые фигурные скобки []
для доступа к свойствам по динамическому имени, для доступа к значениям карты с помощью ключа, содержащего точки, для использования имен / ключей, которые сами по себе являются зарезервированными литералами в Java, и для доступа к элементам массива или списка по индексу.
${sessionScope[dynamicName]}
${someMap[dynamicKey]}
${someMap['key.with.periods']}
${some['class'].simpleName}
${someList[0].name}
${someArray[0].name}
Вышеупомянутое по существу то же, что
session.getAttribute(dynamicName);
someMap.get(dynamicKey);
someMap.get("key.with.periods");
some.getClass().getSimpleName();
someList.get(0).getName();
someArray[0].getName();
Вызов методов без получения
Начиная с EL 2.2, который поддерживается как часть Servlet 3.0 / JSP 2.2 (Tomcat 7, Glassfish 3, JBoss AS 6 и т. Д.), Можно при необходимости вызывать методы без получения с аргументами.
Например
${bean.find(param.id)}
с
public Something find(String id) {
return someService.find(id);
}
вызовет метод с request.getParameter("id")
как аргумент.
Обратите внимание, что EL не поддерживает перегрузку метода, поскольку преобразователь EL не требуется для проверки типа (ов) аргумента.
Распространенное заблуждение состоит в том, что эта функция является частью JSF 2.0, но это не так. EL 2.2 и JSF 2.0 случится и будут включены в Java EE 6 API и, таким образом, как правило, встречаются вместе. Однако JSF 2.0 обратно совместим с Servlet 2.5 (Java EE 5; поставляется с EL 2.1), который не имеет этой функции.
Таким образом, при использовании JSF 2.0 в контейнере Servlet 2.5 вы определенно пропустите эту функцию EL 2.2, и вам нужно будет установить JBoss EL, чтобы получить ту же функцию в EL 2.1. Обратите внимание, что это также означает, что вы можете просто использовать EL 2.2 (или хотя бы JBoss EL) в сочетании с JSF 1.x.
EL функции
Вы можете объявить public static
служебные методы как функции EL (например, как функции JSTL), чтобы вы могли использовать их в EL. Например
package com.example;
public final class Functions {
private Functions() {}
public static boolean matches(String string, String pattern) {
return string.matches(pattern);
}
}
с /WEB-INF/functions.tld
которые выглядят следующим образом:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>Custom_Functions</short-name>
<uri>http://example.com/functions</uri>
<function>
<name>matches</name>
<function-class>com.example.Functions</function-class>
<function-signature>boolean matches(java.lang.String, java.lang.String)</function-signature>
</function>
</taglib>
который можно использовать как
<%@taglib uri="http://example.com/functions" prefix="f" %>
<c:if test="${f:matches(bean.value, '^foo.*')}">
...
</c:if>
Вы даже можете ссылаться на существующие служебные функции, например Apache Commons Lang StringEscapeUtils#escapeEcmaScript()
(или StringEscapeUtils#escapeJavaScript()
при использовании Lang 2.x)
<function>
<name>escapeJS</name>
<function-class>org.apache.commons.lang3.StringEscapeUtils</function-class>
<function-signature>java.lang.String escapeEcmaScript(java.lang.String)</function-signature>
</function>
который можно использовать как
<%@taglib uri="http://example.com/functions" prefix="f" %>
<script>
var foo = "${f:escapeJS(bean.foo)}";
...
</script>
(обратите внимание, что эти кавычки являются обязательными для представления строковой переменной JS, они вообще не имеют ничего общего с функцией EL)
При использовании преемника JSPFacelets вместо JSP перейдите к этому ответу, чтобы узнать, как создать функцию EL для Facelets: Как создать настраиваемую функцию EL для вызова статического метода? Основное отличие заключается в файле taglib.
Характеристики
Ссылки
- Руководство по Java EE 7 - Язык выражений
- Руководство по Java EE 6 - Язык выражений
- Операторы в EL
- Примеры выражений EL
- Неявные объекты в JSP EL (учебник по Java EE 5)
Часто задаваемые вопросы
- Разница между JSP EL, JSF EL и Unified EL - Немного истории об EL
- Как ссылаться на константы в EL?
- В чем необходимость
${pageContext}
? - Как объединить строки в EL?- Еще один похожий вопрос