Was ist JSF? Einführung in JavaServer Faces

JavaServer Faces (JSF) ist die Java-Standardtechnologie zum Erstellen komponentenbasierter, ereignisorientierter Webschnittstellen. Wie JavaServer Pages (JSP) ermöglicht JSF den Zugriff auf serverseitige Daten und Logik. Im Gegensatz zu JSP, einer HTML-Seite mit serverseitigen Funktionen, ist JSF ein XML-Dokument, das formale Komponenten in einem logischen Baum darstellt. JSF-Komponenten werden von Java-Objekten unterstützt, die vom HTML unabhängig sind und über alle Java-Funktionen verfügen, einschließlich des Zugriffs auf Remote-APIs und -Datenbanken.

Die Schlüsselidee eines Frameworks wie JSF besteht darin, clientseitige Technologien wie HTML, CSS und JavaScript zu kapseln (oder zu verpacken ), sodass Entwickler Webschnittstellen ohne große Interaktion mit diesen Technologien erstellen können.

Dieser Artikel enthält eine Momentaufnahme des Ansatzes von JSF zur komponentenbasierten UI-Entwicklung für Java-Webanwendungen. Einfache Beispiele stellen die MVC-Architektur, das Ereignismodell und die Komponentenbibliothek von JSF vor. Beispiele hierfür sind neue Funktionen in JSF 2.3, und wir werden PrimeFaces für unsere Komponentenbibliothek verwenden.

JSF weiterentwickeln

JSF ist seit langem beliebt und wurde kürzlich von Java-kompatiblen Web-Frameworks, einschließlich clientseitiger JavaScript-Frameworks, konkurriert. Dennoch bleibt JavaServer Faces der Java-Standard, insbesondere für die groß angelegte Java-Unternehmensentwicklung. Die JSF-Spezifikation hat auch eine Fülle von Frameworks und Bibliotheken hervorgebracht, die mit den jüngsten clientseitigen Verbesserungen Schritt gehalten haben. Eines davon ist PrimeFaces, das wir in diesem Tutorial untersuchen.

Während der Zeitplan für die zukünftige Entwicklung unklar ist, bietet JSF 2.3 Entwicklern viel zu tun, während wir warten. JSF 2.3 wurde im März 2017 veröffentlicht und wurde absichtlich zur Modernisierung von JSF entwickelt. Unter mehreren hundert kleinen Reparaturen und größeren Updates werden in JSF 2.3 verwaltete Bean-Anmerkungen zugunsten von CDI verworfen, die ich später in diesem Lernprogramm vorstellen werde.

JSF 2.3 in Jakarta EE

Im September 2017 gab Oracle seine Absicht bekannt, Java EE auf die Eclipse Foundation umzustellen. Java EE wurde inzwischen in Jakarta EE umbenannt, und JSF 2.3 (Eclipse Mojarra) wurde zur Fortsetzung übernommen. Die nächste Hauptversion der JSF-Spezifikation wird Eclipse Mojarra 3.0 sein.

Erstellen komponentenbasierter Webschnittstellen in JSF

Die Kernidee von JSF besteht darin, Funktionen in wiederverwendbare Komponenten zu kapseln. Dies ähnelt den in JSP verwendeten wiederverwendbaren Tags, jedoch sind JSF-Komponenten formeller.

Während Sie JSF-Seiten in JavaServer-Seiten verwenden können, ist es üblicher, Facelets zum Erstellen eigenständiger JSF-Seiten zu verwenden. Facelets sind XHTML-Seiten zum Definieren von JSF-Schnittstellen. Mit Facelets verwenden Sie XML-Tags, um einen Komponentenbaum zu erstellen, der zum Gerüst für eine JSF-Benutzeroberfläche wird.

Listing 1 enthält die Hauptteile einer einfachen JSF-Seite, die mit Facelets geschrieben wurde. In diesem Beispiel greifen wir über eine Bean, die über CDI in den Gültigkeitsbereich gestellt wurde, auf die serverseitigen Funktionen von Java zu. Sie werden später mehr über CDI erfahren.

