Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Выражения значений и методов

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

Здесь рассматриваются следующие темы:

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

Выражения значений подразделяются на выражения rvalue и lvalue. Выражение lvalue может указывать цель, такую ​​как объект, свойство компонента или элементы коллекции, которым может быть присвоено значение. Выражение rvalue не может указывать такую ​​цель.

Все выражения немедленного выполнения используют разделители ${}, и хотя выражение может быть выражением lvalue, никакие присваивания никогда не произойдут. Выражения отложенного выполнения используют разделители #{} и могут выступать как выражения rvalue и lvalue. Если выражение является выражением lvalue, ему может быть присвоено новое значение. Рассмотрим следующие два выражения значения:

${customer.name}

#{customer.name}

Первое использует синтаксис немедленного выполнения, тогда как как второй использует синтаксис отложенного выполнения. Первое выражение обращается к свойству name, получает его значение и передаёт значение в обработчик тега. Со вторым выражением обработчик тега может отложить выполнение выражения на более позднее время в жизненном цикле страницы, если технология, использующая этот тег, позволяет.

В случае JavaServer Faces выражение последнего тега вычисляется непосредственно во время первоначального запроса страницы. Во время повторного запроса это выражение может использоваться для установки значения свойству name из пользовательского ввода.

Ссылка на объекты

Идентификатор верхнего уровня (например, customer в выражении customer.name) может ссылаться на следующие объекты:

  • Лямбда-параметры

  • Переменные EL

  • Managed-бины

  • Неявные объекты

  • Классы статических полей и методов

Чтобы обратиться к этим объектам, вы пишете выражение, используя переменную, которая является именем объекта. Следующее выражение ссылается на Managed-бин с именем customer:

${customer}

Вы можете использовать кастомный распознаватель EL, чтобы изменить алгоритм вычисления значений переменных. Например, вы можете предоставить распознаватель EL, который перехватывает объекты с именем customer, так что ${customer} возвращает значение в распознавателе EL. (JavaServer Faces использует распознаватель EL для обработки Managed-бинов.)

Константа enum является частным случаем статического поля, и вы можете напрямую ссылаться на такую ​​константу. Например, рассмотрим этот enum:

public enum Suit {hearts, spades, diamonds, clubs}

В следующем выражении, в котором mySuit является объектом Suit, вы можете сравнить suit.hearts с объектом:

${mySuit == suit.hearts}

Ссылка на свойства объекта или элементы коллекции

Чтобы ссылаться на свойства бина, статические поля или методы класса или элементы коллекции, используйте нотацию . или []. Тот же синтаксис можно использовать для атрибутов неявного объекта, поскольку атрибуты размещены в отображении Map.

Для ссылки на свойство name компонента customer используйте либо выражение ${customer.name}, либо выражение ${customer["name"]}. Здесь часть внутри скобок является литералом String, который является именем свойства для ссылки. Синтаксис [] является более общим, чем синтаксис ., потому что часть внутри скобок может быть любым выражением String, а не только литералами.

Вы можете использовать двойные или одинарные кавычки для литерала String. Вы также можете объединить нотации [] и ., как показано здесь:

${customer.address["street"]}

Вы можете ссылаться на статическое поле или метод, используя синтаксис classname.field, как в следующем примере:

Boolean.FALSE

Имя класса — это имя класса без имени пакета. По умолчанию импортируются все пакеты java.lang. При необходимости вы можете импортировать другие пакеты, классы и статические поля.

Если вы обращаетесь к элементу в массиве или списке, вы должны использовать нотацию [] и указывать индекс в массиве или списке. Индекс — это выражение, которое можно конвертировать в int. Следующий пример ссылается на первый из заказов клиента, предполагая, что customer.orders имеет тип List:

${customer.orders[1]}

Если вы обращаетесь к элементу в Map, вы должны указать ключ для Map. Если ключ является литералом String, можно использовать точку (.). Предполагая, что customer.orders является Map с ключом String, следующие примеры ссылаются на элемент с ключом «socks»:

${customer.orders["socks"]}

${customer.orders.socks}

Ссылка на литералы

EL определяет следующие литералы:

  • Логический: true и false

  • Integer: как в Java

  • Floating-point: как в Java

  • String: с одинарными и двойными кавычками. " экранируется как \", ' — как \' и \ — как \\

  • Null: null

Вот некоторые примеры:

  • ${"literal"}

  • ${true}

  • ${57}

Параметризованные вызовы методов

EL предлагает поддержку параметризованных вызовов методов.

Операторы . и [] могут использоваться для вызова вызовов методов с параметрами, как показано в следующем синтаксисе выражения:

  • expr-a[expr-b](parameters)

  • expr-a.identifier-b(parameters)

В синтаксисе первого выражения expr-a вычисляется для представления объекта компонента. Выражение expr-b вычисляется и приводится (cast) к строке, которая представляет метод в бине, представленном expr-a. Во втором синтаксисе выражения expr-a вычисляется для представления объекта компонента, а identifier-b — строка, представляющая метод в объекте компонента. Параметры в скобках являются аргументами для вызова метода. Параметрами могут быть ноль или более значений выражений, разделённые запятыми.

Параметры поддерживаются как для выражений значений, так и для выражений методов. В следующем примере, который является изменённым тегом из приложения guessnumber, случайное число предоставляется в качестве аргумента, а не из пользовательского ввода для вызова метода:

