Anleitung zur JSF-Ausdruckssprache 3.0

Leitfaden zu JSF Expression Language 3.0

1. Überblick

In diesem Artikel werden die neuesten Funktionen, Verbesserungen und Kompatibilitätsprobleme von Expression Language, Version 3.0 (EL 3.0), vorgestellt.

Dies ist die neueste Version zum Zeitpunkt der Erstellung dieses Dokuments und wird mit neueren JavaEE-Anwendungsservern ausgeliefert (JBoss EAP 7 und Glassfish 4 sind gute Beispiele, die Unterstützung dafür implementiert haben).

Der Artikel konzentriert sich nur auf die Entwicklungen in EL 3.0. Um mehr über die Ausdruckssprache im Allgemeinen zu erfahren, lesen Sie zuerst den Artikel vonEL version 2.2.

2. Voraussetzungen

Die in diesem Artikel gezeigten Beispiele wurden auch mit Tomcat 8 getestet. Um EL3.0 verwenden zu können, müssen Sie die folgende Abhängigkeit hinzufügen:


    javax.el
    javax.el-api
    3.0.0

Sie können das Maven-Repository jederzeit auf die neueste Abhängigkeit überprüfen, indem Sie diesenlink folgen.

3. Lambda-Ausdrücke

Die neueste EL-Iteration bietet eine sehr robuste Unterstützung für Lambda-Ausdrücke. Lambda-Ausdrücke wurden in Java SE 8 eingeführt, in EL wird sie jedoch mit Java EE 7 unterstützt.

Die Implementierung ist voll funktionsfähig und ermöglicht eine große Flexibilität (und ein gewisses implizites Risiko) bei der Verwendung und Evaluierung von EL.

3.1. Lambda EL-Wertausdrücke

Die grundlegende Verwendung dieser Funktionalität ermöglicht es uns, einen Lambda-Ausdruck als Werttyp in einem EL-Werteausdruck anzugeben:

Davon ausgehend kann man die Lambda-Funktion in EL zur Wiederverwendung in zusammengesetzten Anweisungen benennen, genau wie Sie es in einem Lambda-Ausdruck in Java SE tun würden. Zusammengesetzte Lambda-Ausdrücke können durch ein Semikolon (;) getrennt werden:

Dieses Snippet weist die Funktion der Kennungcubezu, die dann sofort wiederverwendet werden kann.

3.2. Weitergabe von Lambda-Ausdrücken an die Backing Bean

Gehen wir noch etwas weiter: Wir können viel Flexibilität erzielen, indem wir Logik in einen EL-Ausdruck (als Lambda) einkapseln und an die JSF-Backing-Bean übergeben:

Dies ermöglicht es uns nun, den gesamten Lambda-Ausdruck als Instanz vonjavax.el.LambdaExpression zu verarbeiten:

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

Dies ist eine überzeugende Funktion, die Folgendes ermöglicht:

  • Eine saubere Art, Logik zu packen und ein sehr flexibles Paradigma für die funktionale Programmierung bereitzustellen. Die oben beschriebene Backing-Bean-Logik kann von Werten abhängig gemacht werden, die aus verschiedenen Quellen stammen.

  • Eine einfache Möglichkeit, Lambda-Unterstützung in Code-Basen vor JDK 8 einzuführen, die möglicherweise nicht für ein Upgrade bereit sind.

  • Ein leistungsstarkes Tool zur Verwendung der neuen Streams / Collections-API.

4. Verbesserungen der Sammlungs-API

Die Unterstützung für die Collections-API in früheren EL-Versionen fehlte etwas. EL 3.0 hat wesentliche API-Verbesserungen für die Unterstützung der Java-Sammlungen eingeführt. Genau wie die Lambda-Ausdrücke bietet EL 3.0 Unterstützung für JDK 8-Streaming in Java EE 7.

4.1. Definition dynamischer Sammlungen

Neu in 3.0 können wir jetzt dynamisch Ad-hoc-Datenstrukturen in EL definieren:

  • Listen:

   
       
           
       
   
  • Sätze:

   
    ....
   

Note: Wie bei normalem JavaSets, ist die Reihenfolge der Elemente in der Liste nicht vorhersehbar

  • Karten:

   

