Izgradnja web aplikacije s Spring Boot i Angular

1. Pregled

Spring Boot i Angular čine snažni tandem koji izvrsno funkcionira za razvoj web aplikacija s minimalnim otiskom.

U ovom vodiču, koristit ćemo Spring Boot za implementaciju RESTful pozadine, a Angular za izradu sučelja temeljenog na JavaScript-u.

2. Proljetna aplikacija za pokretanje

Funkcionalnost naše demo web aplikacije bit će doista pojednostavljena. Bit će samo suženo na dohvaćanje i prikazivanje a Popis JPA entiteta iz H2 baze podataka u memoriji i zadržavanje novih putem običnog HTML obrasca.

2.1. Ovisnosti Mavena

Evo ovisnosti našeg projekta Spring Boot:

 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 runtime 

Primijetite da smo uključili proljeće-boot-starter-web jer ćemo ga koristiti za stvaranje REST usluge, i opruga-čizma-starter-jpa za primjenu sloja postojanosti.

Verzijom baze podataka H2 također upravlja roditelj Spring Boot.

2.2. Klasa JPA entiteta

Da bismo brzo prototipirali sloj domene naše aplikacije, definirajmo jednostavnu klasu JPA entiteta koja će biti odgovorna za modeliranje korisnika:

@Entity javni razred korisnika {@Id @GeneratedValue (strategy = GenerationType.AUTO) private long id; privatni konačni naziv niza; privatna završna adresa e-pošte; // standardni konstruktori / postavljači / getteri / toString} 

2.3. The UserRepository Sučelje

Budući da će nam trebati osnovna CRUD funkcionalnost na Korisnik entiteti, također moramo definirati a UserRepository sučelje:

Javno sučelje @Repository UserRepository proširuje CrudRepository {} 

2.4. OSTALI kontroler

Sada, implementiramo REST API. U ovom slučaju to je samo jednostavan REST kontroler.

@RestController @CrossOrigin (poreklo = "// localhost: 4200") javna klasa UserController {// standardni konstruktori private final UserRepository userRepository; @GetMapping ("/ users") javni popis getUsers () {return (Popis) userRepository.findAll (); } @PostMapping ("/ users") void addUser (@RequestBody User user) {userRepository.save (user); }} 

U definiciji ne postoji ništa suštinski složeno UserController razred.

Naravno, ovdje je jedini detalj provedbe vrijedan pažnje korištenje @CrossOrigin bilješka. Kao što naziv implicira, napomena omogućuje međusobno dijeljenje resursa (CORS) na poslužitelju.

Ovaj korak nije uvijek potreban. Budući da postavljamo našu kutnu fronte to // localhost: 4200 i naš Boot backkend za // localhost: 8080, preglednik bi inače odbijao zahtjeve jednih drugima.

Što se tiče metoda kontrolera, getUser () dohvaća sve Korisnik entiteti iz baze podataka. Slično tome, addUser () metoda zadržava novi entitet u bazi podataka, koji se prosljeđuje u tijelo zahtjeva.

Da bismo sve pojednostavili, namjerno smo izostavili implementaciju kontrolera koja je pokrenula provjeru Spring Boot prije nego što smo nastavili s entitetom. Međutim, u proizvodnji jednostavno ne možemo vjerovati korisničkom unosu, pa bi provjera na strani poslužitelja trebala biti obavezna značajka.

2.5. Pokretanje aplikacije Spring Boot

Na kraju, kreirajmo standardnu ​​klasu bootstrapping Spring Boot i popunimo bazu podataka s nekoliko Korisnik entiteti:

@SpringBootApplication javna klasa Application {public static void main (String [] args) {SpringApplication.run (Application.class, args); } @Bean CommandLineRunner init (UserRepository userRepository) {return args -> {Stream.of ("John", "Julie", "Jennifer", "Helen", "Rachel"). ForEach (ime -> {Korisnik = novi Korisnik (ime, ime.toLowerCase () + "@ domena.com"); userRepository.save (korisnik);}); userRepository.findAll (). forEach (System.out :: println); }; }}

Ajmo sada pokrenuti aplikaciju. Kao što se očekivalo, trebali bismo vidjeti popis Korisnik entiteti ispisani na konzoli pri pokretanju:

Korisnik {id = 1, name = John, [email protected]} Korisnik {id = 2, name = Julie, [email protected]} Korisnik {id = 3, name = Jennifer, [email protected]} Korisnik {id = 4 , name = Helen, [email protected]} Korisnik {id = 5, name = Rachel, [email protected]}

3. Kutna primjena

S našom demonstrativnom aplikacijom Spring Boot koja je pokrenuta, stvorimo sada jednostavnu kutnu aplikaciju koja može trošiti API REST kontrolera.

3.1. Kutna CLI instalacija

Upotrijebit ćemo Angular CLI, snažni uslužni program naredbenog retka, za izradu naše Angular aplikacije.

Kutni CLI izuzetno je vrijedan alat od omogućuje nam stvaranje cijelog projekta Angular od nule, generiranje komponenata, usluga, klasa i sučelja sa samo nekoliko naredbi.

Nakon što instaliramo npm (Node Package Manager), otvorit ćemo naredbenu konzolu i upisati naredbu:

npm install -g @ angular / [zaštićen e-poštom]

To je to. Gornja naredba instalirat će najnoviju verziju Angular CLI-a.

3.2. Projektna skela s kutnim CLI-jem

Zapravo, našu Angularnu strukturu aplikacije možemo generirati od temelja. Ali iskreno, ovo je zadatak koji podrazumijeva pogreške i oduzima puno vremena kojeg bismo trebali izbjegavati u svim slučajevima.

Umjesto toga, dopustit ćemo Angularnom CLI-u da radi težak posao umjesto nas. Dakle, otvorimo naredbenu konzolu, a zatim idite do mape u kojoj želimo da se kreira naša aplikacija i upišite naredbu:

ng novi kutni klijent

The novi naredba generirat će cjelokupnu strukturu aplikacije unutar kutni klijent imenik.

3.3. Ulazna točka kutne aplikacije

Ako zavirimo u kutni klijent mapu, vidjet ćemo da je Angular CLI za nas učinkovito stvorio cijeli projekt.

Datoteke aplikacija programa Angular koriste TypeScript, tipkani nabor JavaScript-a koji se kompajlira u obični JavaScript. Međutim, početna točka bilo koje kutne aplikacije sasvim je stara index.html datoteka.

Uredimo ovu datoteku, kako slijedi:

    Proljetna čizma - kutna primjena 

Kao što gore vidimo, uključili smo Bootstrap 4, tako da komponentama korisničkog sučelja aplikacije možemo dati ljepši izgled. Naravno, moguće je pokupiti još jedan UI komplet iz gomile dostupnih tamo.

Molimo primijetite običaj oznake unutar odjeljak. Na prvi pogled izgledaju prilično čudno, kao nije standardni HTML 5 element.

Zadržimo ih odmah tamo, kao je odabir korijena koji Angular koristi za prikazivanje korijenske komponente aplikacije.

3.4. The app.component.ts Korijenska komponenta

Da bismo bolje razumjeli kako Angular veže HTML predložak na komponentu, idemo na src / app direktorij i uredite app.component.ts TypeScript datoteka - korijenska komponenta:

uvoz {Komponenta} iz '@ kutna / jezgra'; @Component ({selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']}) klasa izvoza AppComponent {title: string; konstruktor () {this.title = 'Spring Boot - kutna aplikacija'; }}

Iz očitih razloga nećemo zaranjati duboko u učenje Typescripta. Unatoč tome, primijetimo da datoteka definira AppComponent klasa, koja deklarira polje titula tipa niz (donja slova). Definitivno, to je tipkani JavaScript.

Uz to, konstruktor polje inicijalizira inicijalizacijom polja niz vrijednost, koja je prilično slična onoj što radimo u Javi.

Najvažniji dio je the @Komponenta oznaka metapodataka ili dekorator, koji definira tri elementa:

  1. selektor - HTML selektor koji se koristi za povezivanje komponente s datotekom HTML predloška
  2. templateUrl - datoteka HTML predloška pridružena komponenti
  3. styleUrls - jedna ili više CSS datoteka povezanih s komponentom

Kao što se očekivalo, možemo koristiti app.component.html i app.component.css datoteke za definiranje HTML predloška i CSS stilova korijenske komponente.

Napokon, selektor element veže cijelu komponentu na izbornik uključen u index.html datoteka.

3.5. The app.component.html Datoteka

Budući da je app.component.html datoteka nam omogućuje definirajte HTML predložak korijenske komponente - the AppComponent klasa - koristit ćemo je za stvaranje osnovne navigacijske trake s dva gumba.

Ako kliknemo prvi gumb, Angular će prikazati tablicu koja sadrži popis Korisnik entiteti pohranjeni u bazi podataka. Slično tome, ako kliknemo drugi, prikazat će se HTML obrazac koji možemo koristiti za dodavanje novih entiteta u bazu podataka:

{{title}}

  • Popis korisnika
  • Dodaj korisnika

Glavnina datoteke je standardni HTML, uz nekoliko napomena koje vrijedi napomenuti.

Prvi je {{title}} izraz. Dvostruke kovrčave zagrade {{ime-varijable}} je rezervirano mjesto koje Angular koristi za obavljanje varijabilne interpolacije.

Imajmo na umu da AppComponent klasa je inicijalizirala titula polje s vrijednošću Proljetna čizma - kutna primjena. Dakle, Angular će prikazati vrijednost ovog polja u predlošku. Isto tako, promjena vrijednosti u konstruktoru odrazit će se na predlošku.

Druga stvar koju treba napomenuti je routerLink atribut.

Angular koristi ovaj atribut za usmjeravanje zahtjeva putem svog modula usmjeravanja (o tome više kasnije). Za sada je dovoljno znati da će modul poslati zahtjev na / korisnici put do određene komponente i zahtjev za / adduser na drugu komponentu.

U svakom slučaju, HTML predložak povezan s odgovarajućom komponentom prikazat će se unutar rezerviranog mjesta.

3.6. The Korisnik Razred

Budući da će se naša aplikacija Angular dohvatiti i ustrajati Korisnik entiteta u bazi podataka, implementiramo jednostavan model domene s TypeScriptom.

Otvorimo terminalnu konzolu i stvorimo a model imenik:

generiranje korisnika klase

Kutni CLI generirat će prazno Korisnik razred. Napunimo ga s nekoliko polja:

klasa izvoza User {id: string; ime: niz; e-mail: string; }

3.7. The Korisnička usluga Servis

S našom domenom na strani klijenta Korisnik klasa već postavljena, implementirajmo sada klasu usluge koja izvodi GET i POST zahtjeve // ​​localhost: 8080 / users krajnjoj točki.

To će nam omogućiti da enkapsuliramo pristup REST kontroleru u jednu klasu, koju možemo ponovno koristiti tijekom cijele aplikacije.

Otvorimo terminal konzole, a zatim stvorimo servis i unutar tog direktorija izdajte sljedeću naredbu:

ng generiranje korisničke usluge usluge

Sada, otvorimo user.service.ts datoteka koju je Angular CLI upravo stvorio i refaktorira je:

uvoz {Injectable} iz '@ angular / core'; uvoz {HttpClient, HttpHeaders} iz '@ angular / common / http'; uvoz {Korisnika} iz '../model/user'; import {Observable} iz 'rxjs / Observable'; @Injectable () klasa izvoza UserService {private usersUrl: string; konstruktor (privatni http: HttpClient) {this.usersUrl = '// localhost: 8080 / users'; } public findAll (): Observable {return this.http.get (this.usersUrl); } javno spremanje (korisnik: korisnik) {return this.http.post (this.usersUrl, korisnik); }}

Ne trebamo čvrstu pozadinu Typecripta da bismo razumjeli kako Korisnička usluga razredna djela. Jednostavno rečeno, kapsulira se unutar komponente koja se može ponovno upotrijebiti svu funkcionalnost potrebnu za konzumiranje API-ja REST kontrolera koji smo prije implementirali u Spring Boot.

The findAll () metoda izvodi GET HTTP zahtjev na // localhost: 8080 / users krajnju točku putem Angular-a HttpClient. Metoda vraća Uočljiv instanca koja sadrži niz od Korisnik predmeta.

Isto tako, uštedjeti() metoda izvodi POST HTTP zahtjev // krajnjoj točki // localhost: 8080 / users.

Određivanjem vrste Korisnik u HttpClientZahtjevnim metodama možemo odgovoriti na kraći odgovor na lakši i učinkovitiji način.

Na kraju, idemo primijetite upotrebu @Injekcijski () oznaka metapodataka. To signalizira da bi uslugu trebalo stvoriti i ubrizgati putem mlaznica ovisnosti Angula.

3.8. The UserListComponent Komponenta

U ovom slučaju, Korisnička usluga class je tanka srednja razina između usluge REST i prezentacijskog sloja aplikacije. Stoga moramo definirati komponentu odgovornu za prikazivanje popisa Korisnik entiteti ustrajali u bazi podataka.

Otvorimo terminalnu konzolu, a zatim stvorimo popis korisnika direktorija i generirajte komponentu popisa korisnika:

generiranje korisničkog popisa komponenata

Angular CLI generirat će praznu klasu komponenata koja implementira ngOnInit sučelje. Sučelje proglašava udicu ngOnInit () metodu, koju Angular poziva nakon završetka instanciranja izvedbene klase, a nakon pozivanja i svog konstruktora.

Refaktoriziramo klasu tako da može potrajati Korisnička usluga primjer u konstruktoru:

uvoz {Component, OnInit} iz '@ angular / core'; uvoz {Korisnika} iz '../model/user'; uvoz {UserService} iz '../service/user.service'; @Component ({selector: 'app-user-list', templateUrl: './user-list.component.html', styleUrls: ['./user-list.component.css']}) klasa izvoza UserListComponent implementira OnInit {korisnici: Korisnik []; konstruktor (privatni userService: UserService) {} ngOnInit () {this.userService.findAll (). subscribe (data => {this.users = data;}); }} 

Provedba UserListComponent čas je prilično objašnjen. Jednostavno koristi FindAll korisnika UserService () metoda za dohvaćanje svih entiteta koji su postojali u bazi podataka i njihovo spremanje u korisnika polje.

Uz to, moramo urediti HTML datoteku komponente, user-list.component.html, za stvaranje tablice koja prikazuje popis entiteta:

#ImeE-mail
{{user.id}}{{ Korisničko ime }}{{user.email}}

Primijetite upotrebu * ngFor direktiva. Direktiva se naziva a repetitor, a možemo ga koristiti za ponavljanje sadržaja varijable i iterativno prikazivanje HTML elemenata. U ovom smo ga slučaju koristili za dinamičko prikazivanje redaka tablice.

Uz to, koristili smo varijabilnu interpolaciju za prikazivanje iskaznica,Ime, i e-mail svakog korisnika.

3.9. The UserFormComponent Komponenta

Slično tome, moramo stvoriti komponentu koja nam omogućuje da ustrajemo u novom Korisnik objekt u bazi podataka.

Stvorimo a korisnički oblik imenik i upišite sljedeće:

generiranje korisničkog oblika komponente 

Dalje, otvorimo user-form.component.ts datoteku i dodajte u UserFormComponent razred metoda za spremanje a Korisnik objekt:

uvoz {Komponenta} iz '@ kutna / jezgra'; uvoziti {ActivatedRoute, Router} iz '@ angular / router'; uvoz {UserService} iz '../service/user.service'; uvoz {User} iz '../model/user'; @Component ({selector: 'app-user-form', templateUrl: './user-form.component.html', styleUrls: ['./user-form.component.css']}) klasa izvoza UserFormComponent {user : Korisnik; konstruktor (privatna ruta: ActivatedRoute, privatni usmjerivač: usmjerivač, privatna korisnička usluga: UserService) {this.user = novi korisnik (); } onSubmit () {this.userService.save (this.user) .subscribe (rezultat => this.gotoUserList ()); } gotoUserList () {this.router.navigate (['/ users']); }}

U ovom slučaju, UserFormComponent također uzima a Korisnička usluga primjer u konstruktoru, koji onSubmit () metoda koristi za spremanje isporučenog Korisnik objekt.

Budući da moramo ponovno prikazati ažurirani popis entiteta nakon što nastavimo s novim, nazivamo gotoUserList () metoda nakon umetanja koja korisnika preusmjerava na / korisnici staza.

Osim toga, moramo urediti user-form.component.html datoteku i stvorite HTML obrazac za zadržavanje novog korisnika u bazi podataka:

 Ime Potrebno je ime E-adresa Potrebna je adresa e-pošte Pošalji 

Na prvi pogled oblik izgleda prilično standardno. Ali obuhvaća puno Angular-ovih funkcionalnosti iza kulisa.

Primijetimo upotrebu the ngPošaljite direktivu koja poziva onSubmit () metoda kada se obrazac predaje.

Dalje, definirali smo varijabla predloška #userForm, tako da Angular automatski dodaje NgForm direktivu koja nam omogućuje praćenje oblika u cjelini.

The NgForm Direktiva sadrži kontrole koje smo kreirali za elemente obrasca pomoću ngModel direktiva i a Ime atribut i također prati njihova svojstva, uključujući i njihovo stanje.

The ngModel Direktiva daje nam dvosmjernu funkcionalnost vezivanja podataka između kontrola obrasca i klijentskog modela domene - Korisnik razred.

To znači da će podaci uneseni u polja za unos obrasca teći prema modelu - i obrnuto. Promjene u oba elementa odmah će se odraziti DOM manipulacijom.

Dodatno, ngModel omogućuje nam praćenje stanja svake kontrole obrasca i izvršavanje provjere na strani klijenta, dodavanjem svake kontrole različitih CSS klasa i DOM svojstava.

U gornjoj HTML datoteci koristili smo svojstva primijenjena na kontrole obrasca samo za prikaz okvira upozorenja kada su vrijednosti u obrascu promijenjene.

3.10. The usmjeravanje aplikacija.module.ts Datoteka

Iako su komponente izolirane, ipak moramo koristiti mehanizam za njihovo pozivanje kada korisnik klikne gumbe na navigacijskoj traci.

Ovdje je Modul usmjerivača dolazi u igru. Pa, otvorimo usmjeravanje aplikacija.module.ts datoteku i konfigurirajte modul, tako da može slati zahtjeve odgovarajućim komponentama:

uvoz {NgModule} iz '@ kutna / jezgra'; uvoziti {Rute, RouterModule} iz '@ angular / router'; uvezi {UserListComponent} iz './user-list/user-list.component'; uvezi {UserFormComponent} iz './user-form/user-form.component'; const routes: Routes = [{put: 'korisnici', komponenta: UserListComponent}, {put: 'adduser', komponenta: UserFormComponent}]; @NgModule ({importi: [RouterModule.forRoot (rute)], izvozi: [RouterModule]}) klasa izvoza AppRoutingModule {} 

Kao što gore možemo vidjeti, the Rute niz upućuje usmjerivač koju komponentu treba prikazati kada korisnik klikne vezu ili navede URL u adresnu traku preglednika.

Ruta se sastoji od dva dijela:

  1. Staza - a niz koji se podudara s URL-om u adresnoj traci preglednika
  2. Komponenta - komponenta koju treba stvoriti kada je ruta aktivna (navigirana)

Ako korisnik klikne na Popis korisnika gumb koji povezuje na / korisnici putanju ili unese URL u adresnu traku preglednika, usmjerivač će prikazati UserListComponent datoteka predloška komponente u rezerviranog mjesta.

Isto tako, ako kliknu na Dodaj korisnika gumb, prikazat će UserFormComponent komponenta.

3.11. The app.module.ts Datoteka

Dalje, moramo urediti app.module.ts datoteku, tako da Angular može uvesti sve potrebne module, komponente i usluge.

Uz to, moramo navesti kojeg ćemo pružatelja usluga koristiti za stvaranje i ubrizgavanje Korisnička usluga razred. Inače, Angular ga neće moći ubrizgati u klase komponenata:

uvoz {BrowserModule} iz '@ angular / platform-browser'; uvoz {NgModule} iz '@ kutna / jezgra'; uvoz {AppRoutingModule} iz './app-routing.module'; uvoz {FormsModule} iz '@ angular / forms'; uvoziti {HttpClientModule} iz '@ angular / common / http'; uvoz {AppComponent} iz './app.component'; uvezi {UserListComponent} iz './user-list/user-list.component'; uvezi {UserFormComponent} iz './user-form/user-form.component'; uvoz {UserService} iz './service/user.service'; @NgModule ({deklaracije: [AppComponent, UserListComponent, UserFormComponent], uvozi: [BrowserModule, AppRoutingModule, HttpClientModule, FormsModule], dobavljači: [UserService], bootstrap: [AppComponent]}) klasa izvoza AppModule {}

4. Pokretanje aplikacije

Napokon, spremni smo za pokretanje naše aplikacije.

Da bismo to postigli, prvo pokrenimo aplikaciju Spring Boot, tako da je usluga REST živa i osluškuje zahtjeve.

Nakon što se pokrene aplikacija Spring Boot, otvorimo naredbenu konzolu i upišimo sljedeću naredbu:

ng služi --otvoreno

Ovo će pokrenuti Angular-ov poslužitelj za razvoj uživo i također otvoriti preglednik na // localhost: 4200.

Trebali bismo vidjeti navigacijsku traku s gumbima za popis postojećih entiteta i za dodavanje novih. Ako kliknemo prvi gumb, ispod navigacijske trake trebali bismo vidjeti tablicu s popisom entiteta koji se zadržavaju u bazi podataka:

Slično tome, klikom na drugi gumb prikazat će se HTML obrazac za zadržavanje novog entiteta:

5. Zaključak

U ovom vodiču, naučili smo kako izraditi osnovnu web aplikaciju s Spring Boot i Angular.

Kao i obično, svi uzorci koda prikazani u ovom vodiču dostupni su na GitHubu.