<h:inputText value="#{userNumberBean.userNumber('5')}">

В предыдущем примере используется выражение значения.

Рассмотрим следующий пример тега компонента JavaServer Faces, который использует выражение метода:

<h:commandButton action="#{trader.buy}" value="buy"/>

Выражение EL trader.buy вызывает метод buy бина trader. Вы можете изменить тег для передачи параметра. Вот исправленный тег, в котором передаётся параметр:

<h:commandButton action="#{trader.buy('SOMESTOCK')}" value="buy"/>

В предыдущем примере вы передаёте строку 'SOMESTOCK' (символ акции) в качестве параметра методу buy.

Где могут использоваться выражения значения

Можно использовать выражения значений с использованием разделителей ${}

  • В статическом тексте

  • В любом стандартном или кастомном атрибуте тега, который может принимать выражение

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

<some:tag>
    некоторый текст ${expr} некоторый текст
</some:tag>

Атрибут тега можно установить следующими способами.

  • С единственной конструкцией выражения:

    <some:tag value="${expr}"/>
    
    <another:tag value="#{expr}"/>

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

  • С одним или несколькими выражениями, разделёнными или окружёнными текстом:

    <some:tag value="some${expr}${expr}text${expr}"/>
    
    <another:tag value="some#{expr}#{expr}text#{expr}"/>

    Эти виды выражений, называемые составными выражениями, вычисляются слева направо. Каждое выражение, встроенное в составное выражение, конвертируется в String и затем объединяется с любым промежуточным текстом. Результирующая String затем конвертируется к ожидаемому типу атрибута.

  • Только с текстом:

    <some:tag value="sometext"/>

    Значение атрибута String конвертируется к ожидаемому типу атрибута.

Вы можете использовать оператор конкатенации строк += чтобы создать одно выражение из того, что иначе было бы составным выражением. Например, вы можете изменить составное выражение

<some:tag value="sometext ${expr} moretext"/>

на

<some:tag value="${sometext += expr += moretext}"/>

Все выражения, используемые для установки значений атрибутов, вычисляются в контексте ожидаемого типа. Если результат вычисления выражения не соответствует в точности ожидаемому типу, будет выполнена конвертация типа. Например, выражение ${1.2E4}, предоставленное как значение атрибута типа float, приведёт к следующей конвертации:

Float.valueOf("1.2E4").floatValue()

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

Ещё одна особенность EL — поддержка выражений отложенного выполнения методов. Выражение метода используется для ссылки на публичный метод бина и имеет тот же синтаксис, что и выражение lvalue.

В JavaServer Faces тег компонента представляет компонент на странице. Тег компонента использует выражения метода для указания методов, которые могут быть вызваны для выполнения некоторой обработки для компонента. Эти методы необходимы для обработки событий, которые генерируют компоненты, и для валидации данных компонентов, как показано в этом примере:

<h:form>
    <h:inputText id="name"
                 value="#{customer.name}"
                 validator="#{customer.validateName}"/>
    <h:commandButton id="submit"
                     action="#{customer.submit}" />
</h:form>

Тег h:inputText отображается в виде поля. Атрибут validator этого тега h:inputText ссылается на метод validateName в бине customer.

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

Как и выражения lvalue, выражения методов могут использовать операторы . и []. Например, #{object.method} эквивалентно #{object["method"]}. Литерал внутри [] конвертируется в String и используется для поиска имени метода, который ему соответствует.

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

  • С единственной конструкцией выражения, где бин ссылается на компонент JavaBeans, а метод ссылается на метод компонента JavaBeans:

    <some:tag value="#{bean.method}"/>

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

  • Только с текстом:

    <some:tag value="sometext"/>

    Выражения метода поддерживают литералы в первую очередь для поддержки атрибутов action в JavaServer Faces. Когда вызывается метод, на который ссылается выражение этого метода, метод возвращает литерал String, который затем конвертируется к ожидаемому возвращаемому типу, как определено в дескрипторе библиотеки тегов.

Лямбда-выражения

Лямбда-выражение — это выражение значения с параметрами. Синтаксис аналогичен лямбда-выражению в Java, за исключением того, что в EL тело лямбда-выражения является выражением EL.

Для получения основной информации о лямбда-выражениях см. http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html.

Замечание:

Лямбда-выражения являются частью Java SE 8, но вы можете использовать их в выражениях EL с Java SE 7, версией Java, связанной с платформой Java EE 7.

Лямбда-выражение использует символ стрелки (). Идентификаторы слева от оператора называются лямбда-параметрами. Тело справа от оператора должно быть выражением EL. Параметры лямбда заключены в скобки. Круглые скобки могут быть опущены, если есть только один параметр. Вот некоторые примеры:

x -> x+1
(x, y) -> x + y
() -> 64

Лямбда-выражение ведет себя как функция. Оно может быть вызвано немедленно. Например, следующий вызов при вычислении даёт результат 7:

((x, y) -> x + y)(3, 4)

Вы можете использовать лямбда-выражение в сочетании с операторами присваивания и точки с запятой. Например, следующий код назначает предыдущее лямбда-выражение переменной, а затем вызывает его. Результат снова 7:

v = (x, y) -> x + y; v(3, 4)

Лямбда-выражение также можно передавать в качестве аргумента методу и вызывать в методе. Он также может быть вложен в другое лямбда-выражение.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)