Cos'è JSF? Presentazione di JavaServer Faces

JavaServer Faces (JSF) è la tecnologia standard Java per la creazione di interfacce Web basate su componenti e orientate agli eventi. Come JavaServer Pages (JSP), JSF consente l'accesso ai dati e alla logica lato server. A differenza di JSP, che è essenzialmente una pagina HTML imbevuta di funzionalità lato server, JSF è un documento XML che rappresenta componenti formali in un albero logico. I componenti JSF sono supportati da oggetti Java, che sono indipendenti dall'HTML e hanno l'intera gamma di capacità Java, incluso l'accesso ad API e database remoti.

L'idea chiave di un framework come JSF è incapsulare (o avvolgere ) tecnologie lato client come HTML, CSS e JavaScript, consentendo agli sviluppatori di creare interfacce web senza molta interazione con queste tecnologie.

Questo articolo presenta un'istantanea dell'approccio di JSF allo sviluppo dell'interfaccia utente basata su componenti per applicazioni Web Java. Semplici esempi introducono l'architettura MVC, il modello di eventi e la libreria dei componenti di JSF. Gli esempi includono nuove funzionalità in JSF 2.3 e useremo PrimeFaces per la nostra libreria di componenti.

JSF in evoluzione

Molto popolare, JSF ha recentemente affrontato la concorrenza dei framework Web compatibili con Java, inclusi i framework JavaScript lato client. Tuttavia, JavaServer Faces rimane lo standard Java, soprattutto per lo sviluppo aziendale Java su larga scala. La specifica JSF ha anche generato una vasta gamma di framework e librerie, che hanno tenuto il passo con i recenti miglioramenti lato client. Uno di questi è PrimeFaces, che esploriamo in questo tutorial.

Sebbene il programma per lo sviluppo futuro non sia chiaro, JSF 2.3 offre agli sviluppatori molto con cui lavorare mentre aspettiamo. Rilasciato a marzo 2017, JSF 2.3 è stato intenzionalmente progettato per modernizzare JSF. Tra diverse centinaia di piccole riparazioni e aggiornamenti più grandi, JSF 2.3 depreca le annotazioni dei bean gestiti a favore di CDI, che introdurrò più avanti in questo tutorial.

JSF 2.3 a Jakarta EE

Nel settembre 2017, Oracle ha annunciato la sua intenzione di trasferire Java EE alla Eclipse Foundation. Da allora Java EE è stato rinominato Jakarta EE, e JSF 2.3 (Eclipse Mojarra) è stato adottato per la continuazione. La prossima versione principale della specifica JSF sarà Eclipse Mojarra 3.0.

Creazione di interfacce web basate su componenti in JSF

L'idea centrale di JSF è incapsulare la funzionalità in componenti riutilizzabili. È simile ai tag riutilizzabili utilizzati in JSP, ma i componenti JSF sono più formali.

Sebbene sia possibile utilizzare pagine JSF all'interno di JavaServer Pages, è più comune utilizzare Facelets per creare pagine JSF autonome. I facelets sono pagine XHTML progettate per definire le interfacce JSF. Con Facelets, si utilizzano tag XML per creare un albero dei componenti che diventa lo scaffold per un'interfaccia utente JSF.

Il Listato 1 presenta le parti principali di una semplice pagina JSF scritta utilizzando Facelets. In questo esempio accediamo alle funzionalità lato server di Java tramite un bean che è stato inserito nell'ambito tramite CDI. Più avanti vedrai di più su CDI.

Listato 1. Pagina di esempio JSF

    Hello JavaWorld!   #{javaBean.content}  

Nel Listato 1 vediamo una pagina XHTML standard. Una vista Facelets è costruita sopra XHTML. Oltre allo spazio dei nomi XHTML, viene definito e referenziato uno spazio dei nomi secondario.

La hlibreria contiene componenti standard da utilizzare nelle pagine HTML JSF. La //xmlns.jcp.org/jsf/htmllibreria definisce una raccolta di componenti JSF, in questo caso una raccolta di elementi HTML comuni. Uno di questi componenti è l' elemento.

Componenti HTML in JSF

In termini di sintassi, l' elemento del Listato 1 fa riferimento alla jsf/htmllibreria con il hprefisso. Quindi fa riferimento al componente specifico all'interno della libreria, che è il headcomponente.

Il componente restituisce l'elemento HTML head. (Tutta quella sintassi potrebbe sembrare eccessiva per uno scopo così semplice, ma c'è una buona ragione, come vedrai tra poco.)

Componenti di nesting

All'interno della testa è annidato un elemento HTML standard . Questo elemento viene fornito al componente, insieme agli elementi figlio del contenuto annidati al suo interno.

Nel corpo del documento, un'espressione JSF è contenuta dalla #{}sintassi. Questo è esattamente analogo a un'espressione JSP con il ${}formato: consente l'accesso a oggetti Java nell'ambito e funzioni semplici.

Il modello di base per JSF è semplice: utilizzare Facelets per creare un albero XML che fa riferimento a una o più librerie di componenti, quindi utilizzare i componenti all'interno della libreria per eseguire il rendering di oggetti Java come HTML.

Utilizzo di oggetti Java in JSF

