Spring Cloud - Angular toevoegen 4

1. Overzicht

In ons laatste Spring Cloud-artikel hebben we Zipkin-ondersteuning toegevoegd aan onze applicatie. In dit artikel gaan we een front-end-applicatie aan onze stack toevoegen.

Tot nu toe hebben we volledig aan de achterkant gewerkt om onze cloudapplicatie te bouwen. Maar wat heb je aan een webapp als er geen gebruikersinterface is? In dit artikel gaan we dat probleem oplossen door een applicatie met één pagina in ons project te integreren.

We zullen deze app schrijven met Hoekig en Bootstrap. De stijl van Angular 4-code lijkt veel op het coderen van een Spring-app, wat een natuurlijke cross-over is voor een Spring-ontwikkelaar! Hoewel de front-end-code Angular gebruikt, kan de inhoud van dit artikel eenvoudig met minimale inspanning worden uitgebreid naar elk front-end-framework.

In dit artikel gaan we een Angular 4-app bouwen en deze verbinden met onze cloudservices. We zullen demonstreren hoe u login tussen een SPA en Spring Security integreert. We laten ook zien hoe u toegang kunt krijgen tot de gegevens van onze applicatie met behulp van Angular's ondersteuning voor HTTP-communicatie.

2. Gateway-wijzigingen

Met de front-end op zijn plaats, gaan we overschakelen naar formuliergebaseerd inloggen en delen van de gebruikersinterface beveiligen voor geprivilegieerde gebruikers. Dit vereist het aanbrengen van wijzigingen in onze gateway-beveiligingsconfiguratie.

2.1. Bijwerken HttpSecurity

Laten we eerst updaten configureren (HttpSecurity http) methode in onze gateway SecurityConfig.java klasse:

@Override protected void configure (HttpSecurity http) {http .formLogin () .defaultSuccessUrl ("/ home / index.html", true) .and () .authorizeRequests () .antMatchers ("/ book-service / **", "/ rating-service / **", "/ login *", "/") .permitAll () .antMatchers ("/ eureka / **"). hasRole ("ADMIN") .anyRequest (). geverifieerd () .en () .logout () .en () .csrf (). uitschakelen (); }

Eerst voegen we een standaard succes-URL toe om naar te verwijzen /home/index.html aangezien dit zal zijn waar onze Angular-app leeft. Vervolgens configureren we de ant-matchers om elk verzoek via de gateway toe te staan, behalve de Eureka middelen. Hiermee worden alle beveiligingscontroles gedelegeerd aan back-endservices.

Vervolgens hebben we de succes-URL voor het uitloggen verwijderd, omdat de standaardomleiding terug naar de inlogpagina prima werkt.

2.2. Voeg een hoofd-eindpunt toe

Laten we vervolgens een eindpunt toevoegen om de geverifieerde gebruiker te retourneren. Dit wordt gebruikt in onze Angular-app om in te loggen en de rollen van onze gebruiker te identificeren. Dit helpt ons te bepalen welke acties ze op onze site kunnen doen.

Voeg in het gatewayproject een AuthenticationController klasse:

@RestController publieke klasse AuthenticationController {@GetMapping ("/ me") publieke Principal getMyUser (Principal principal) {return principal; }}

De controller stuurt het momenteel aangemelde gebruikersobject terug naar de beller. Dit geeft ons alle informatie die we nodig hebben om onze Angular-app te bedienen.

2.3. Voeg een bestemmingspagina toe

Laten we een heel eenvoudige bestemmingspagina toevoegen, zodat gebruikers iets zien wanneer ze naar de root van onze applicatie gaan.

In src / main / resources / static, laten we een index.html bestand met een link naar de inlogpagina:

    Boek Rater Landing 

Zoveel geweldige dingen over de boeken

Log in

3. Angular CLI en het Starter Project

Zorg ervoor dat u de nieuwste versies van Node.js en npm installeert voordat u een nieuw Angular-project start.

3.1. Installeer de Angular CLI

Om te beginnen zullen we moeten gebruiken npm om de Angular-opdrachtregelinterface te downloaden en te installeren. Open een terminal en voer het volgende uit:

npm install -g @ angular / cli

Hiermee wordt de CLI wereldwijd gedownload en geïnstalleerd.

3.2. Installeer een nieuw project

