Vad är JSF? Introduktion till JavaServer Faces

JavaServer Faces (JSF) är Java-standardtekniken för att bygga komponentbaserade, händelserienterade webbgränssnitt. Precis som JavaServer Pages (JSP), tillåter JSF åtkomst till serversidan och logik. Till skillnad från JSP, som i huvudsak är en HTML-sida genomsyrad av serverns funktioner, är JSF ett XML-dokument som representerar formella komponenter i ett logiskt träd. JSF-komponenter stöds av Java-objekt, som är oberoende av HTML och har hela utbudet av Java-funktioner, inklusive åtkomst till fjärr-API: er och databaser.

Nyckelidén till ett ramverk som JSF är att inkapsla (eller slå in ) klientteknologier som HTML, CSS och JavaScript, så att utvecklare kan bygga webbgränssnitt utan mycket interaktion med dessa tekniker.

Denna artikel presenterar en ögonblicksbild av JSFs strategi för komponentbaserad UI-utveckling för Java-webbapplikationer. Enkla exempel introducerar JSFs MVC-arkitektur, händelsemodell och komponentbibliotek. Exempel inkluderar nya funktioner i JSF 2.3, och vi använder PrimeFaces för vårt komponentbibliotek.

JSF utvecklas

Långt populärt har JSF nyligen mött konkurrens från Java-kompatibla webbramar, inklusive JavaScript-ramar på klientsidan. Ändå förblir JavaServer Faces Java-standarden, särskilt för storskalig Java-företagsutveckling. JSF-specifikationen har också skapat en mängd ramar och bibliotek, som har hållit jämna steg med de senaste förbättringarna på klientsidan. En av dessa är PrimeFaces, som vi utforskar i denna handledning.

Medan schemat för framtida utveckling är oklart, ger JSF 2.3 utvecklare mycket att arbeta med medan vi väntar. Släpptes i mars 2017, JSF 2.3 var avsiktligt utformad för att modernisera JSF. Bland flera hundra små reparationer och större uppdateringar avskaffar JSF 2.3 hanterade bönanoteringar till förmån för CDI, som jag kommer att presentera senare i denna handledning.

JSF 2.3 i Jakarta EE

I september 2017 tillkännagav Oracle sin avsikt att överföra Java EE till Eclipse Foundation. Java EE har sedan dess omarbetats till Jakarta EE, och JSF 2.3 (Eclipse Mojarra) har antagits för fortsättning. Nästa stora utgåva av JSF-specifikationen kommer att vara Eclipse Mojarra 3.0.

Bygga komponentbaserade webbgränssnitt i JSF

JSFs kärnidé är att inkapsla funktionalitet i återanvändbara komponenter. Detta liknar de återanvändbara taggar som används i JSP, men JSF-komponenter är mer formella.

Medan du kan använda JSF-sidor inom JavaServer-sidor är det vanligare att använda Facelets för att bygga fristående JSF-sidor. Facelets är XHTML-sidor utformade för att definiera JSF-gränssnitt. Med Facelets använder du XML-taggar för att skapa ett komponentträd som blir byggnadsställning för ett JSF-användargränssnitt.

Listning 1 presenterar huvuddelarna på en enkel JSF-sida skriven med Facelets. I det här exemplet kommer vi åt Java-serverns funktioner via en böna som har placerats i omfattning via CDI. Du kommer att se mer om CDI senare.

Listning 1. Exempel på JSF

    Hello JavaWorld!   #{javaBean.content}  

I Listing 1 ser vi en vanlig XHTML-sida. En Facelets-vy är byggd ovanpå XHTML. Förutom XHTML-namnområdet definieras och refereras till ett sekundärt namnområde.

I hbiblioteket finns standardkomponenter för användning i JSF HTML-sidor. Den //xmlns.jcp.org/jsf/htmlbibliotek definierar en samling av JSF-komponenter, i detta fall en samling av vanliga HTML-element. En av dessa komponenter är elementet.

HTML-komponenter i JSF

När det gäller syntax hänvisar Listing 1- element till jsf/htmlbiblioteket med hprefixet. Den refererar sedan till den specifika komponenten i biblioteket, som är headkomponenten.

Den komponent matar ut HTML-huvudelementet. (All den syntaxen kan tyckas vara överdriven för ett så enkelt ändamål, men det finns goda skäl för det, som du ser snart.)

Häckande komponenter

Inuti huvudet är kapslat ett standard HTML- element. Detta element tillhandahålls till komponenten, tillsammans med innehållet underordnade element inuti den.

I dokumentets kropp innehåller ett JSF-uttryck #{}syntaxen. Detta är exakt analogt med ett JSP-uttryck med ${}formatet: det tillåter åtkomst till Java-objekt i omfattning och enkla funktioner.

Grundmönstret för JSF är enkelt: Använd Facelets för att bygga ett XML-träd som refererar till ett komponentbibliotek eller bibliotek och använd sedan komponenter i biblioteket för att göra Java-objekt som HTML.

Använda Java-objekt i JSF