Listing 1. JSF-Beispielseite

    Hello JavaWorld!   #{javaBean.content}  

In Listing 1 sehen wir eine Standard-XHTML-Seite. Eine Facelets-Ansicht basiert auf XHTML. Zusätzlich zum XHTML-Namespace wird ein sekundärer Namespace definiert und referenziert.

Die hBibliothek enthält Standardkomponenten zur Verwendung in JSF-HTML-Seiten. Die //xmlns.jcp.org/jsf/htmlBibliothek definiert eine Sammlung von JSF-Komponenten, in diesem Fall eine Sammlung allgemeiner HTML-Elemente. Eine dieser Komponenten ist das Element.

HTML-Komponenten in JSF

In Bezug auf die Syntax verweist das Element von Listing 1 auf die jsf/htmlBibliothek mit dem hPräfix. Anschließend wird auf die spezifische Komponente in der Bibliothek verwiesen, bei der es sich um die headKomponente handelt.

Die Komponente gibt das HTML-Kopfelement aus. (All diese Syntax mag für einen so einfachen Zweck wie ein Overkill erscheinen, aber es gibt einen guten Grund dafür, wie Sie gleich sehen werden.)

Verschachtelungskomponenten

Im Kopf ist ein Standard-HTML- Element verschachtelt . Dieses Element wird der Komponente zusammen mit den darin verschachtelten untergeordneten Inhaltselementen bereitgestellt .

Im Hauptteil des Dokuments ist ein JSF-Ausdruck in der #{}Syntax enthalten. Dies ist genau analog zu einem JSP-Ausdruck mit dem ${}Format: Er ermöglicht den Zugriff auf Java-Objekte im Gültigkeitsbereich und einfache Funktionen.

Das Grundmuster für JSF ist einfach: Verwenden Sie Facelets, um einen XML-Baum zu erstellen, der auf eine oder mehrere Komponentenbibliotheken verweist, und verwenden Sie dann Komponenten in der Bibliothek, um Java-Objekte als HTML zu rendern.

Verwenden von Java-Objekten in JSF