Navigeer, terwijl je nog in de terminal bent, naar het gatewayproject en ga naar de gateway / src / hoofdmap. Maak een directory met de naam "angular" en navigeer ernaartoe. Vanaf hier rennen:

ng nieuwe ui

Wees geduldig; de CLI zet een gloednieuw project op en downloadt alle JavaScript-afhankelijkheden met npm. Het is niet ongebruikelijk dat dit proces vele minuten in beslag neemt.

De ng commando is de snelkoppeling voor de Angular CLI, de nieuw parameter instrueert die CLI om een ​​nieuw project te maken, en de ui commando geeft ons project een naam.

3.3. Voer het project uit

Zodra het nieuw commando is voltooid. Navigeer naar het ui map die is gemaakt en wordt uitgevoerd:

ng serveren

Zodra het project is opgebouwd, navigeert u naar // localhost: 4200. We zouden dit in de browser moeten zien:

Gefeliciteerd! We hebben zojuist een Angular-app gebouwd!

3.4. Installeer Bootstrap

Laten we npm gebruiken om bootstrap te installeren. Voer vanuit de ui-directory deze opdracht uit:

npm install [e-mail beschermd] --save

Hiermee wordt bootstrap gedownload naar de map node_modules.

In de ui directory, open het .angular-cli.json het dossier. Dit is het bestand dat enkele eigenschappen van ons project configureert. Vind de apps> stijlen eigenschap en voeg een bestandslocatie toe van onze Bootstrap CSS-klasse:

"styles": ["styles.css", "../node_modules/bootstrap/dist/css/bootstrap.min.css"],

Dit zal Angular instrueren om Bootstrap op te nemen in het gecompileerde CSS-bestand dat met het project is gebouwd.

3.5. Stel de Build Output Directory in

Vervolgens moeten we Angular vertellen waar we de build-bestanden moeten plaatsen, zodat onze spring-boot-app ze kan gebruiken. Spring Boot kan bestanden bedienen vanaf twee locaties in de bronnenmap:

  • src / main / resources / static
  • src / main / resource / public

Omdat we de statische map al gebruiken om enkele bronnen voor Eureka te bedienen, en Angular deze map elke keer dat een build wordt uitgevoerd, verwijdert, laten we onze Angular-app in de openbare map bouwen.

Open de .angular-cli.json bestand opnieuw en zoek het apps> outDir eigendom. Werk dat bij draad:

"outDir": "../../resources/static/home",

Als het Angular-project zich in src / main / angular / ui bevindt, wordt het naar de map src / main / resources / public gebouwd. Als de app in een andere map staat, moet deze string worden aangepast om de locatie correct in te stellen.

3.6. Automatiseer de build met Maven

Ten slotte zullen we een geautomatiseerde build opzetten die wordt uitgevoerd wanneer we onze code compileren. Deze ant-taak zal de Angular CLI-buildtaak uitvoeren wanneer "mvn compile" wordt uitgevoerd. Voeg deze stap toe aan de POM.xml van de gateway om ervoor te zorgen dat we elke keer dat we compileren de laatste ui-wijzigingen krijgen:

 maven-antrun-plugin genereren-bronnen uitvoeren 

We moeten opmerken dat deze opstelling vereist dat de Angular CLI beschikbaar is op het klassenpad. Het pushen van dit script naar een omgeving die die afhankelijkheid niet heeft, zal resulteren in build-fouten.

Laten we nu beginnen met het bouwen van onze Angular-applicatie!

4. Hoekig

In dit gedeelte van de tutorial bouwen we een authenticatiemechanisme op onze pagina. We gebruiken basisverificatie en volgen een eenvoudige stroom om het te laten werken.

Gebruikers hebben een inlogformulier waar ze hun gebruikersnaam en wachtwoord kunnen invoeren.

Vervolgens gebruiken we hun inloggegevens om een ​​base64-verificatietoken te maken en het "/me" eindpunt. Het eindpunt retourneert een Opdrachtgever object met de rollen van deze gebruiker.

Ten slotte slaan we de inloggegevens en de opdrachtgever op bij de klant om te gebruiken bij volgende verzoeken.

Laten we eens kijken hoe dit wordt gedaan!

4.1. Sjabloon