Återgå till Listing 1, notera att inuti JSF-uttrycket ( ${javaBean.content) javaBeanObjektet är i omfång när den här markeringen körs. XHTML of Facelets får åtkomst till .contentfastigheten på javaBeanobjektet. Den slutliga utgången är ett webbgränssnitt som sammanfogar Facelets-visningsstrukturen med Javas data- och logikfunktioner på serversidan.

Att använda ett JSF-uttryck är bara ett sätt att komma åt Java-applikationsdata från ett JSF-användargränssnitt. Så småningom vill du utforska andra sätt som en JSF-komponent kan interagera med Java-backend - saker som datalistor och rutnät och en mängd olika ingångskontroller. För närvarande räcker det att absorbera hur JSF använder XML-taggar (eller anteckningar) för att skapa ett träd av komponenter som matar ut HTML baserat på data som finns i Java-objekt.

Kommentarer mot XML

Med JSF 2.3 har det blivit möjligt att definiera JSF-komponenter med anteckningar, och helt undvika XML-metadata. Det är fullt möjligt att definiera och distribuera en JSF-app utan att redigera någon XML.

Strukturen för en JSF-applikation

Precis som JavaServer Pages och Servlet API kräver JavaServer Faces en standardkatalogstruktur och metadata. Dessa distribueras som .war- filer.

Strukturen för en .war-fil liknar ett Servlet- eller JSP-program. Den innehåller en /web-appkatalog som innehåller programmets markeringsfiler (i detta fall HTML, JSP och Facelets), samt en /WEB-INFkatalog som presenterar metadata för att beskriva applikationen.

Serverar JSF

Medan du kan köra JSF i en Java EE-behållare som Glassfish, är en enkel servletbehållare allt du verkligen behöver. Tomcat är en populär behållare för JSF och andra Java-tekniker på serversidan.

JSF 2.3: Specifikationer och implementeringar

En av Java: s styrkor är att det är standardbaserat, och dessa standarder styrs av en öppen källkodsprocess. Sedan starten har Java Community Process (JCP) övervakat utvecklingen av Java-teknik. När en specifikation eller specifikationsförbättring har utvecklats och godkänts av JCP är den tillgänglig att implementeras av flera parter. Fram till nyligen utvecklades Servlets, JSP och JSF med JCP: s open source-specifikationsprocess.

The most recent JSF specification as of this writing is JSF 2.3, released as part of Java EE 8 in 2017. Oracle's (now Eclipse's) Mojarra is the JSF reference implementation, and MyFaces and PrimeFaces are popular third-party implementations.

Each of these frameworks implements the JSF core, which includes some standard components. Vendors may also offer additional component libraries on top of the standard. When evaluating JSF frameworks, it's a good idea to consider the needs of your application and what component libraries are available to help you build it. Ideally, your JSF framework should get you as close as possible to what you need, right out of the box.

MVC in JSF 2.3

JSF is an MVC framework, implementing the model-view-controller pattern. In the MVC pattern, the idea is to separate the three concerns of a UI into discreet parts, so they're easier to manage. In general, the view is responsible for displaying data in the model, and the controller is responsible for setting up the model and routing the user to the correct view.

In a JSF implementation, the view is the Facelets page with its set of XML tags. These define the layout of the user interface. The other half of using JSF is the server-side, where Java classes back those UI components.

Managed beans deprecated in JSF 2.3

Managed bean annotations have been deprecated in JSF 2.3, and replaced by CDI (Contexts and Dependency Injection). With CDI, developers define a context and inject objects to that context. Those familiar with managed beans will find the annotation syntax slightly different, but the semantics remain exactly the same.

Controller beans

In JSF 2.3, controller beans provide the controller part of the MVC equation. Normal Java objects (often called POJOs, or plain old Java objects) provide the model.

In terms of process flow, controller beans:

  1. Decide where to direct user requests
  2. Set up POJOs for the model
  3. Use the model to render the Facelets view

JSF then folds together the component tree and model to render the output HTML.

Listning 2 visar hur du skulle definiera javaBeanobjektet från Listing 1 med CDI. Den här listan förutsätter att applikationen har cdi-api-1.2.jar i sina beroenden.

Listing 2. En JavaBean definierad med 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 med PrimeFaces

I nästa avsnitt använder jag PrimeFaces för att visa dig hur JSF implementerar MVC-mönstret, händelsestyrda meddelanden och återanvändbara komponenter. För att starta öppnar du PrimeFaces Showcase, klickar på länken Data i vänster kolumn och väljer DataList . Detta kommer att dra upp DataList-demokoden för PrimeFaces.

Figur 1 visar var du hittar dessa prover.

Matthew Tyson

Figur 2 visar utdata från en enkel datatabell, som är hämtad från PrimeFaces DataList-demo.

Matthew Tyson

PrimeFaces DataList: Åtkomst till datamodellen

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.

Observera därefter att CarServicefastigheten har @Injectanteckningen (kallad @ManagedPropertyföre JSF 2.3). Detta är en annan JSF-funktion som gör att bönor kan "kopplas ihop", en teknik som populariseras av Spring-ramverket och andra verktyg för beroende av injektion. I huvudsak hittar JSF carServiceobjektet i omfång och associerar det automatiskt till servicefältet på DataListViewobjektet.