Wenn Sie zu Listing 1 zurückkehren, beachten Sie, dass sich das Objekt im JSF-Ausdruck ( ${javaBean.content) javaBeanim Gültigkeitsbereich befindet, wenn dieses Markup ausgeführt wird. Das XHTML von Facelets greift auf die .contentEigenschaft des javaBeanObjekts zu. Die endgültige Ausgabe ist eine Webschnittstelle, die die Facelets-Ansichtsstruktur mit den serverseitigen Daten- und Logikfunktionen von Java zusammenführt.

Die Verwendung eines JSF-Ausdrucks ist nur eine Möglichkeit, über eine JSF-Benutzeroberfläche auf Java-Anwendungsdaten zuzugreifen. Schließlich möchten Sie andere Möglichkeiten untersuchen, wie eine JSF-Komponente mit dem Java-Backend interagieren kann - beispielsweise Datenlisten und Raster sowie eine Vielzahl von Eingabesteuerelementen. Im Moment reicht es aus, zu erfassen, wie JSF XML-Tags (oder Anmerkungen) verwendet, um einen Baum von Komponenten zu erstellen, der HTML basierend auf den in Java-Objekten enthaltenen Daten ausgibt.

Anmerkungen vs XML

Mit JSF 2.3 ist es möglich geworden, JSF-Komponenten mit Anmerkungen zu definieren, wobei XML-Metadaten vollständig vermieden werden. Es ist vollständig möglich, eine JSF-App zu definieren und bereitzustellen, ohne XML zu bearbeiten.

Struktur einer JSF-Anwendung

Wie JavaServer Pages und die Servlet-API erfordern JavaServer Faces eine Standardverzeichnisstruktur und Metadaten. Diese werden als .war- Dateien bereitgestellt .

Die Struktur einer .war-Datei ähnelt einer Servlet- oder JSP-Anwendung. Es enthält ein /web-appVerzeichnis, das die Markup-Dateien der Anwendung enthält (in diesem Fall HTML, JSP und Facelets), sowie ein /WEB-INFVerzeichnis, das die Metadaten zur Beschreibung der Anwendung enthält.

JSF bedienen

Während Sie JSF in einem Java EE-Container wie Glassfish ausführen können, ist ein einfacher Servlet-Container alles, was Sie wirklich brauchen. Tomcat ist ein beliebter Container für JSF und andere serverseitige Java-Technologien.

JSF 2.3: Spezifikation und Implementierungen

Eine der Stärken von Java besteht darin, dass es auf Standards basiert und diese Standards von einem Open-Source-Community-Prozess gesteuert werden. Seit seiner Gründung hat der Java Community Process (JCP) die Entwicklung der Java-Technologie überwacht. Sobald eine Spezifikation oder Spezifikationsverbesserung von JCP entwickelt und genehmigt wurde, kann sie von mehreren Parteien implementiert werden. Bis vor kurzem wurden Servlets, JSP und JSF mithilfe des Open Source-Spezifikationsprozesses von JCP entwickelt.

Die aktuellste JSF-Spezifikation zum jetzigen Zeitpunkt ist JSF 2.3, das 2017 als Teil von Java EE 8 veröffentlicht wurde. Mojarra von Oracle (jetzt Eclipse) ist die JSF-Referenzimplementierung, und MyFaces und PrimeFaces sind beliebte Implementierungen von Drittanbietern.

Jedes dieser Frameworks implementiert den JSF-Kern, der einige Standardkomponenten enthält. Anbieter bieten möglicherweise zusätzlich zum Standard zusätzliche Komponentenbibliotheken an. Bei der Evaluierung von JSF-Frameworks sollten Sie die Anforderungen Ihrer Anwendung und die verfügbaren Komponentenbibliotheken berücksichtigen, um sie zu erstellen. Idealerweise sollte Ihr JSF-Framework Sie sofort so nah wie möglich an das bringen, was Sie benötigen.

MVC in JSF 2.3

JSF ist ein MVC-Framework , das das Model-View-Controller-Muster implementiert. Im MVC-Muster besteht die Idee darin, die drei Aspekte einer Benutzeroberfläche in diskrete Teile zu unterteilen, damit sie einfacher zu verwalten sind. Im Allgemeinen ist die Ansicht für die Anzeige von Daten im Modell verantwortlich, und die Steuerung ist für die Einrichtung des Modells und die Weiterleitung des Benutzers an die richtige Ansicht verantwortlich.

In einer JSF-Implementierung ist die Ansicht die Facelets-Seite mit ihren XML-Tags. Diese definieren das Layout der Benutzeroberfläche. Die andere Hälfte der Verwendung von JSF ist die Serverseite, auf der Java-Klassen diese UI-Komponenten unterstützen.

Verwaltete Beans sind in JSF 2.3 veraltet

Verwaltete Bean-Annotationen wurden in JSF 2.3 nicht mehr unterstützt und durch CDI (Contexts and Dependency Injection) ersetzt. Mit CDI definieren Entwickler einen Kontext und fügen diesem Kontext Objekte hinzu. Diejenigen, die mit verwalteten Beans vertraut sind, werden die Annotationssyntax etwas anders finden, aber die Semantik bleibt genau gleich.

Controller Beans

In JSF 2.3 stellen Controller-Beans den Controller- Teil der MVC-Gleichung bereit . Normale Java-Objekte (oft als POJOs oder einfache alte Java-Objekte bezeichnet) stellen das Modell bereit.

In Bezug auf den Prozessfluss, Controller Beans:

  1. Entscheiden Sie, wohin Benutzeranforderungen geleitet werden sollen
  2. Richten Sie POJOs für das Modell ein
  3. Verwenden Sie das Modell, um die Facelets-Ansicht zu rendern

JSF faltet dann den Komponentenbaum und das Modell zusammen, um den Ausgabe-HTML-Code zu rendern.

Listing 2 zeigt, wie Sie das javaBeanObjekt aus Listing 1 mit CDI definieren würden . In dieser Auflistung wird davon ausgegangen, dass die Anwendung die cdi-api-1.2.jar in ihren Abhängigkeiten hat.

Listing 2. Eine mit CDI definierte JavaBean

 import javax.inject.Named; import javax.enterprise.context.SessionScoped; @Named @ViewScoped public class JavaBean implements Serializable { private String content = ìWelcome to JSF!î // getters/setters } 

JSF 2.3 mit PrimeFaces

In den nächsten Abschnitten werde ich PrimeFaces verwenden, um Ihnen zu zeigen, wie JSF das MVC-Muster, ereignisgesteuertes Messaging und wiederverwendbare Komponenten implementiert. Öffnen Sie zunächst den PrimeFaces Showcase, klicken Sie in der linken Spalte auf den Link Daten und wählen Sie Datenliste aus . Dadurch wird der DataList-Demo-Code für PrimeFaces aufgerufen.

Abbildung 1 zeigt Ihnen, wo Sie diese Beispiele finden.

Matthew Tyson

Abbildung 2 zeigt die Ausgabe einer einfachen Datentabelle, die aus der PrimeFaces DataList-Demo stammt.

Matthew Tyson

PrimeFaces DataList: Zugriff auf das Datenmodell

Listing 3 presents the markup for this dataList display. If you scroll to the bottom of the PrimeFaces showcase, you can see the markup in the dataList.xhtml tab.

Listing 3. Facelet for PrimeFaces DataList

   Basic  #{car.brand}, #{car.year}  

In Listing 3, notice the value property of the dataList component. You can see that this references a dataListView object, and accesses the .cars1 property on it. The component is going to use the model object returned by that field. JSF tokens use conventional accessors to reference object properties, so .cars1 will refer to the getCars() getter on the object.

Next, notice the var="car" property. This tells the dataList component what variable to use when it iterates over the list of cars returned by the value field. These properties are specific to the dataList component, but the value property is very common. The var attribute is also conventional for components that iterate over lists.

In the body of the component in Listing 3, you can see the car variable is accessed via JSF expressions like #{car.brand}. Each iteration of the dataListView.cars1 instance will output the car.brand field.

Notice that the tag demonstrates the ability to customize components for how they will display. In this case, the header is defined as Basic.

You can see how the Facelets XML will drive this output by combining the data with the markup. Now let's look at the Java code behind it.

DataList's server-side components

Listing 4 shows DataListView, the Java class that is used by the markup in Listing 3. You'll see shortly how the dataListView instance is associated with the DataListView class.

Listing 4. DataListView class

 package org.primefaces.showcase.view.data; import java.io.Serializable; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Named; // Pre JSF 2.3, this was: // import javax.faces.bean.ManagedBean; import javax.inject.Inject; import javax.faces.bean.ViewScoped; import org.primefaces.showcase.domain.Car; import org.primefaces.showcase.service.CarService; @Named @ViewScoped public class DataListView implements Serializable { private List cars1; private Car selectedCar; @Inject("#{carService}") private CarService service; @PostConstruct public void init() { cars1 = service.createCars(10); } public List getCars1() { return cars1; } public void setService(CarService service) { this.service = service; } } 

Listing 4 has a few other important elements, which we'll consider piece by piece.

Dependency injection and annotations

First, notice that the DataListView class is annotated with @Named, which you can see from the import import javax.inject.Named; is part of JSF. The @Named annotation tells JSF this bean is part of the app. The @ViewScoped annotation informs JSF that the bean will live for just the life of the view.

Beachten Sie als Nächstes, dass die CarServiceEigenschaft über die @InjectAnnotation verfügt ( @ManagedPropertyvor JSF 2.3 als Annotation bezeichnet ). Dies ist eine weitere JSF-Funktion, mit der Beans "miteinander verdrahtet" werden können, eine Technik, die vom Spring-Framework und anderen Tools zur Abhängigkeitsinjektion populär gemacht wird. Im Wesentlichen findet JSF das carServiceObjekt im Bereich und ordnet es automatisch dem serviceFeld auf dem DataListViewObjekt zu.