Navigeer in het gatewayproject naar src / main / angular / ui / src / app en open het app.component.html het dossier. Dit is de eerste sjabloon die Angular laadt en waar onze gebruikers terechtkomen na inloggen.

Hier gaan we wat code toevoegen om een ​​navigatiebalk weer te geven met een inlogformulier:

    Boek Rater Admin 
    Uitloggen

    Iedereen kan de boeken bekijken.

    Gebruikers kunnen beoordelingen bekijken en maken

    Beheerders kunnen alles doen!

    Deze code stelt een navigatiebalk in met Bootstrap-klassen. In de balk is een inline inlogformulier ingebed. Angular gebruikt deze opmaak om dynamisch met JavaScript te communiceren om verschillende delen van de pagina weer te geven en zaken zoals het indienen van formulieren te beheren.

    Uitspraken zoals (ngSubmit) = "onLogin (f)" geef gewoon aan dat wanneer het formulier wordt verzonden, de methode wordt aangeroepen "OnLogin (f)" en geef het formulier door aan die functie. Binnen de jumbotron div hebben we alineatags die dynamisch worden weergegeven, afhankelijk van de toestand van ons hoofdobject.

    Laten we vervolgens het Typescript-bestand coderen dat deze sjabloon ondersteunt.

    4.2. Typoscript

    Open vanuit dezelfde map het bestand app.component.ts. In dit bestand zullen we alle typoscripteigenschappen en methoden toevoegen die nodig zijn om onze sjabloon te laten functioneren:

    importeer {Component} uit "@ angular / core"; importeer {Principal} uit "./principal"; importeer {Response} van "@ angular / http"; importeer {Boek} uit "./book"; importeer {HttpService} van "./http.service"; @Component ({selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']}) exportklasse AppComponent {selectedBook: Book = null; principal: Principal = nieuwe Principal (false, []); loginFailed: boolean = false; constructor (privé httpService: HttpService) {} ngOnInit (): void {this.httpService.me () .subscribe ((response: Response) => {let principalJson = response.json (); this.principal = nieuwe Principal (principalJson .authenticated, principalJson.authorities);}, (error) => {console.log (error);}); } onLogout () {this.httpService.logout () .subscribe ((response: Response) => {if (response.status === 200) {this.loginFailed = false; this.principal = nieuwe Principal (false, [ ]); window.location.replace (response.url);}}, (error) => {console.log (error);}); }}

    Deze klasse haakt in op de Angular levenscyclusmethode, ngOnInit (). Bij deze methode noemen we de /me eindpunt om de huidige rol en status van de gebruiker op te halen. Dit bepaalt wat de gebruiker op de hoofdpagina ziet. Deze methode wordt geactiveerd wanneer dit onderdeel wordt gemaakt, wat een goed moment is om de eigenschappen van de gebruiker te controleren op toestemmingen in onze app.

    We hebben ook een onLogout () methode die onze gebruiker uitlogt en de staat van deze pagina herstelt naar de oorspronkelijke instellingen.

    Er is hier echter wat magie aan de hand. De httpService eigenschap die is gedeclareerd in de constructor. Angular injecteert deze eigenschap tijdens runtime in onze klas. Angular beheert enkele exemplaren van serviceklassen en injecteert deze met behulp van constructor-injectie, net als Spring!

    Vervolgens moeten we de HttpService klasse.

    4.3. HttpService

    Maak in dezelfde map een bestand met de naam "Http.service.ts". Voeg in dit bestand deze code toe om de inlog- en uitlogmethoden te ondersteunen:

    importeer {Injectable} vanuit "@ angular / core"; importeer {Observable} van "rxjs"; importeer {Response, Http, Headers, RequestOptions} vanuit "@ angular / http"; importeer {Boek} uit "./book"; importeer {Rating} van "./rating"; @Injectable () exportklasse HttpService {constructor (privé http: Http) {} me (): Observable {retourneer this.http.get ("/ me", this.makeOptions ())} logout (): Observable {retourneer dit .http.post ("/ logout", '', this.makeOptions ())} private makeOptions (): RequestOptions {let headers = new Headers ({'Content-Type': 'application / json'}); retourneer nieuwe RequestOptions ({headers: headers}); }}

    In deze klasse injecteren we een andere afhankelijkheid met behulp van de DI-constructie van Angular. Deze keer is het de Http klasse. Deze klasse behandelt alle HTTP-communicatie en wordt aan ons geleverd door het framework.

    Deze methoden voeren elk een HTTP-verzoek uit met behulp van de HTTP-bibliotheek van angular. Elk verzoek specificeert ook een inhoudstype in de headers.

    Nu moeten we nog een ding doen om het HttpService geregistreerd in het afhankelijkheidsinjectiesysteem. Open de app.module.ts bestand en zoek de eigenschap van de provider. Voeg het HttpService aan die array. Het resultaat zou er als volgt uit moeten zien:

    providers: [HttpService],

    4.4. Principal toevoegen

    Laten we vervolgens ons hoofd-DTO-object toevoegen aan onze typoscript-code. Voeg in dezelfde map een bestand toe met de naam "principal.ts" en voeg deze code toe:

    export klasse Principal {openbaar geverifieerd: boolean; overheidsinstanties: Autoriteit [] = []; openbare inloggegevens: alle; constructor (geverifieerd: boolean, autoriteiten: elke [], inloggegevens: elke) {this.authenticated = geverifieerd; autoriteiten.map (auth => this.authorities.push (nieuwe autoriteit (auth.authority))) this.credentials = referenties; } isAdmin () {retourneer this.authorities.some ((auth: Authority) => auth.authority.indexOf ('ADMIN')> -1)}} export class Authority {publieke autoriteit: String; constructor (autoriteit: String) {this.authority = autoriteit; }}

    We hebben het Opdrachtgever klasse en een Gezag klasse. Dit zijn twee DTO-klassen, net als POJO's in een Spring-app. Daarom hoeven we deze klassen niet in hoekregistratie bij het DI-systeem te registreren.

    Laten we vervolgens een omleidingsregel configureren om onbekende verzoeken om te leiden naar de root van onze applicatie.

    4.5. 404 Behandeling

    Laten we terug navigeren naar de Java-code voor de gatewayservice. In de waar Gateway Toepassing klasse verblijft voeg een nieuwe klasse toe met de naam ErrorPageConfig:

    @Component openbare klasse ErrorPageConfig implementeert ErrorPageRegistrar {@Override public void registerErrorPages (ErrorPageRegistry-register) {registry.addErrorPages (nieuwe ErrorPage (HttpStatus.NOT_FOUND, "/home/index.html")); }}

    Deze klasse identificeert elk 404-antwoord en leidt de gebruiker door naar "/Home/index.html". In een app met één pagina behandelen we zo al het verkeer dat niet naar een speciale bron gaat, aangezien de klant alle navigatieroutes zou moeten afhandelen.

    Nu zijn we klaar om deze app te starten en te zien wat we hebben gebouwd!

    4.6. Bouwen en bekijken

    Ren nu "mvn compileren”Uit de gateway-map. Dit zal onze Java-bron compileren en de Angular-app naar de openbare map bouwen. Laten we de andere cloud-applicaties starten: config, ontdekking, en zipkin. Voer vervolgens het gateway-project uit. Wanneer de service start, navigeert u naar // localhost: 8080 om onze app te zien. We zouden zoiets als dit moeten zien:

    Laten we vervolgens de link naar de inlogpagina volgen:

    Log in met de gebruikers- / wachtwoordreferenties. Klik op "Inloggen", en we zouden moeten worden omgeleid naar /home/index.html waar onze enkele pagina-app wordt geladen.

    Het lijkt op ons jumbotron geeft aan dat we zijn ingelogd als gebruiker! Log nu uit door op de link in de rechterbovenhoek te klikken en log in met de admin / admin referenties deze keer.

    Ziet er goed uit! Nu zijn we ingelogd als admin.

    5. Conclusie

    In dit artikel hebben we gezien hoe eenvoudig het is om een ​​app met één pagina in ons cloudsysteem te integreren. We hebben een modern framework genomen en een werkende beveiligingsconfiguratie in onze applicatie geïntegreerd.

    Gebruik deze voorbeelden en probeer een code te schrijven om het boekenservice of rating-service. Aangezien we nu voorbeelden hebben van het maken van HTTP-oproepen en het bedraden van gegevens naar de sjablonen, zou dit relatief eenvoudig moeten zijn.

    Als je wilt zien hoe de rest van de site zoals altijd is opgebouwd, kun je de broncode vinden op Github.