Wat is JSF? Introductie van JavaServer Faces

JavaServer Faces (JSF) is de Java-standaardtechnologie voor het bouwen van componentgebaseerde, gebeurtenisgeoriënteerde webinterfaces. Net als JavaServer Pages (JSP) geeft JSF toegang tot server-side data en logica. In tegenstelling tot JSP, dat in wezen een HTML-pagina is die doordrenkt is met server-side-mogelijkheden, is JSF een XML-document dat formele componenten in een logische structuur vertegenwoordigt. JSF-componenten worden ondersteund door Java-objecten, die onafhankelijk zijn van de HTML en beschikken over alle Java-mogelijkheden, inclusief toegang tot externe API's en databases.

Het belangrijkste idee van een framework als JSF is om clienttechnologieën zoals HTML, CSS en JavaScript in te kapselen (of in te pakken ), zodat ontwikkelaars webinterfaces kunnen bouwen zonder veel interactie met deze technologieën.

Dit artikel geeft een momentopname van JSF's benadering van op componenten gebaseerde UI-ontwikkeling voor Java-webtoepassingen. Eenvoudige voorbeelden introduceren de MVC-architectuur, het gebeurtenismodel en de componentenbibliotheek van JSF. Voorbeelden zijn onder meer nieuwe functies in JSF 2.3, en we zullen PrimeFaces gebruiken voor onze componentenbibliotheek.

JSF evolueren

JSF is al lang populair en heeft onlangs te maken gehad met concurrentie van Java-compatibele webframeworks, waaronder JavaScript-frameworks aan de clientzijde. Toch blijft JavaServer Faces de Java-standaard, vooral voor grootschalige Java-bedrijfsontwikkeling. De JSF-specificatie heeft ook een schat aan frameworks en bibliotheken voortgebracht, die gelijke tred hebben gehouden met recente verbeteringen aan de clientzijde. Een daarvan is PrimeFaces, die we in deze tutorial onderzoeken.

Hoewel het schema voor toekomstige ontwikkeling onduidelijk is, biedt JSF 2.3 ontwikkelaars genoeg om mee te werken terwijl we wachten. JSF 2.3, uitgebracht in maart 2017, was met opzet ontworpen om JSF te moderniseren. Tussen enkele honderden kleine reparaties en grotere updates, schaft JSF 2.3 managed bean-annotaties af ten gunste van CDI, die ik later in deze tutorial zal introduceren.

JSF 2.3 in Jakarta EE

In september 2017 kondigde Oracle het voornemen aan om Java EE over te zetten naar de Eclipse Foundation. Java EE is sindsdien omgedoopt tot Jakarta EE en JSF 2.3 (Eclipse Mojarra) is goedgekeurd voor voortzetting. De volgende grote release van de JSF-specificatie zal Eclipse Mojarra 3.0 zijn.

Op componenten gebaseerde webinterfaces bouwen in JSF

Het kernidee van JSF is om functionaliteit in te kapselen in herbruikbare componenten. Dit is vergelijkbaar met de herbruikbare tags die in JSP worden gebruikt, maar JSF-componenten zijn formeler.

Hoewel u JSF-pagina's binnen JavaServer Pages kunt gebruiken, is het gebruikelijker om Facelets te gebruiken om zelfstandige JSF-pagina's te bouwen. Facelets zijn XHTML-pagina's die zijn ontworpen voor het definiëren van JSF-interfaces. Met Facelets gebruikt u XML-tags om een ​​componentenboom te maken die de basis wordt voor een JSF-gebruikersinterface.

Listing 1 presenteert de belangrijkste onderdelen van een eenvoudige JSF-pagina die is geschreven met Facelets. In dit voorbeeld hebben we toegang tot Java's server-side mogelijkheden via een bean die via CDI in scope is geplaatst. Je zult later meer over CDI zien.

Listing 1. JSF-voorbeeldpagina

    Hello JavaWorld!   #{javaBean.content}  

In Listing 1 zien we een standaard XHTML-pagina. Een Facelets-weergave is bovenop XHTML gebouwd. Naast de XHTML-naamruimte wordt een secundaire naamruimte gedefinieerd en er wordt naar verwezen.

