Co to jest JSF? Przedstawiamy JavaServer Faces

JavaServer Faces (JSF) to standardowa technologia Java do tworzenia opartych na komponentach, zorientowanych na zdarzenia interfejsów internetowych. Podobnie jak JavaServer Pages (JSP), JSF umożliwia dostęp do danych i logiki po stronie serwera. W przeciwieństwie do JSP, która jest zasadniczo stroną HTML nasyconą możliwościami po stronie serwera, JSF jest dokumentem XML, który reprezentuje formalne komponenty w drzewie logicznym. Komponenty JSF są obsługiwane przez obiekty Java, które są niezależne od HTML i mają pełen zakres możliwości Java, w tym dostęp do zdalnych interfejsów API i baz danych.

Kluczową ideą struktury takiej jak JSF jest hermetyzacja (lub opakowanie ) technologii po stronie klienta, takich jak HTML, CSS i JavaScript, umożliwiając programistom tworzenie interfejsów internetowych bez zbytniej interakcji z tymi technologiami.

W tym artykule przedstawiono przegląd podejścia JSF do tworzenia interfejsu użytkownika opartego na komponentach dla aplikacji internetowych Java. Proste przykłady przedstawiają architekturę MVC JSF, model zdarzeń i bibliotekę komponentów. Przykłady obejmują nowe funkcje w JSF 2.3 i będziemy używać PrimeFaces dla naszej biblioteki komponentów.

Ewoluujący JSF

Od dawna popularny, JSF ostatnio stanął w obliczu konkurencji ze strony platform internetowych zgodnych z Javą, w tym struktur JavaScript po stronie klienta. Mimo to JavaServer Faces pozostaje standardem języka Java, zwłaszcza w przypadku tworzenia przedsiębiorstw w języku Java na dużą skalę. Specyfikacja JSF zaowocowała również bogactwem ram i bibliotek, które dotrzymały kroku ostatnim ulepszeniom po stronie klienta. Jednym z nich jest PrimeFaces, który omówimy w tym samouczku.

Chociaż harmonogram przyszłego rozwoju jest niejasny, JSF 2.3 daje programistom dużo pracy, gdy czekamy. Wydany w marcu 2017 r. JSF 2.3 został celowo zaprojektowany w celu modernizacji JSF. Wśród kilkuset drobnych napraw i większych aktualizacji, JSF 2.3 wycofuje zarządzane adnotacje bean na rzecz CDI, które przedstawię w dalszej części tego samouczka.

JSF 2.3 w Dżakarcie EE

We wrześniu 2017 r. Firma Oracle ogłosiła zamiar przeniesienia Java EE do Eclipse Foundation. Od tego czasu Java EE została przemianowana na Jakarta EE, a JSF 2.3 (Eclipse Mojarra) została przyjęta do kontynuacji. Następnym głównym wydaniem specyfikacji JSF będzie Eclipse Mojarra 3.0.

Tworzenie interfejsów internetowych opartych na komponentach w JSF

Podstawową ideą JSF jest zamknięcie funkcjonalności w komponentach wielokrotnego użytku. Jest to podobne do znaczników wielokrotnego użytku używanych w JSP, ale komponenty JSF są bardziej formalne.

Chociaż możesz używać stron JSF na stronach JavaServer Pages, częściej używa się funkcji Facelets do tworzenia samodzielnych stron JSF. Facelety to strony XHTML przeznaczone do definiowania interfejsów JSF. W przypadku Facelets znaczniki XML służą do tworzenia drzewa komponentów, które stanie się szkieletem dla interfejsu użytkownika JSF.

Listing 1 przedstawia główne części prostej strony JSF napisanej przy użyciu Facelets. W tym przykładzie uzyskujemy dostęp do możliwości Java po stronie serwera za pośrednictwem komponentu bean, który został umieszczony w zasięgu za pomocą CDI. Później dowiesz się więcej o CDI.

Listing 1. Przykładowa strona JSF

    Hello JavaWorld!   #{javaBean.content}  

Na liście 1 widzimy standardową stronę XHTML. Widok Facelets jest oparty na XHTML. Oprócz przestrzeni nazw XHTML definiuje się i odwołuje do dodatkowej przestrzeni nazw.

