Руководство по языку выражений JSF 3.0

Руководство по языку выражений JSF 3.0

1. обзор

В этой статье мы рассмотрим последние функции, улучшения и проблемы совместимости Expression Language версии 3.0 (EL 3.0).

Это самая последняя версия на момент написания этой статьи, она поставляется с более свежими серверами приложений JavaEE (JBoss EAP 7 и Glassfish 4 являются хорошими примерами, в которых реализована поддержка для этого).

Статья посвящена только разработкам в EL 3.0 - чтобы узнать больше о Expression Language в целом, сначала прочтите статьюEL version 2.2.

2. Предпосылки

Примеры, приведенные в статье, также были протестированы на Tomcat 8. Чтобы использовать EL3.0, вы должны добавить следующую зависимость:


    javax.el
    javax.el-api
    3.0.0

Вы всегда можете проверить репозиторий Maven на наличие последней зависимости, выполнив этотlink.

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

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

Реализация здесь является полнофункциональной, что обеспечивает большую гибкость (и некоторый предполагаемый риск) в использовании и оценке EL.

3.1. Лямбда-выражения значений EL

Основное использование этой функциональности позволяет нам указывать лямбда-выражение в качестве типа значения в выражении значения EL:

Исходя из этого, можно назвать лямбда-функцию в EL для повторного использования в составных выражениях, как в лямбда-выражении в Java SE. Составные лямбда-выражения можно разделять точкой с запятой (;):

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

3.2. Передача лямбда-выражений в компонент поддержки

Давайте пойдем дальше: мы можем получить большую гибкость, инкапсулируя логику в выражение EL (как лямбда) и передавая ее в компонент поддержки JSF:

Теперь это позволяет нам обрабатывать лямбда-выражение целиком как экземплярjavax.el.LambdaExpression:

public String multiplyValue(LambdaExpression expr){
    return (String) expr.invoke(
      FacesContext.getCurrentInstance().getELContext(), pageCounter);
}

Это замечательная функция, которая позволяет:

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

  • Простой способ внедрить поддержку лямбды в кодовые базы до JDK 8, которые могут быть не готовы к обновлению.

  • Мощный инструмент в использовании нового API Streams / Collections.

4. Улучшения API коллекций

Поддержка API Коллекций в более ранних версиях EL была несколько недостаточной. В EL 3.0 были внесены значительные улучшения API в поддержку коллекций Java, и, как и в лямбда-выражениях, EL 3.0 обеспечивает поддержку потоковой передачи данных JDK 8 в Java EE 7.

4.1. Определение динамических коллекций

Новое в 3.0, теперь мы можем динамически определять специальные структуры данных в EL:

  • Списки:

   
       
           
       
   
  • Наборы:

   
    ....
   

Note: Как и в обычной JavaSets, порядок элементов непредсказуем, если они указаны

  • Карты:

   

Tip: Распространенная ошибка в учебниках при определении динамических карт использует двойные кавычки («) вместо одинарных кавычек для ключа карты - это приведет к ошибке компиляции EL.

4.2. Расширенные операции сбора

В EL3.0 поддерживается расширенная семантика запросов, сочетающая мощь лямбда-выражений, новый потоковый API и SQL-подобные операции, такие как объединения и группировка. Мы не будем рассматривать их в этой статье, поскольку это сложные темы. Давайте посмотрим на образец, чтобы продемонстрировать его силу:


    
        
    

Таблица выше будет фильтровать список поддержки, используя переданное лямбда-выражение

 
 

Выходной текстavg будет вычислять среднее значение чисел в списке. Обе эти операции являются нулевыми за счет новогоOptional API (еще одно улучшение по сравнению с предыдущими версиями).

Помните, что для поддержки этого не требуется JDK 8, только JavaEE 7 / EL3.0. Это означает, что вы можете выполнять большинство операций JDK 8Streamв EL, но не в Java-коде вспомогательного компонента.

Tip: Вы можете использовать тег JSTL<c:set/>, чтобы объявить свою структуру данных как переменную уровня страницы и вместо этого управлять ею на всей странице JSF:

 

Теперь вы можете ссылаться на“#{pageLevelNumberList}” на всей странице, как на настоящий JSF-компонент или bean-компонент. Это позволяет использовать много раз по всей странице

5. Статические поля и методы

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

Во-первых, мы должны вручную импортировать класс, содержащий константы, в контекст EL. В идеале это нужно сделать как можно раньше. Здесь мы делаем это в инициализаторе@PostConstruct управляемого bean-компонента JSF (AServletContextListener также является жизнеспособным кандидатом):

 @PostConstruct
 public void init() {
     FacesContext.getCurrentInstance()
       .getApplication().addELContextListener(new ELContextListener() {
         @Override
         public void contextCreated(ELContextEvent evt) {
             evt.getELContext().getImportHandler()
              .importClass("com.example.el.controllers.ELSampleBean");
         }
     });
 }

Затем мы определяем поле константString (илиEnum, если вы выберете) в желаемом классе:

public static final String constantField
  = "THIS_IS_NOT_CHANGING_ANYTIME_SOON";

После чего мы можем теперь получить доступ к переменной в EL:

 
 

Согласно спецификации EL 3.0, любой класс за пределамиjava.lang.* должен быть импортирован вручную, как показано. Только после этого константы, определенные в классе, становятся доступны в EL. В идеале импорт выполняется как часть инициализации среды выполнения JSF.

Здесь необходимо сделать несколько заметок:

  • Синтаксис требует, чтобы поля и методы былиpublic, staticfinal в случае методов)

  • Синтаксис изменился между первоначальным проектом спецификации EL 3.0 и версией выпуска. Так что в некоторых учебниках вы все равно можете найти что-то похожее на:

    T(YourClass).yourStaticVariableOrMethod

    На практике это не сработает (решение об изменении дизайна для упрощения синтаксиса было принято на поздних этапах цикла реализации)

  • В последнем синтаксисе, который был выпущен, все еще была ошибка - важно использовать последние версии этих ошибок.

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

Мы рассмотрели некоторые особенности последней реализации EL. Значительные улучшения были сделаны, чтобы привнести в API новые интересные функции, такие как лямбда и гибкость потоков.

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

Так что стоит отметить, что последние улучшения API могут открыть нам возможность столкнуться с анти-шаблонами в JSF, потому что теперь EL имеет возможность выполнять настоящую бизнес-логику - в большей степени, чем раньше. И поэтому важно помнить об этом во время реальной реализации, чтобы четко разделить обязанности.

Ну и конечно примеры из статейcan be found on GitHub.