De hbibliotheek bevat standaardcomponenten voor gebruik in JSF HTML-pagina's. De //xmlns.jcp.org/jsf/htmlbibliotheek definieert een verzameling JSF-componenten, in dit geval een verzameling algemene HTML-elementen. Een van deze componenten is het element.

HTML-componenten in JSF

In termen van syntaxis verwijst het element van listing 1 naar de jsf/htmlbibliotheek met het hvoorvoegsel. Het verwijst dan naar de specifieke component binnen de bibliotheek, dat is de headcomponent.

De component voert het HTML-head-element uit. (Al die syntaxis lijkt misschien overdreven voor zo'n eenvoudig doel, maar er is een goede reden voor, zoals je binnenkort zult zien.)

Onderdelen nestelen

In het hoofd is een standaard HTML- element genest . Dit element wordt aan de component geleverd, samen met de onderliggende contentelementen die erin zijn genest.

In de hoofdtekst van het document is een JSF-expressie opgenomen in de #{}syntaxis. Dit is precies analoog aan een JSP-expressie met het ${}formaat: het biedt toegang tot Java-objecten binnen het bereik en eenvoudige functies.

Het basispatroon voor JSF is eenvoudig: gebruik Facelets om een ​​XML-boomstructuur te bouwen die verwijst naar een componentbibliotheek of bibliotheken, en gebruik vervolgens componenten binnen de bibliotheek om Java-objecten als HTML weer te geven.

Java-objecten gebruiken in JSF

Als we teruggaan naar Listing 1, merk op dat binnen de JSF expression ( ${javaBean.content) Het javaBeanobject binnen het bereik valt wanneer deze opmaak wordt uitgevoerd. De XHTML van Facelets geeft toegang tot de .contenteigenschap op het javaBeanobject. De uiteindelijke output is een webinterface die de Facelets-weergavestructuur combineert met Java's server-side data en logische mogelijkheden.

Het gebruik van een JSF-expressie is slechts één manier om toegang te krijgen tot Java-toepassingsgegevens vanuit een JSF-gebruikersinterface. Uiteindelijk wilt u andere manieren onderzoeken waarop een JSF-component kan communiceren met de Java-backend - zaken als gegevenslijsten en rasters en een verscheidenheid aan invoerbesturingselementen. Voorlopig is het voldoende om te begrijpen hoe JSF XML-tags (of annotaties) gebruikt om een ​​boom met componenten te maken die HTML uitvoert op basis van de gegevens in Java-objecten.

Annotaties versus XML

Met JSF 2.3 is het mogelijk geworden om JSF-componenten met annotaties te definiëren, waarbij XML-metadata volledig wordt vermeden. Het is volledig mogelijk om een ​​JSF-app te definiëren en te implementeren zonder XML te bewerken.

Opbouw van een JSF-applicatie

Net als JavaServer Pages en de Servlet API, vereist JavaServer Faces een standaard directorystructuur en metadata. Deze worden geïmplementeerd als .war- bestanden.

De structuur van een .war-bestand is vergelijkbaar met een Servlet- of JSP-applicatie. Het bevat een /web-appdirectory met de opmaakbestanden van de applicatie (in dit geval HTML, JSP en Facelets), evenals een /WEB-INFdirectory die de metadata presenteert om de applicatie te beschrijven.

JSF bedienen

Hoewel u JSF in een Java EE-container zoals Glassfish kunt uitvoeren, is een eenvoudige servlet-container alles wat u echt nodig hebt. Tomcat is een populaire container voor JSF en andere Java-technologieën aan de serverzijde.

JSF 2.3: Spec en implementaties

Een van Java's sterke punten is dat het gebaseerd is op standaarden, en die standaarden worden beheerst door een open source community-proces. Sinds de oprichting heeft het Java Community Process (JCP) toezicht gehouden op de ontwikkeling van Java-technologie. Zodra een specificatie of specificatieverbetering is ontwikkeld en goedgekeurd door JCP, kan deze door meerdere partijen worden geïmplementeerd. Tot voor kort werden Servlets, JSP en JSF allemaal ontwikkeld met behulp van het open source-specificatieproces van JCP.

De meest recente JSF-specificatie op het moment van schrijven is JSF 2.3, uitgebracht als onderdeel van Java EE 8 in 2017. Oracle's (nu Eclipse's) Mojarra is de JSF-referentie-implementatie, en MyFaces en PrimeFaces zijn populaire implementaties van derden.

Elk van deze frameworks implementeert de JSF-kern, die enkele standaardcomponenten bevat. Leveranciers kunnen naast de standaard ook aanvullende componentbibliotheken aanbieden. Bij het evalueren van JSF-frameworks is het een goed idee om na te denken over de behoeften van uw applicatie en welke componentbibliotheken beschikbaar zijn om u te helpen deze te bouwen. Idealiter zou uw JSF-framework u zo dicht mogelijk bij wat u nodig heeft, direct uit de doos moeten brengen.

MVC in JSF 2.3

JSF is een MVC-framework dat het model-view-controller-patroon implementeert. In het MVC-patroon is het de bedoeling om de drie zorgen van een gebruikersinterface op te splitsen in discrete delen, zodat ze gemakkelijker te beheren zijn. Over het algemeen is de weergave verantwoordelijk voor het weergeven van gegevens in het model en is de controller verantwoordelijk voor het opzetten van het model en het routeren van de gebruiker naar de juiste weergave.

In een JSF-implementatie is de weergave de Facelets-pagina met zijn set XML-tags. Deze bepalen de lay-out van de gebruikersinterface. De andere helft van het gebruik van JSF is de serverkant, waar Java die UI-componenten ondersteunt.

Beheerde bonen verouderd in JSF 2.3

Beheerde bean-annotaties zijn verouderd in JSF 2.3 en vervangen door CDI (Contexts and Dependency Injection). Met CDI definiëren ontwikkelaars een context en injecteren ze objecten in die context. Degenen die bekend zijn met beheerde bonen zullen de annotatiesyntaxis iets anders vinden, maar de semantiek blijft precies hetzelfde.

Controller bonen

In JSF 2.3 vormen controllerbeans het controller- gedeelte van de MVC-vergelijking. Normale Java-objecten (vaak POJO's of gewone oude Java-objecten genoemd) vormen het model.

In termen van processtroom, controllerbeans:

  1. Bepaal waar u gebruikersverzoeken naartoe wilt sturen
  2. Stel POJO's in voor het model
  3. Gebruik het model om de Facelets-weergave te renderen

JSF vouwt vervolgens de componentenboom en het model samen om de uitvoer-HTML weer te geven.

Listing 2 laat zien hoe u het javaBeanobject uit Listing 1 zou definiëren met behulp van CDI. Deze lijst gaat ervan uit dat de applicatie de cdi-api-1.2.jar in zijn afhankelijkheden heeft.

Listing 2. Een JavaBean gedefinieerd met behulp van CDI

 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 met PrimeFaces

In de volgende secties zal ik PrimeFaces gebruiken om u te laten zien hoe JSF het MVC-patroon, gebeurtenisgestuurde berichten en herbruikbare componenten implementeert. Om te beginnen, opent u de PrimeFaces Showcase, klikt u op de gegevenskoppeling in de linkerkolom en selecteert u Gegevenslijst . Dit zal de DataList-democode voor PrimeFaces oproepen.

In afbeelding 1 ziet u waar u deze voorbeelden kunt vinden.

Matthew Tyson

Figuur 2 toont de uitvoer van een eenvoudige gegevenstabel, die is overgenomen uit de PrimeFaces DataList-demo.

Matthew Tyson

PrimeFaces DataList: toegang tot het datamodel

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.

Merk vervolgens op dat de CarServiceeigenschap de @Injectannotatie heeft (de @ManagedPropertyprior genoemd naar JSF 2.3). Dit is een andere JSF-functie waarmee bonen 'met elkaar kunnen worden verbonden', een techniek die gepopulariseerd is door het Spring-raamwerk en andere hulpmiddelen voor het injecteren van afhankelijkheden. In wezen zal JSF het carServiceobject binnen het bereik zoeken en het automatisch koppelen aan het serviceveld op het DataListViewobject.