Tornando al Listato 1, si noti che all'interno dell'espressione JSF ( ${javaBean.content) L' javaBeanoggetto è nell'ambito quando viene eseguito questo markup. L'XHTML di Facelets accede alla .contentproprietà javaBeansull'oggetto. L'output finale è un'interfaccia web che unisce la struttura della vista Facelets con i dati lato server e le capacità logiche di Java.

L'utilizzo di un'espressione JSF è solo un modo per accedere ai dati dell'applicazione Java da un'interfaccia utente JSF. Alla fine, vorrai esplorare altri modi in cui un componente JSF può interagire con il backend Java, cose come elenchi di dati e griglie e una varietà di controlli di input. Per ora, è sufficiente comprendere come JSF utilizza i tag XML (o annotazioni) per creare un albero di componenti che restituisce HTML in base ai dati contenuti negli oggetti Java.

Annotazioni vs XML

Con JSF 2.3 è diventato possibile definire componenti JSF con annotazioni, evitando completamente i metadati XML. È completamente possibile definire e distribuire un'app JSF senza modificare alcun XML.

Struttura di un'applicazione JSF

Come JavaServer Pages e Servlet API, JavaServer Faces richiede una struttura di directory e metadati standard. Questi vengono distribuiti come file .war .

La struttura di un file .war è simile a un'applicazione Servlet o JSP. Contiene una /web-appdirectory, che contiene i file di markup dell'applicazione (in questo caso HTML, JSP e Facelets), nonché una /WEB-INFdirectory, che presenta i metadati per descrivere l'applicazione.

Servire JSF

Sebbene sia possibile eseguire JSF in un contenitore Java EE come Glassfish, un semplice contenitore servlet è tutto ciò di cui hai veramente bisogno. Tomcat è un popolare contenitore per JSF e altre tecnologie Java lato server.

JSF 2.3: Specifiche e implementazioni

Uno dei punti di forza di Java è che è basato su standard e tali standard sono governati da un processo comunitario open source. Fin dal suo inizio, il Java Community Process (JCP) ha supervisionato lo sviluppo della tecnologia Java. Una volta che una specifica o un miglioramento della specifica è stato sviluppato e approvato da JCP, è disponibile per essere implementato da più parti. Fino a poco tempo, Servlet, JSP e JSF erano tutti sviluppati utilizzando il processo di specifica open source di JCP.

La specifica JSF più recente al momento della stesura di questo documento è JSF 2.3, rilasciata come parte di Java EE 8 nel 2017. Mojarra di Oracle (ora Eclipse) è l'implementazione di riferimento JSF e MyFaces e PrimeFaces sono popolari implementazioni di terze parti.

Ciascuno di questi framework implementa il core JSF, che include alcuni componenti standard. I fornitori possono anche offrire librerie di componenti aggiuntive oltre allo standard. Quando si valutano i framework JSF, è una buona idea considerare le esigenze della propria applicazione e quali librerie di componenti sono disponibili per aiutarvi a costruirla. Idealmente, il tuo framework JSF dovrebbe portarti il ​​più vicino possibile a ciò di cui hai bisogno, fin da subito.

MVC in JSF 2.3

JSF è un framework MVC , che implementa il pattern model-view-controller. Nel pattern MVC, l'idea è di separare le tre preoccupazioni di un'interfaccia utente in parti discrete, in modo che siano più facili da gestire. In generale, la visualizzazione è responsabile della visualizzazione dei dati nel modello e il controller è responsabile della configurazione del modello e del routing dell'utente alla visualizzazione corretta.

In un'implementazione JSF, la vista è la pagina Facelets con il suo insieme di tag XML. Questi definiscono il layout dell'interfaccia utente. L'altra metà dell'utilizzo di JSF è il lato server, dove le classi Java supportano quei componenti dell'interfaccia utente.

Bean gestiti deprecati in JSF 2.3

Le annotazioni dei bean gestiti sono state deprecate in JSF 2.3 e sostituite da CDI (Contexts and Dependency Injection). Con CDI, gli sviluppatori definiscono un contesto e inseriscono oggetti in quel contesto. Chi ha familiarità con i bean gestiti troverà la sintassi dell'annotazione leggermente diversa, ma la semantica rimane esattamente la stessa.

Fagioli controller

In JSF 2.3, i bean controller forniscono la parte controller dell'equazione MVC. I normali oggetti Java (spesso chiamati POJO o semplici vecchi oggetti Java) forniscono il modello.

In termini di flusso di processo, i bean del controller:

  1. Decidi dove indirizzare le richieste degli utenti
  2. Imposta POJO per il modello
  3. Utilizzare il modello per eseguire il rendering della vista Facelets

JSF quindi piega insieme l'albero dei componenti e il modello per eseguire il rendering dell'HTML di output.

Il Listato 2 mostra come definire l' javaBeanoggetto del Listato 1 utilizzando CDI. Questo elenco presuppone che l'applicazione abbia cdi-api-1.2.jar nelle sue dipendenze.

Listato 2. Un JavaBean definito utilizzando 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 con PrimeFaces

Nelle prossime sezioni userò PrimeFaces per mostrarti come JSF implementa il pattern MVC, la messaggistica basata sugli eventi e i componenti riutilizzabili. Per iniziare, apri PrimeFaces Showcase, fai clic sul collegamento Dati nella colonna di sinistra e seleziona DataList . Questo farà apparire il codice demo DataList per PrimeFaces.

La figura 1 mostra dove trovare questi campioni.

Matthew Tyson

La Figura 2 mostra l'output di una semplice tabella di dati, che è presa dalla demo PrimeFaces DataList.

Matthew Tyson

PrimeFaces DataList: accesso al modello di dati

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.

Successivamente, osserva che la CarServiceproprietà ha l' @Injectannotazione (chiamata @ManagedPropertyprecedente a JSF 2.3). Questa è un'altra funzionalità JSF che consente ai bean di essere "cablati insieme", una tecnica resa popolare dal framework Spring e da altri strumenti di inserimento delle dipendenze. In sostanza, JSF troverà l' carServiceoggetto nell'ambito e lo assocerà automaticamente al servicecampo DataListViewsull'oggetto.