Spring Boot 2.0 - Projectstructuur en best practices (deel 2)

In vervolg op het eerste deel van de serie over Spring Boot v2.0, is dit het tweede en laatste deel waar we de projectstructuur van de applicatie zullen doornemen samen met enkele belangrijke fragmenten en best practices waarmee rekening moet worden gehouden bij het doen van op Spring Boot gebaseerde ontwikkeling. .

Slechts een kleine disclaimer, na het opzetten van deze starterkit en een grondige evaluatie, zou je kunnen denken dat dit niet echt een implementatie van microservices is met Spring Boot, ik moet zeggen dat ik het volledig met je eens ben, maar dit is een monoliet ontwikkeld in Spring Boot. Dit artikel gaat meer over het leren coderen met de best practices in Spring Boot en idealiter zou een reserveringssysteem meer dan slechts één service of codebasis moeten hebben, ik beloof dat ik binnenkort een nieuwe serie zal publiceren over het gebruik van Spring Boot bij het maken van een gedistribueerde applicatie met behulp van Netflix OSS-stack. Tot die tijd kunt u dit als uitgangspunt beschouwen en de projectstructuur en bijbehorende hulpmiddelen op elkaar afstemmen.

Broncode

De broncode voor deze starterkit kan worden gekloond uit de volgende GitHub-repository:

Applicatie structuur

Spring Boot is een eigenzinnig framework dat ons leven heel gemakkelijk maakt, omdat we niet de versies van verschillende afhankelijkheden hoeven te kiezen op basis van de versie van Spring Framework, het wordt allemaal verzorgd door Spring Boot.

Ik heb geprobeerd dezelfde ideologie te volgen bij het creëren van de projectstructuur, in het begin lijkt het misschien overweldigend, maar geloof me als je eenmaal begint met het schrijven van je stukken, de structuur zal je enorm helpen door je tijd te besparen en na te denken over vragen die al zijn beantwoord . De structuur ziet er als volgt uit:

Modellen & DTO's

De verschillende modellen van de applicatie zijn georganiseerd onder het modelpakket, hun DTO's (gegevensoverdrachtobjecten) zijn aanwezig onder het dto-pakket. Er zijn verschillende meningen over de vraag of we DTO's moeten gebruiken of niet, ik behoor tot de groep van mensen die denken dat we dat zeker moeten doen en als je DTO's niet gebruikt, is je modellaag zeer nauw gekoppeld aan de UI-laag en dat is iets dat geen enkel ondernemingsproject ooit zou moeten doen instappen.

Met DTO's kunnen we alleen de gegevens overbrengen die we moeten delen met de gebruikersinterface en niet het hele modelobject dat we mogelijk hebben verzameld met behulp van verschillende subobjecten en die in de database zijn blijven staan. Het in kaart brengen van modellen aan de DTO's kan worden afgehandeld met behulp van het ModelMapper-hulpprogramma, maar het is alleen nuttig wanneer uw DTO (bijna) vrijwel gelijk is aan de betreffende modellen, wat niet altijd het geval is en daarom geef ik er de voorkeur aan aangepaste mapper-klassen te gebruiken. U kunt enkele voorbeelden vinden onder het pakket "dto / mapper".

Laten we bijvoorbeeld eens kijken hoe ons Trip.java-model is georganiseerd:

Trip.java

Zoals we kunnen zien, heeft het model verwijzingen naar de collecties Stop, Bus en Agency. Dit is nodig om de relatie tussen deze verschillende collecties met een reis te behouden. Hoewel dit niet hetzelfde is als een concept van een externe sleutel in MySQL en er hier geen standaardcascade wordt toegepast, biedt het ons een manier om hetzelfde te emuleren in MongoDB. Het bijbehorende gegevensoverdrachtobject ziet er als volgt uit:

TripDto.java