Tip: Ein häufiger Fehler in Lehrbüchern beim Definieren dynamischer Karten verwendet doppelte Anführungszeichen (") anstelle von einfachen Anführungszeichen für den Kartenschlüssel. Dies führt zu einem EL-Kompilierungsfehler.

4.2. Erweiterte Erfassungsvorgänge

Mit EL3.0 wird eine erweiterte Abfragesemantik unterstützt, die die Leistungsfähigkeit von Lambda-Ausdrücken, die neue Streaming-API und SQL-ähnliche Vorgänge wie Verknüpfungen und Gruppierungen kombiniert. Wir werden diese in diesem Artikel nicht behandeln, da es sich um fortgeschrittene Themen handelt. Schauen wir uns ein Beispiel an, um seine Leistungsfähigkeit zu demonstrieren:


    
        
    

In der obigen Tabelle wird eine Backing-Liste mit dem übergebenen Lambda-Ausdruck gefiltert

 
 

Der Ausgabetextavg berechnet den Durchschnitt der Zahlen in der Liste. Beide Operationen sind durch die neuenOptional API nullsicher (eine weitere Verbesserung gegenüber früheren Versionen).

Denken Sie daran, dass für die Unterstützung hierfür kein JDK 8 erforderlich ist, sondern nur JavaEE 7 / EL3.0. Dies bedeutet, dass Sie die meisten JDK 8Stream-Operationen in EL ausführen können, jedoch nicht im Java-Code der Backing Bean.

Tip: Mit dem Tag JSTL<c:set/> können Sie Ihre Datenstruktur als Variable auf Seitenebene deklarieren und diese stattdessen auf der gesamten JSF-Seite bearbeiten:

 

Sie können jetzt auf der gesamten Seite auf“#{pageLevelNumberList}” verweisen, als wäre es eine echte JSF-Komponente oder Bean. Dies ermöglicht eine erhebliche Wiederverwendung auf der gesamten Seite

5. Statische Felder und Methoden

In früheren EL-Versionen wurde kein statischer Feld-, Methoden- oder Enum-Zugriff unterstützt. Dinge haben sich geändert.

Zuerst müssen wir die Klasse mit den Konstanten manuell in den EL-Kontext importieren. Dies geschieht im Idealfall so früh wie möglich. Hier machen wir es im@PostConstruct-Initialisierer der JSF-verwalteten Bean (AServletContextListener ist ebenfalls ein brauchbarer Kandidat):

 @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");
         }
     });
 }

Dann definieren wir einString konstantes Feld (oder einEnum, wenn Sie möchten) in der gewünschten Klasse:

public static final String constantField
  = "THIS_IS_NOT_CHANGING_ANYTIME_SOON";

Danach können wir in EL auf die Variable zugreifen:

 
 

Gemäß der EL 3.0-Spezifikation muss jede Klasse außerhalb vonjava.lang.* wie gezeigt manuell importiert werden. Erst danach sind die in einer Klasse definierten Konstanten in EL verfügbar. Der Import erfolgt idealerweise im Rahmen der Initialisierung der JSF-Laufzeit.

Hier sind einige Anmerkungen notwendig:

  • Die Syntax erfordert, dass die Felder und Methodenpublic, static (undfinal bei Methoden) sind.

  • Die Syntax hat sich zwischen dem ersten Entwurf der EL 3.0-Spezifikation und der Release-Version geändert. In einigen Lehrbüchern finden Sie möglicherweise noch etwas, das wie folgt aussieht:

    T(YourClass).yourStaticVariableOrMethod

    Dies funktioniert in der Praxis nicht (eine Designänderung zur Vereinfachung der Syntax wurde spät im Implementierungszyklus beschlossen).

  • Die endgültige Syntax, die veröffentlicht wurde, war immer noch fehlerhaft - es ist wichtig, die neuesten Versionen davon auszuführen.

6. Fazit

Wir haben einige der Highlights in der neuesten EL-Implementierung untersucht. Es wurden wesentliche Verbesserungen vorgenommen, um der API coole neue Funktionen wie Lambda und Streams-Flexibilität zu verleihen.

Angesichts der Flexibilität, die wir jetzt in EL haben, ist es wichtig, sich an eines der Entwurfsziele des JSF-Frameworks zu erinnern: eine saubere Trennung von Bedenken bei der Verwendung des MVC-Musters.

Es ist daher erwähnenswert, dass die neuesten Verbesserungen der API uns möglicherweise für Anti-Patterns in JSF öffnen, da EL jetzt die Fähigkeit besitzt, echte Geschäftslogik zu erstellen - mehr als zuvor. Daher ist es wichtig, dies bei einer Implementierung in der Praxis zu berücksichtigen, um sicherzustellen, dass die Verantwortlichkeiten sauber voneinander getrennt sind.

Und natürlich die Beispiele aus den Artikelncan be found on GitHub.