Inleiding tot Ninja Framework
1. Overzicht
Tegenwoordig zijn er veel op JEE gebaseerde frameworks zoals Spring, Play en Grails beschikbaar voor de ontwikkeling van webapplicaties.
We kunnen onze redenen hebben om een van hen te verkiezen boven de andere. Onze keuze hangt echter ook af van de use case en het probleem dat we proberen op te lossen.
In deze inleidende tutorial verkennen we het Ninja-webframework en maken we een eenvoudige webtoepassing. Tegelijkertijd zullen we enkele van de basisfuncties onderzoeken die het biedt.
2. Ninja
Ninja is een full-stack, maar toch lichtgewicht, webframework dat gebruikmaakt van bestaande Java-bibliotheken om het werk gedaan te krijgen.
Met functies van HTML tot JSON-weergave, volharding tot testen, is het een alles-in-één oplossing voor het bouwen van schaalbare webapplicaties.
Het volgt de conventie over configuratie paradigma en categoriseert de code in pakketten zoals modellen, controllers, en Diensten.
Ninja gebruikt populaire Java-bibliotheken voor belangrijke functies zoals Jackson voor JSON / XML-rendering, Guice voor afhankelijkheidsbeheer, Hibernate voor persistentie en Flyway voor databasemigraties.
Voor snelle ontwikkeling biedt het SuperDevMode voor het opnieuw laden van de code. Het stelt ons dus in staat om de veranderingen onmiddellijk in de ontwikkelomgeving te zien.
3. Installatie
Ninja heeft een standaardset tools nodig om een webapplicatie te maken:
- Java 1.8 of hoger
- Maven 3 of hoger
- IDE (Eclipse of IntelliJ)
We gebruiken een Maven-archetype om het Ninja-project snel op te zetten. Het zal ons vragen om een groeps-ID, een artefact-ID en een versienummer op te geven, gevolgd door een projectnaam:
mvn-archetype: genereer -DarchetypeGroupId = org.ninjaframework \ -DarchetypeArtifactId = ninja-servlet-archetype-simple
Of, voor een bestaand Maven-project, kunnen we de nieuwste ninja-core-afhankelijkheid toevoegen aan het pom.xml:
org.ninjaframework ninja-core 6.5.0
Vervolgens voeren we de opdracht Maven uit om de bestanden voor de eerste keer te compileren:
mvn schone installatie
Laten we als laatste de app uitvoeren met behulp van een door Ninja geleverde Maven-opdracht:
mvn ninja: rennen
Voila! Onze applicatie is gestart en zal toegankelijk zijn op localhost: 8080:
4. Projectstructuur
Laten we eens kijken naar de Maven-achtige projectstructuur gemaakt door Ninja:
Het framework maakt een aantal pakketten op basis van conventies.
De Java-klassen zijn gecategoriseerd onder conf, controllers, modellen, en Diensten mappen in src / main / java. Hetzelfde, src / test / java beschikt over de overeenkomstige unit-testklassen. De keer bekeken directory onder src / main / java bevat de HTML-bestanden. En de src / main / java / assets directory bevat bronnen zoals afbeeldingen, stylesheets en JavaScript-bestanden. We zijn allemaal klaar om een paar basisfuncties van het framework te bespreken. Een controller is een klasse die een verzoek ontvangt en het antwoord met specifieke resultaten retourneert. Laten we eerst een paar te volgen conventies bespreken: Laten we het Applicatiecontroller class met een eenvoudige methode om de HTML weer te geven: Hier de inhoudsopgave methode zal een HTML renderen door de html methode van de Resultaten klasse. De Resultaat object bevat alles wat nodig is om de inhoud weer te geven, zoals responscode, headers en cookies. Opmerking: Guice's @Singleton annotatie staat slechts één instantie van de controller in de hele app toe. Voor de inhoudsopgave methode, zal Ninja het HTML-bestand zoeken - inhoudsopgave.ftl.html onder de views / ApplicationController directory. Ninja gebruikt de Freemarker-sjabloonengine voor HTML-weergave. Dus alle bestanden onder keer bekeken zou de .ftl.html uitbreiding. Laten we het ikndex.ftl.html bestand voor het inhoudsopgave methode: Hier hebben we de door Ninja geleverde gebruikt i18n tag om het halloMsg eigendom van de message.properties het dossier. We zullen dit later in de sectie internationalisering verder bespreken. Vervolgens definiëren we de route voor het verzoek om het inhoudsopgave methode. Ninja gebruikt de Routes klasse in de conf pakket om een URL toe te wijzen aan een bepaalde methode van de controller. Laten we een route toevoegen om toegang te krijgen tot het inhoudsopgave methode van de Applicatiecontroller: Dat is het! We zijn helemaal klaar om toegang te krijgen tot het inhoudsopgave pagina op localhost: 8080 / index: Zoals eerder besproken, gebruikt Ninja Jackson voor JSON-rendering. Om JSON-inhoud weer te geven, kunnen we de json methode van de Resultaten klasse. Laten we de userJson methode in de Applicatiecontroller class en geef de inhoud weer van een simple Hash kaart in JSON: Vervolgens voegen we de vereiste routering toe om toegang te krijgen tot het userJson: Nu kunnen we JSON renderen met localhost: 8080 / userJson: We kunnen een service creëren om de bedrijfslogica gescheiden te houden van de controller en onze service waar nodig injecteren. Laten we eerst een simple maken Gebruikersservice interface om de abstractie te definiëren: Vervolgens implementeren we het Gebruikersservice interface in het UserServiceImpl class en overschrijf de getUserMap methode: Dan binden we de Gebruikersservice interface met de UserServiceImpl klasse met behulp van Ninja's afhankelijkheidsinjectiefunctie van Guice. Laten we de binding toevoegen in het Module klasse beschikbaar in de conf pakket: Als laatste injecteren we de Gebruikersservice afhankelijkheid in de Applicatiecontroller klasse met behulp van de @Injecteren annotatie: We zijn er dus helemaal klaar voor om de Gebruikersservice‘S getUserMap methode in de Applicatiecontroller: Ninja biedt een eenvoudige maar efficiënte manier om succes- en foutmeldingen van verzoeken af te handelen via de functie Flash Scope. Om het in de controller te gebruiken, voegen we de FlashScope argument voor de methode: Merk op omleiding methode van de Resultaten class leidt het doel door naar de opgegeven URL. Vervolgens voegen we een routing toe /flash naar de showFlashMsg methode en pas de weergave aan om de flitsberichten weer te geven: Nu kunnen we de FlashScope in actie bij localhost: 8080 / flash: Ninja biedt een ingebouwde internationaliseringsfunctie die eenvoudig te configureren is. Eerst definiëren we de lijst met ondersteunde talen in het application.conf het dossier: Vervolgens maken we het bestand met standaardeigenschappen - messages.properties voor Engels - met sleutel-waardeparen voor berichten: Evenzo kunnen we de taalcode in de bestandsnaam toevoegen voor een taalspecifiek eigenschappenbestand, bijvoorbeeld message_fr.properties bestand voor Frans: Zodra de configuraties klaar zijn, kunnen we internationalisering eenvoudig inschakelen in het Applicatiecontroller klasse. We hebben twee manieren, ofwel door de Lang klasse of de Berichten klasse: Gebruik vervolgens de Lang klasse, kunnen we de taal van het resultaat instellen: Evenzo, met behulp van de Berichten klas, kunnen we een taalspecifiek bericht krijgen: Ninja ondersteunt JPA 2.0 en gebruikt Hibernate om persistentie in de webtoepassing mogelijk te maken. Het biedt ook ingebouwde H2-databaseondersteuning voor snelle ontwikkeling. We hebben een Entiteit class om verbinding te maken met een tabel in de database. Hiervoor volgt Ninja de conventie om te zoeken naar de entiteitsklassen in het modellen pakket. Dus we maken het Gebruiker entiteitsklasse daar: Vervolgens configureren we de slaapstand en stellen we de details voor de databaseverbinding in. Voor de Hibernate-configuratie verwacht Ninja het persistence.xml bestand in het src / main / java / META-INF directory: Vervolgens voegen we de gegevens van de databaseverbinding toe aan application.conf: Als laatste injecteren we de instantie van de EntityManager in de Applicatiecontroller met behulp van Guice's Aanbieder klasse: Dus we zijn klaar om de EntityManager om het Gebruiker voorwerp: Evenzo kunnen we de EntityManager om de Gebruiker object van de DB: Hier, Ninja's @BuienRadarNL annotatie zal alles afhandelen over de databaseverbindingen zonder transacties te behandelen. Daarom kan het handig zijn voor alleen-lezen zoekopdrachten, waar we meestal geen transacties nodig hebben. Ninja biedt ingebouwde ondersteuning voor bean-validaties door de JSR303-specificaties te volgen. Laten we de functie eens bekijken door een eigenschap te annoteren in de Gebruiker entiteit met de @Niet nul annotatie: Vervolgens zullen we het reeds besproken wijzigen insertUser methode in de Applicatiecontroller om de validatie mogelijk te maken: We hebben Ninja's gebruikt @ JSR303Validatie annotatie om de validatie van het Gebruiker voorwerp. Vervolgens hebben we het Validatie argument om met validaties te werken via methoden zoals hasSchendingen, getViolations, en addViolation. Als laatste, de FlashScope object wordt gebruikt om de validatiefout op het scherm weer te geven. Opmerking: Ninja volgt de JSR303-specificaties voor bean-validaties. De JSR380-specificatie (Bean Validation 2.0) is echter de nieuwe standaard. In dit artikel hebben we het Ninja-webframework onderzocht - een full-stack framework dat handige functies biedt met behulp van populaire Java-bibliotheken. Om te beginnen hebben we een eenvoudige webapplicatie gemaakt met controllers, modellen, en Diensten. Vervolgens hebben we JPA-ondersteuning in de app ingeschakeld voor persistentie. Tegelijkertijd zagen we een paar basisfuncties zoals routes, JSON-rendering, internationalisatie en Flash-scopes. Als laatste hebben we de validatieondersteuning van het framework onderzocht. Zoals gewoonlijk zijn alle code-implementaties beschikbaar op GitHub.5. Verantwoordelijke
@Singleton public class ApplicationController {public Result index () {return Results.html (); }}
6. Bekijken
Ninja: Index-gebruiker Json
7. Route
openbare klasse Routes implementeert ApplicationRoutes {@Override public void init (routerrouter) {router.GET (). route ("/ index"). met (ApplicationController :: index); }}
8. JSON-weergave
openbaar resultaat userJson () {HashMap userMap = nieuwe HashMap (); userMap.put ("naam", "Norman Lewis"); userMap.put ("email", "[email protected]"); return Results.json (). render (gebruiker); }
router.GET (). route ("/ userJson"). met (ApplicationController :: userJson);
9. Dienst
openbare interface UserService {HashMap getUserMap (); }
openbare klasse UserServiceImpl implementeert UserService {@Override openbare HashMap getUserMap () {HashMap userMap = nieuwe HashMap (); userMap.put ("naam", "Norman Lewis"); userMap.put ("email", "[email protected]"); return userMap; }}
@Singleton public class Module breidt AbstractModule uit {protected void configure () {bind (UserService.class) .to (UserServiceImpl.class); }}
openbare klasse ApplicationController {@Inject UserService userService; // ...}
openbaar resultaat userJson () {HashMap userMap = userService.getUserMap (); return Results.json (). render (userMap); }
10. Flitsbereik
openbaar resultaat showFlashMsg (FlashScope flashScope) {flashScope.success ("Succesbericht"); flashScope.error ("Foutmelding"); return Results.redirect ("/ home"); }
$ {flash.error} $ {flash.success}
11. Internationalisering
application.languages = fr, en
header.home = Home! helloMsg = Hallo, welkom bij Ninja Framework!
header.home = Accueil! helloMsg = Bonjour, bienvenue dans Ninja Framework!
@Singleton openbare klasse ApplicationController {@Inject Lang lang; @Inject Berichten msg; // ...}
Resultaat resultaat = Results.html (); lang.setLanguage ("fr", resultaat);
Optionele taal = Optioneel.of ("fr"); String helloMsg = msg.get ("helloMsg", taal) .get ();
12. Volharding
12.1. Model
@Entity openbare klasse Gebruiker {@Id @GeneratedValue (strategie = GenerationType.AUTO) Lange id; openbare tekenreeks voornaam; openbare String-e-mail; }
12.2. Configuratie
org.hibernate.jpa.HibernatePersistenceProvider
ninja.jpa.persistence_unit_name = dev_unit db.connection.url = jdbc: h2: ./ devDb db.connection.username = sa db.connection.password =
12.3. EntityManager
openbare klasse ApplicationController {@Inject Provider entityManagerProvider; // ...}
@ Transactional public Resultaat insertUser (gebruiker gebruiker) {EntityManager entityManager = entityManagerProvider.get (); entiteitManager.persist (gebruiker); entiteitManager.flush (); return Results.redirect ("/ home"); }
@UnitOfWork openbaar resultaat fetchUsers () {EntityManager entityManager = entityManagerProvider.get (); Query q = entityManager.createQuery ("SELECT x UIT gebruiker x"); Lijst gebruikers = (Lijst) q.getResultList (); return Results.json (). render (gebruikers); }
13. Validatie
public class Gebruiker {// ... @NotNull public String firstName; }
@Transactional public Result insertUser (FlashScope flashScope, @ JSR303Validation User user, Validation validation) {if (validation.getViolations (). Size ()> 0) {flashScope.error ("Validatiefout: gebruiker kan niet worden aangemaakt"); } anders {EntityManager entityManager = entitiyManagerProvider.get (); entiteitManager.persist (gebruiker); entiteitManager.flush (); flashScope.success ("Gebruiker '" + gebruiker + "' is succesvol aangemaakt"); } return Results.redirect ("/ home"); }
14. Conclusie