hBiblioteka zawiera standardowe komponenty stosowane stron JSF HTML. //xmlns.jcp.org/jsf/htmlBiblioteka definiuje zbiór komponentów JSF, w tym przypadku zbiór wspólnych elementów HTML. Jednym z tych elementów jest element.

Komponenty HTML w JSF

Pod względem składni element Listingu 1 odwołuje się do jsf/htmlbiblioteki z hprefiksem. Następnie odwołuje się do określonego komponentu w bibliotece, którym jest headkomponent.

Component element głowicy HTML. (Cała ta składnia może wydawać się przesadą w tak prostym celu, ale jest ku temu dobry powód, jak wkrótce zobaczysz).

Zagnieżdżanie komponentów

Wewnątrz głowy jest zagnieżdżony standardowy element HTML . Ten element jest dostarczany do komponentu wraz z zagnieżdżonymi w nim elementami potomnymi treści.

W treści dokumentu #{}składnia zawiera wyrażenie JSF . Jest to dokładnie analogiczne do wyrażenia JSP z ${}formatem: umożliwia dostęp do obiektów Java w zakresie i prostych funkcji.

Podstawowy wzorzec dla JSF jest prosty: użyj funkcji Facelets, aby zbudować drzewo XML, które odwołuje się do biblioteki komponentów lub bibliotek, a następnie użyj komponentów w bibliotece do renderowania obiektów Java jako HTML.

Korzystanie z obiektów Java w JSF

