Príklad ovládača, služby a DAO s Spring Boot a JSF

1. Úvod

JavaServer Faces je rámec užívateľského rozhrania na strane servera. Pôvodne bol vyvinutý ako súčasť Jakarta EE. V tomto návode preskúmame, ako integrovať JSF do aplikácie Spring Boot.

Ako príklad implementujeme jednoduchú aplikáciu na vytvorenie zoznamu TO-DO.

2. Maven závislosti

Musíme predĺžiť naše pom.xml používať technológie JSF:

 org.apache.tomcat.embed tomcat-embed-jasper org.glassfish javax.faces 2.3.7 

The javax.faces artefakt obsahuje API JSF a tiež implementácie. Podrobné informácie nájdete tu.

3. Konfigurácia servletu JSF

Rámec JSF používa súbory XHTML na opis obsahu a štruktúry používateľského rozhrania. Strana servera generuje súbory JSF z popisov XHTML.

Začnime vytvorením statickej štruktúry v index.xhtml súbor v src / main / webapp adresár:

    Aplikácia TO-DO 

Vitajte v aplikácii TO-DO!

Toto je statická správa vykreslená z xhtml.

Obsah bude k dispozícii na adrese /index.jsf. Ak sa však v tejto fáze pokúsime dostať k obsahu, na strane klienta sa zobrazí chybové hlásenie:

Vyskytla sa neočakávaná chyba (typ = Nenašiel sa, stav = 404). Nie je k dispozícii žiadna správa

Nebude chýbať žiadna backendová chybová správa. Aj tak môžeme prísť na to na vybavenie žiadosti potrebujeme servlet JSF a mapovanie servletu tak, aby zodpovedalo požiadavke so spracovateľom.

Pretože sme v Spring Boot, môžeme našu triedu aplikácií ľahko rozšíriť tak, aby zvládla požadovanú konfiguráciu:

@SpringBootApplication verejná trieda JsfApplication rozširuje SpringBootServletInitializer {public static void main (String [] args) {SpringApplication.run (JsfApplication.class, args); } @Bean public ServletRegistrationBean servletRegistrationBean () {servlet FacesServlet = nový FacesServlet (); ServletRegistrationBean servletRegistrationBean = nový ServletRegistrationBean (servlet, "* .jsf"); návrat servletRegistrationBean; }}

Vyzerá to skvele a dosť rozumne, ale bohužiaľ stále nie dosť dobre. Keď sa pokúsime otvoriť /index.jsf teraz dostaneme ďalšiu chybu:

java.lang.IllegalStateException: Nepodarilo sa nájsť zálohu pre továrenské javax.faces.context.FacesContextFactory.

Bohužiaľ potrebujeme web.xml okrem konfigurácie Java. Vytvorme to v src / webapp / WEB-INF:

 Servlet Faces javax.faces.webapp.FacesServlet 1 Servlet Faces * .jsf 

Teraz je naša konfigurácia pripravená na použitie. Otvorené /index.jsf:

Vitajte v aplikácii TO-DO! Toto je statická správa vykreslená z xhtml.

Predtým, ako vytvoríme naše užívateľské rozhranie, vytvorme si backend aplikácie.

4. Implementácia vzoru DAO

DAO je skratka pre objekt prístupu k údajom. Trieda DAO je zvyčajne zodpovedná za dva koncepty. Zapuzdrenie detailov vrstvy perzistencie a poskytnutie rozhrania CRUD pre jednu entitu. Podrobný popis nájdete v tomto návode.

Ak chcete implementovať vzor DAO, najskôr definujeme všeobecné rozhranie:

verejné rozhranie Dao {Voliteľné get (int id); Zbierka getAll (); int save (T t); aktualizácia neplatnosti (T t); neplatné mazanie (T t); }

Teraz vytvorme našu prvú a jedinú triedu domény v tejto úlohovej aplikácii:

public class Todo {private int id; súkromná reťazcová správa; priorita súkromného int; // štandardné getre a setre}

Ďalšou triedou bude implementácia Dao. Krása tohto vzoru je, že môžeme kedykoľvek poskytnúť novú implementáciu tohto rozhrania.

V dôsledku toho môžeme zmeniť vrstvu perzistencie bez toho, aby sme sa dotkli zvyšku kódu.

Pre náš príklad použijeme triedu ukladania v pamäti:

@ Verejná trieda komponentu TodoDao implementuje Dao {private List todoList = new ArrayList (); @Override public Voliteľné get (int id) {návrat Optional.ofNullable (todoList.get (id)); } @Override public Collection getAll () {return todoList.stream () .filter (Objects :: nonNull) .collect (Collectors.collectingAndThen (Collectors.toList (), Collections :: unmodifiableList)); } @Override public int save (Todo todo) {todoList.add (todo); int index = todoList.size () - 1; todo.setId (index); index návratnosti; } @Override public void update (Todo todo) {todoList.set (todo.getId (), todo); } @Override public void delete (Todo todo) {todoList.set (todo.getId (), null); }}

5. Servisná vrstva

Hlavným cieľom vrstvy DAO je zvládnuť podrobnosti mechanizmu perzistencie. Zatiaľ čo vrstva služieb stojí na jej vrchole pri zvládaní obchodných požiadaviek.

Všimnite si, že na rozhranie DAO sa bude odkazovať zo služby:

@Scope (value = "session") @Component (value = "todoService") verejná trieda TodoService {@Autowired private Dao todoDao; súkromné ​​Todo todo = nové Todo (); public void save () {todoDao.save (todo); todo = nové Todo (); } verejná zbierka getAllTodo () {return todoDao.getAll (); } public int saveTodo (Todo todo) {validate (todo); vrátiť todoDao.save (todo); } private void validate (Todo todo) {// Vynechané podrobnosti} public Todo getTodo () {return todo; }}

Tu je služba pomenovaným komponentom. Názov použijeme na odkazovanie na fazuľa z kontextu JSF.

Táto trieda má tiež rozsah relácie, ktorý bude pre túto jednoduchú aplikáciu vyhovujúci.

Viac informácií o jarných oboroch nájdete v tomto výučbe. Pretože vstavané rozsahy Spring majú iný model ako JSF, stojí za to zvážiť definovanie vlastného rozsahu.

Ďalšie pokyny k tomu sú uvedené v tomto výučbe.

6. Prevádzkovateľ

Rovnako ako v aplikácii JSP bude ovládač ovládať navigáciu medzi rôznymi zobrazeniami.

Ďalej implementujeme minimalistický radič. Bude navigovať z úvodnej stránky na stránku so zoznamom úloh:

@Scope (value = "session") @Component (value = "jsfController") verejná trieda JsfController {public String loadTodoPage () {checkPermission (); vrátiť "/todo.xhtml"; } private void checkPermission () {// Podrobnosti vynechané}}

Navigácia je založená na vrátenom mene. Preto loadTodoPage pošle nás na todo.xhtml stránku, ktorú budeme implementovať ďalej.

7. Pripojenie JSF a jarných bôbov

Pozrime sa, ako môžeme odkazovať na naše komponenty z kontextu JSF. Najskôr predĺžime index.xthml:

  // rovnaký kód ako predtým // rovnaký kód ako predtým 

Tu sme predstavili a príkazové tlačidlo vo vnútri tvarového prvku. To je dôležité, pretože každý UICommand prvok (napr. commandButton)musí byť umiestnený vo vnútri a UIForm prvok (napr. forma).

V tejto fáze môžeme spustiť našu aplikáciu a preskúmať ju /index.jsf:

Po kliknutí na tlačidlo sa nám bohužiaľ zobrazí chyba:

Vyskytla sa neočakávaná chyba (typ = Interná chyba servera, stav = 500). javax.el.PropertyNotFoundException: /index.xhtml @ 11,104 action = "# {jsfController.loadTodoPage}": Cieľ je nedosiahnuteľný, identifikátor [jsfController] bol vyriešený na hodnotu null

Správa jasne uvádza problém: jsfController rozhodnutý pre nulový. Zodpovedajúci komponent buď nebol vytvorený, alebo aspoň je neviditeľný z kontextu JSF.

V tejto situácii je to pravda druhá.

Musíme spojiť jarný kontext s JSF kontexte v rámci webapp / WEB-INF / face-config.xml:

   org.springframework.web.jsf.el.SpringBeanFacesELResolver 

Teraz, keď je náš radič pripravený na prácu, budeme potrebovať todo.xhtml!

8. Interakcia so službou od spoločnosti JSF

Náš todo.xhtml stránka bude mať dva účely. Najskôr zobrazí všetky prvky úloh.

Po druhé, ponúknite možnosť pridať do zoznamu nové prvky.

Z tohto dôvodu bude komponent používateľského rozhrania priamo interagovať so službou deklarovanou skôr:

    Aplikácia TO-DO Zoznam položiek TO-DO Správa # {item.message} Priorita # {item.priority} Pridať novú položku úloh: 

Vyššie uvedené dva účely sú implementované v dvoch samostatných div prvkov.

V prvom sme použili a údajová tabuľka prvok, ktorý predstavuje všetky hodnoty z todoService.AllTodo.

Druhy div obsahuje formulár, kde môžeme upraviť stav súboru Robiť objekt v TodoService.

Používame inputText prvok na prijatie vstupu používateľa, kde sa druhý vstup automaticky prevedie na int. Vďaka príkazové tlačidlo, užívateľ môže pretrvávať (do pamäte teraz) Robiť objekt s todoService.save.

9. Záver

Rámec JSF možno integrovať do jarného rámca. Musíte si vybrať, ktorý framework bude spravovať fazuľa. V tomto tutoriáli sme použili jarný framework.

Model rozsahu je však trochu iný ako rámec JSF. Môžete teda zvážiť definovanie vlastných rozsahov v jarnom kontexte.

Ako vždy, kód je k dispozícii na GitHub.