Zoals ik eerder heb beschreven, zijn DTO's niet bedoeld als spiegelbeeld van hun model-tegenhangers, maar als een weerspiegeling van wat de gebruikersinterface of de API-reactie vereist. In dit geval had het geen zin om een ​​samenstellingsrelatie te maken tussen een reis en zijn bus of bureau of de haltes, maar hun primaire sleutels kunnen het lukken. Dit ontkoppelt niet alleen deze DTO's, het vermindert ook de totale grootte van het responspakket dat via HTTP van de server naar de client zal reizen.

De volgende vraag kan zijn hoe het model POJO naar deze DTO te converteren, er zijn meer dan één manier om dit te doen, maar mijn voorkeur is expliciet en doe-het-zelf als volgt:

Services en DAO's

De gegevenstoegangsobjecten (DAO's) zijn aanwezig in het repository-pakket. Het zijn allemaal uitbreidingen van de MongoRepository-interface die de servicelaag helpen behouden en de gegevens ophalen van MongoDB.

De servicelaag wordt gedefinieerd onder het servicepakket, gezien de huidige case study was het logisch om twee basisservices te creëren:

  1. Gebruikersservice en
  2. BusReservationService

Het uitleggen van elke methode in deze services valt buiten het bereik van deze blogpost, maar ik zal een lijst maken van de interfaces die de bewerkingen tonen die door deze services worden ondersteund.

UserService.java

BusReservationService.java

Afgezien van het opmerken van de methode voor het benoemen van conventies, weet ik zeker dat je hebt gemerkt dat de servicelaag nooit een model als invoer accepteert en er ook nooit een retourneert. Dit is een andere best practice die Spring-ontwikkelaars in een gelaagde architectuur moeten volgen. De controllerlaag werkt samen met de servicelaag om een ​​klus te klaren wanneer deze een verzoek ontvangt van de view- of api-laag, wanneer dit wel gebeurt, moet deze geen toegang hebben tot de modelobjecten en moet deze altijd converseren in termen van neutrale DTO's.

Wanneer de service een DTO-object ontvangt, moet het proberen dit te begrijpen door het overeenkomstige modelobject uit de database op te vragen en vervolgens de benodigde bewerking uitvoeren en een respons-DTO maken om terug te sturen naar de aanroepende service. Met deze aanpak kunt u het beeld en de modellen onafhankelijk van elkaar veranderen zonder dat u zich zorgen hoeft te maken dat de ene de andere kapot maakt.

Laten we ter illustratie van de bovengenoemde aanpak een voorbeeld nemen van een servicebewerking "updateProfile" die wordt gebruikt om de informatie van de gebruiker bij te werken. De methodedefinitie ziet er als volgt uit:

Veiligheid

De beveiligingsinstelling is aanwezig onder het configuratiepakket en de daadwerkelijke configuraties worden uitgevoerd onder de klasse die aanwezig is in het beveiligingspakket. De applicatie heeft verschillende beveiligingsconcepten voor de admin portal en de REST API's, voor de portal heb ik het standaard lente sessie mechanisme toegepast dat gebaseerd is op het concept van sessieID en cookies. Voor de REST API's heb ik JWT-tokengebaseerd authenticatiemechanisme gebruikt.

De beveiliging voor web en apis wordt beide in dezelfde klasse MultiHttpSecurityConfig.java geconfigureerd. Het heeft twee statische klassen die zich uitstrekken van WebSecurityConfigurerAdapter waarmee we de http-beveiliging voor inkomende aanvragen kunnen configureren.

Met de annotatie @Order kunnen de aanvragen worden gescand via de verschillende configuraties in de opgegeven volgorde. Dus een API-aanvraag doorloopt de ApiWebSecurityConfigurationAdapter en wordt daar geabsorbeerd, maar een Admin-aanvraag gaat er eerst doorheen, maar omdat het niet overeenkomt met de criteria, probeert Spring Security het de volgende configuratie te laten doorlopen met een onmiddellijk hogere bestelling die in dit geval is FormLoginWebSecurityConfigurerAdapter.

De API-aanvragen moeten door de ApiJWTAuthenticationFilter en ApiJWTAuthorizationFilter gaan die verantwoordelijk zijn voor het maken en valideren van het JWT-token dat is uitgegeven op het moment van inloggen. Als u zich afvraagt ​​welke URL moet worden gebruikt voor API-authenticatie (login), dan is dit:

http: // localhost: 8080 / api / auth

En als je je afvraagt ​​hoe dit is geconfigureerd, ligt het antwoord in de klasse ApiJWTAuthenticationFilter, de constructor heeft de volgende gecodeerde informatie:

this.setRequiresAuthenticationRequestMatcher (nieuwe AntPathRequestMatcher ("/ api / auth", "POST"));

Dit vertelt AbstractAuthenticationProcessingFilter om het AuthenticationRequestMatcher te koppelen met het "/ api / auth" -pad voor de API-aanvragen.

De admin-applicatie is alleen toegestaan ​​voor gebruikers met de rol "ADMIN". Alle wachtwoorden worden gecodeerd met behulp van BCryptPasswordEncoder en we kunnen nooit hun werkelijke waarde zien zodra ze zijn opgeslagen in de database.

Controllers

Laatste, maar het belangrijkste deel is de controllerlaag. Het bindt alles samen vanaf het moment dat een verzoek wordt onderschept tot het antwoord is voorbereid en teruggestuurd. De controller-laag is aanwezig in het controller-pakket, de best practices suggereren dat we deze laag een versie houden om meerdere versies van de applicatie te ondersteunen en dezelfde practice wordt hier toegepast.

Voorlopig is code alleen aanwezig onder v1, maar na verloop van tijd verwacht ik verschillende versies met verschillende functies. De beheerdersportal gerelateerde controllers zijn aanwezig in het ui-pakket en de betreffende formulieropdrachtobjecten bevinden zich onder het opdrachtenpakket. De REST API-controllers bevinden zich onder het api-pakket en de bijbehorende verzoekklassen bevinden zich onder het aanvraagpakket.

De admin-paneelcontrollers werken volgens het Spring WebMVC-concept. Ze reageren op binnenkomende webverzoeken met Spring's ModelAndView-objecten die de gegevens bevatten die op de betreffende weergaven / formulieren en de naam van de weer te geven weergave moeten worden weergegeven, een voorbeeld uit de DashboardController-klasse is als volgt:

Verzoek- en formulieropdrachten

Nogmaals, er zijn verschillende meningen onder de ontwikkelaarsgemeenschap over het gebruik van afzonderlijke klassen voor het in kaart brengen van de inkomende aanvraag versus het gebruik van de DTO's versus het gebruik van de modellen, ik ben persoonlijk een fan van ze zoveel mogelijk te scheiden om losse koppeling tussen UI te bevorderen en controller laag.

De aanvraagobjecten en de formulieropdrachten geven ons een manier om een ​​extra validatieniveau toe te passen op de binnenkomende aanvragen voordat ze worden geconverteerd naar de DTO's die geldige informatie overbrengen naar de servicelaag voor persistentie en het ophalen van gegevens. We zouden hier DTO's kunnen gebruiken en sommige ontwikkelaars geven de voorkeur aan die aanpak omdat het een aantal extra klassen vermindert, maar ik geef er meestal de voorkeur aan om de validatielogica gescheiden te houden van de overdrachtobjecten en ben daarom geneigd om de aanvraag- / opdrachtobjecten voor hen te gebruiken.

Een voorbeeld van een op een opdrachtpatroon gebaseerde klasse BusFormCommand ziet er als volgt uit:

En een voorbeeld van een verzoek verzonden via API, BookTicketRequest is als volgt:

De statische bronnen zijn gegroepeerd in de bronnenmap. Alle UI-objecten en hun stijlaspecten kunnen hier worden gevonden.

Lombok

Een van de grootste klachten tegen Java is hoeveel lawaai er in een enkele klasse te vinden is. Project Lombok zag dit als een probleem en heeft als doel het lawaai van enkele van de ergste overtreders te verminderen door ze te vervangen door een eenvoudige set annotaties. Je zult zien dat Lombok overal in dit startpakket wordt gebruikt, het heeft zelfs bijgedragen aan het verminderen van de coderegels, bespaart veel ontwikkeltijd en moeite en maakt de code veel leesbaarder. Enkele van de belangrijkste annotaties die ik het liefst gebruik, zijn:

@Getter / @ Setter

Schrijf nooit meer openbaar in getFoo () {return foo;}.

@ToString

U hoeft geen debugger te starten om uw velden te zien: laat lombok gewoon een toString voor u genereren!

@EqualsAndHashCode

Gelijkheid gemakkelijk gemaakt: genereert hashCode en is gelijk aan implementaties uit de velden van uw object ..

@Gegevens

Nu allemaal samen: een snelkoppeling voor @ToString, @EqualsAndHashCode, @Getter op alle velden en @Setter op alle niet-definitieve velden, en

@RequiredArgsConstructor!

In wezen iets zo uitgebreid als:

Kan eenvoudig worden geschreven als:

Je kunt het verschil heel goed zien, niet alleen het uiterlijk ziet er veel schoner uit, we zijn gekomen van 59 regels saaie POJO naar een op Java gebaseerd bestand met 8 regels.

API-respons en uitzonderingsbehandeling

Ik heb geprobeerd een beetje te experimenteren met de RuntimeExceptions en een miniframework te bedenken voor het verwerken van de uitzonderingen van de hele toepassing met behulp van een paar klassen en het eigenschappenbestand. Als u het uitzonderingspakket zorgvuldig in acht neemt, bestaat het uit twee enums:

  1. EntityType en
  2. ExceptionType

Het EntityType-overzicht bevat alle entiteitsnamen die we in het systeem gebruiken voor persistentie en die welke kunnen leiden tot een runtime-uitzondering. Het Enception-type enum bestaat uit de verschillende uitzonderingen op entiteitsniveau, zoals de uitzonderingen EntityNotFound en DuplicateEntity.

De BRSException-klasse heeft twee statische klassen EntityNotFoundException en DuplicateEntityException, de twee meest voorkomende uitzonderingen op de servicelaag. Het bevat ook een reeks overbelaste methoden throwException die EntityType, ExceptionType en argumenten gebruiken om een ​​opgemaakt bericht te maken waarvan de sjabloon aanwezig is onder het bestand custom.properties.

Met behulp van deze klasse was ik in staat om de hele dienstenlaag in staat te stellen om een ​​verscheidenheid aan entiteitsuitzonderingen op een uniforme manier te gooien zonder de codebasis vol te zetten met allerlei NOT_FOUND en DUPLICATE entiteitsuitzonderingen.

Als u bijvoorbeeld tijdens het inloggen een e-mailadres probeert te gebruiken dat niet is geregistreerd, wordt er een uitzondering gegenereerd met de volgende enkele coderegel:

gooi uitzondering (USER, ENTITY_NOT_FOUND, userDto.getEmail ());

Dit resulteert in het clubben van de namen van deze twee enum-elementen USER ("user") en ENTITY_NOT_FOUND ("not.found") en komt als volgt met een key user.not.found die aanwezig is in de custom.properties-bestanden:

user.not.found = Gevraagde gebruiker met e-mail - {0} bestaat niet.

Door simpelweg de parameter {0} te vervangen door het e-mailadres dat is opgenomen in de uitzonderingsfout, kunt u een goed opgemaakt bericht krijgen dat aan de gebruiker wordt getoond of dat als antwoord op de REST API-oproep wordt teruggestuurd. De definitie van de BRSException-klasse is als volgt:

Een ander belangrijk onderdeel van dit mini-framework is de klasse CustomizedResponseEntityExceptionHandler die er als volgt uitziet:

Deze klasse zorgt voor deze RuntimeExceptions voordat een reactie op de API-verzoeken wordt verzonden. Het is een controlleradvies dat controleert of een aanroep van een servicelaag resulteerde in een EntityNotFoundException of een DuplicateEntityException en stuurt een passend antwoord naar de beller.

Ten slotte worden de API-antwoorden allemaal op een uniforme manier verzonden met behulp van de Response-klasse die aanwezig is in het dto / response-pakket. Met deze klasse kunnen we uniforme objecten maken die resulteren in een reactie zoals hieronder weergegeven (deze is een reactie voor de api “api / v1 / reservation / stops”):

{
 "Status": "OK",
 "Payload": [
   {
    "Code": "STPA",
    "Name": "Stop A",
    "Detail": "Dichtbij heuvels"
   },
   {
    "Code": "STPB",
    "Name": "Stop B",
    "Detail": "Bij rivier"
   }
 ]
}

En wanneer er een uitzondering is (bijvoorbeeld zoeken naar een reis tussen twee haltes die niet zijn verbonden door een bus), worden de volgende antwoorden teruggestuurd (resultaat van het GET-verzoek “api / v1 / reservation / tripsbystops”):

{
  "Status": "NOT_FOUND",
  "Fouten": "Geen ritten tussen bronstop -" STPD "en bestemmingstop -" STPC "zijn op dit moment beschikbaar."
}
{
  "Status": "NOT_FOUND",
  “Fouten”:
  {
    "Timestamp": "2019–03–13T07: 47: 10.990 + 0000",
    "Message": "Gevraagde stop met code - STPF bestaat niet."
  }
}

Zoals u kunt zien, beide typen antwoorden, een met een HTTP-200 en een andere met HTTP-404, verandert de respons-payload niet van structuur en kan het aanroepende framework de reactie blind accepteren, wetende dat er een status en een fout of payload-veld in het JSON-object.

API-documentatie

Het is net zo belangrijk om uw werk te documenteren (evenals de ontwikkeling ervan) en ervoor te zorgen dat uw Spring Boot API's op een leesbare manier beschikbaar zijn voor frontend teams (interne) of externe consumenten. De tool voor API-documentatie die in deze starterkit wordt gebruikt, is Swagger2, u kunt hetzelfde openen in een browser met de volgende URL:

http: // localhost: 8080 / branie-ui.html

U krijgt een goed gestructureerde gebruikersinterface met twee specificaties:

1. Gebruiker
2. BRS

U kunt de gebruikersspecificatie gebruiken om de aanmeldings-API uit te voeren voor het genereren van het bearertoken. Het token moet dan worden toegepast in de pop-up 'Autoriseren', die het standaard op alle beveiligde apis's toepast (beide ophalen en plaatsen). Houd er rekening mee dat u het woord "Drager" gevolgd door een spatie vóór het token moet toevoegen voordat u het in het dialoogvenster voor autorisatie toepast.

De configuratie van Swagger wordt verzorgd door klasse BrsConfiguration. Ik heb daar twee specificaties gedefinieerd met behulp van de methoden "swaggerBRSApi" en "swaggerUserApi". Omdat het inloggedeelte standaard wordt verzorgd door Spring Security, kunnen we de API's niet impliciet weergeven omdat de rest van de API's in het systeem zijn gedefinieerd en om dezelfde reden heb ik een controller in het configuratiepakket met de naam gedefinieerd "FakeController":

Het doel is om het genereren van swagger-documentatie voor inlog- en uitlog-apis te vergemakkelijken, het zal nooit ontstaan ​​tijdens de levenscyclus van de applicatie, omdat de “/ api / auth” -api wordt verwerkt door de beveiligingsfilters die in de codebasis zijn gedefinieerd. Hier zijn enkele voorbeeldschermafbeeldingen om dingen een beetje beter te visualiseren:

Swagger UI/ api / auth login, met dank aan FakeControllerAutorisatie dialoogvenster voor het registreren van Bearer tokensBRS API'sBRS API's vermeld

Om de Swagger UI te gebruiken en de beveiligde API's uit te voeren, moet u eerst de "/ api / auth" van de gebruikersspecificatie bedienen en een Bearer-token genereren. Nadat het token is uitgegeven, kunt u het registreren in de pop-up Autoriseren en vervolgens naar de BRS-specificatie gaan om de beveiligde API's uit te voeren. Als u het token niet registreert, blijft u de HTTP 401-fout ontvangen.

Je kunt problemen krijgen tijdens het uitproberen van de Swagger-Ui voor die HTTP-GET-aanvragen die een body met parameters hebben, maak je geen zorgen het is niet de fout van de code, het is Swagger's beslissing om te stoppen met het ondersteunen van body-params voor GET- en DELETE-aanvragen . U kunt dit probleem omzeilen door het krulverzoek van swagger te kopiëren en in een terminalvenster uit te voeren. Dat zou goed moeten werken of u kunt ervoor kiezen om voor Postman of een vergelijkbare tool te gaan, omdat ze (nog) geen dergelijke restrictie afdwingen. Naar mijn mening, zolang de Open API-specificaties de bodyparams niet beperken in GET-aanvragen, zouden tools zoals Swagger dat ook niet moeten doen, maar het is een oproep die ze moeten doen en niet ons als ontwikkelaars.

UI-architectuur

De gebruikersinterface voor de beheerportal is ontworpen met behulp van materiaalontwerp met behulp van Bootstrap en een responsief webapp-concept. De gebruikersinterface wordt aan de serverzijde weergegeven met behulp van Thymeleaf-sjablonen (de voorkeur verdienende sjabloonmotor in het voorjaar).

De standaard manier van werken met Thymeleaf is het gebruik van. Dit leidt vaak tot repetitieve code, vooral wanneer een website veel pagina's heeft en elke pagina verschillende herbruikbare componenten heeft (bijvoorbeeld koptekst, navigatie, zijbalk en voettekst). Het is repetitief omdat elke inhoudspagina dezelfde fragmenten op dezelfde locaties moet bevatten. Dit heeft ook een negatief effect wanneer de pagina-indeling verandert, b.v. bij het plaatsen van de zijbalk van links naar rechts.

Het decoratorpatroon dat wordt gebruikt door het Thymeleaf Layout-dialect lost deze problemen op. In de context van sjabloonmotoren werkt het decoratorpatroon niet meer met opgenomen op inhoudspagina's, maar verwijst het naar een algemeen sjabloonbestand. Elke pagina biedt in principe alleen de hoofdinhoud en door te beschrijven welke basissjabloon de sjabloonpagina moet gebruiken om de laatste pagina te bouwen. De inhoud wordt versierd met het sjabloonbestand. Deze aanpak heeft voordelen ten opzichte van de standaard manier om fragmenten op te nemen:

  • De pagina zelf hoeft alleen de inhoud te verstrekken.
  • Omdat een sjabloonbestand wordt gebruikt om de laatste pagina samen te stellen, kunnen algemene wijzigingen eenvoudig worden aangebracht.
  • De code wordt korter en schoner.
  • Aangezien elke inhoudspagina verwijst naar welk sjabloonbestand moet worden gebruikt, is het gemakkelijk om verschillende sjablonen te gebruiken voor verschillende delen van de applicatie (bijv. Openbaar gebied en beheerdersgebied).

De lay-out voor admin portal is als volgt ontworpen:

Blogachtige lay-out

De afzonderlijke gebieden in deze lay-out hebben het volgende doel:

  • Koptekst: dit fragment wordt gebruikt voor de statische import (CSS en JavaScript), de titel en metatags.
  • Navigatie: de navigatiebalk met gebruikersprofiel rechtsboven.
  • Inhoud: de tijdelijke aanduiding voor inhoud die wordt vervangen door de gevraagde pagina.
  • Zijbalk: een zijbalk voor aanvullende informatie.
  • Voettekst: het voettekstgebied met de copyrightinformatie.

Deze componenten kunnen zich in de hoofdmap / sjablonenmap in de hoofdmap bevinden, evenals onder de fragmenten en lay-out van de submappen. Het inhoudsgebied in deze lay-out zal de volgende pagina's hosten:

  • Dashboard
  • agentschap
  • Bus
  • Reis
  • Profiel

Ook is een foutpagina voor elke niet-verwerkte uitzondering ontworpen met de naam "error.html". De aanmeldings- en aanmeldingspagina's zijn afzonderlijk van de portal ontworpen die toegankelijk is voor een aangemelde gebruiker.

De server lokaal uitvoeren

Om deze Spring Boot-app te kunnen gebruiken, moet je deze eerst bouwen. Gebruik de onderstaande opdracht om de Spring Boot-app te bouwen en te verpakken in een enkel uitvoerbaar Jar-bestand met een Maven. Je moet het uitvoeren vanuit de projectmap die het bestand pom.xml bevat.

maven pakket

of u kunt ook gebruiken

MVN schone installatie

Om de app vanuit een terminalvenster uit te voeren, kunt u de opdracht java -jar gebruiken. Dit is op voorwaarde dat uw Spring Boot-app is verpakt als een uitvoerbaar jar-bestand.

java -jar target / springboot-starterkit-0.0.1-SNAPSHOT.jar

U kunt ook de Maven-plug-in gebruiken om de app uit te voeren. Gebruik het onderstaande voorbeeld om uw Spring Boot-app uit te voeren met de Maven-plug-in:

mvn spring-boot: rennen

U kunt alle / alle bovenstaande opdrachten volgen, of eenvoudigweg de configuratie van uw favoriete IDE gebruiken en vanaf daar de app uitvoeren / debuggen voor ontwikkelingsdoeleinden. Nadat de server is ingesteld, moet u via de volgende URL toegang hebben tot de beheerdersinterface:

http: // localhost: 8080

En de REST API's zijn toegankelijk via het volgende basispad:

http: // localhost: 8080 / api /

Enkele van de belangrijke api-eindpunten zijn:

  • http: // localhost: 8080 / api / v1 / user / signup (HTTP: POST)
  • http: // localhost: 8080 / api / auth (HTTP: POST)
  • http: // localhost: 8080 / api / v1 / reservering / stops (HTTP: GET)
  • http: // localhost: 8080 / api / v1 / reservering / tripsbystops (HTTP: GET)
  • http: // localhost: 8080 / api / v1 / reservering / tripschedules (HTTP: GET)
  • http: // localhost: 8080 / api / v1 / reservering / bookticket (HTTP: POST)

Docker Container

Gebruik de volgende opdracht om de containerafbeelding samen te stellen:

docker build -t veer / startset.

En de volgende opdracht om de container uit te voeren:

docker run -p 8080: 8080 veer / startset

Let op: wanneer u de containerimage bouwt en als mongodb lokaal op uw systeem wordt uitgevoerd, moet u het IP-adres van uw systeem (of IP in de cloud gehoste database) opgeven in het bestand application.properties (of env vars) om verbinding te kunnen maken naar de database vanuit de container.

Gevolgtrekking

Zoals u kunt zien, is de starterkit ontworpen om u uren codeertijd te besparen door u een gestroomlijnde, efficiënte en schoon gecodeerde interface en architectuur te bieden waarop u uw eigen ontwikkeling kunt baseren. Probeer het uit en laat me je feedback weten.

Ik hoop dat deze serie van twee artikelen je heeft geholpen bij het verbeteren van je Spring Boot-vaardigheden en dat het je een solide platform heeft gegeven om te beginnen met het schrijven van je volgende Spring Boot-app.

Iedereen blij coderen!

Als het interessant of nuttig voor je was, druk dan op de lap klapknop en help anderen dit verhaal ook te vinden.

Wist je dat je tot 50 klappen kon geven?