Wracając do Listingu 1, zwróć uwagę, że wewnątrz wyrażenia JSF ( ${javaBean.content) javaBeanObiekt znajduje się w zasięgu, gdy ten znacznik jest wykonywany. XHTML Facelets uzyskuje dostęp do .contentwłaściwości javaBeanobiektu. Ostatnim wynikiem jest interfejs sieciowy, który łączy strukturę widoku Facelets z danymi i możliwościami logicznymi języka Java po stronie serwera.

Użycie wyrażenia JSF to tylko jeden ze sposobów uzyskania dostępu do danych aplikacji Java z interfejsu użytkownika JSF. Ostatecznie będziesz chciał zbadać inne sposoby, w jakie komponent JSF może współdziałać z zapleczem Java - rzeczy takie jak listy i siatki danych oraz różne kontrolki wejściowe. Na razie wystarczy przyjrzeć się, jak JSF wykorzystuje znaczniki XML (lub adnotacje) do tworzenia drzewa komponentów, które generują HTML na podstawie danych zawartych w obiektach Java.

Adnotacje a XML

Dzięki JSF 2.3 stało się możliwe definiowanie komponentów JSF z adnotacjami, całkowicie rezygnując z metadanych XML. W pełni można zdefiniować i wdrożyć aplikację JSF bez edytowania kodu XML.

Struktura aplikacji JSF

Podobnie jak JavaServer Pages i Servlet API, JavaServer Faces wymaga standardowej struktury katalogów i metadanych. Są one wdrażane jako pliki .war .

Struktura pliku War jest podobna do aplikacji Servlet lub JSP. Zawiera /web-appkatalog, w którym znajdują się pliki znaczników aplikacji (w tym przypadku HTML, JSP i Facelets), a także /WEB-INFkatalog, w którym prezentowane są metadane opisujące aplikację.

Obsługujemy JSF

Chociaż możesz uruchomić JSF w kontenerze Java EE, takim jak Glassfish, prosty kontener serwletów jest wszystkim, czego naprawdę potrzebujesz. Tomcat to popularny kontener dla JSF i innych technologii Java po stronie serwera.

JSF 2.3: Specyfikacja i implementacje

Jedną z mocnych stron Javy jest to, że jest oparta na standardach, a te standardy są zarządzane przez społeczność open source. Od samego początku Java Community Process (JCP) nadzorowała rozwój technologii Java. Gdy specyfikacja lub ulepszenie specyfikacji zostanie opracowane i zatwierdzone przez JCP, jest dostępne do wdrożenia przez wiele stron. Do niedawna serwlety, JSP i JSF były opracowywane przy użyciu procesu specyfikacji JCP typu open source.

Najnowsza specyfikacja JSF w chwili pisania tego tekstu to JSF 2.3, wydana jako część Java EE 8 w 2017 r. Oracle (obecnie Eclipse) Mojarra jest implementacją referencyjną JSF, a MyFaces i PrimeFaces to popularne implementacje innych firm.

Każdy z tych frameworków implementuje rdzeń JSF, który zawiera pewne standardowe komponenty. Sprzedawcy mogą również oferować dodatkowe biblioteki komponentów poza standardem. Oceniając frameworki JSF, dobrym pomysłem jest rozważenie potrzeb aplikacji i dostępnych bibliotek komponentów, które pomogą Ci ją zbudować. Idealnie byłoby, gdyby twój framework JSF był jak najbliżej tego, czego potrzebujesz, zaraz po wyjęciu z pudełka.

MVC w JSF 2.3

JSF to framework MVC , implementujący wzorzec model-widok-kontroler. We wzorcu MVC chodzi o rozdzielenie trzech problemów interfejsu użytkownika na dyskretne części, aby łatwiej nimi zarządzać. Generalnie widok jest odpowiedzialny za wyświetlanie danych w modelu, a kontroler odpowiada za ustawienie modelu i skierowanie użytkownika do właściwego widoku.

W implementacji JSF widokiem jest strona Facelets z zestawem znaczników XML. Definiują one układ interfejsu użytkownika. Druga połowa korzystania z JSF to strona serwera, gdzie klasy Java wspierają te komponenty interfejsu użytkownika.

Zarządzane komponenty bean są przestarzałe w JSF 2.3

Zarządzane adnotacje bean zostały wycofane w JSF 2.3 i zastąpione przez CDI (Contexts and Dependency Injection). Dzięki CDI programiści definiują kontekst i wstrzykują obiekty do tego kontekstu. Osoby zaznajomione z zarządzanymi fasolami będą miały nieco inną składnię adnotacji, ale semantyka pozostanie dokładnie taka sama.

Fasola kontrolera

W JSF 2.3 komponenty bean kontrolerów udostępniają część równania MVC będącą kontrolerem . Model dostarczają normalne obiekty Java (często nazywane POJO lub zwykłe stare obiekty Java).

Pod względem przebiegu procesu fasola kontrolera:

  1. Zdecyduj, dokąd kierować żądania użytkowników
  2. Skonfiguruj POJO dla modelu
  3. Użyj modelu, aby wyrenderować widok Facelets

JSF następnie składa razem drzewo komponentów i model, aby wyrenderować wyjściowy kod HTML.

Listing 2 pokazuje, jak zdefiniować javaBeanobiekt z Listingu 1 za pomocą CDI. Ta lista zakłada, że ​​aplikacja ma w swoich zależnościach plik cdi-api-1.2.jar.

Listing 2. JavaBean zdefiniowany za pomocą 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 z PrimeFaces

W następnych sekcjach wykorzystam PrimeFaces, aby pokazać, jak JSF implementuje wzorzec MVC, komunikaty sterowane zdarzeniami i komponenty wielokrotnego użytku. Aby rozpocząć, otwórz PrimeFaces Showcase, kliknij łącze Dane w lewej kolumnie i wybierz DataList . Spowoduje to wyświetlenie kodu demonstracyjnego DataList dla PrimeFaces.

Rysunek 1 pokazuje, gdzie znaleźć te próbki.

Matthew Tyson

Rysunek 2 przedstawia dane wyjściowe prostej tabeli danych, które pochodzą z demonstracji PrimeFaces DataList.

Matthew Tyson

PrimeFaces DataList: Dostęp do modelu danych

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.

Następnie zwróć uwagę, że CarServicewłaściwość ma @Injectadnotację (zwaną @ManagedPropertyprzed JSF 2.3). Jest to kolejna funkcja JSF, która umożliwia „łączenie ze sobą” komponentów bean, technika spopularyzowana przez framework Spring i inne narzędzia do iniekcji zależności. Zasadniczo JSF znajdzie carServiceobiekt w zasięgu i automatycznie skojarzy go z servicepolem w DataListViewobiekcie.