Einführung in ActiveWeb
1. Überblick
In diesem Artikel werden wir dieActiveweb veranschaulichen - ein Full-Stack-Webframework von JavaLite - das alles bietet, was für die Entwicklung dynamischer Webanwendungen oder REST-vollständiger Webdienste erforderlich ist.
2. Grundlegende Konzepte und Prinzipien
Activeweb nutzt "Konvention über Konfiguration" - was bedeutet, dass es konfigurierbar ist, aber sinnvolle Standardeinstellungen hat und keine zusätzliche Konfiguration erfordert. Wir müssen nur einige vordefinierte Konventionen befolgen, wie z. B. die Benennung von Klassen, Methoden und Feldern in einem bestimmten vordefinierten Format.
Es vereinfacht auch die Entwicklung, indem die Quelle neu kompiliert und in den laufenden Container geladen wird (standardmäßig Jetty).
Für das Abhängigkeitsmanagement wird Google Guice als DI-Framework verwendet. Um mehr über Guice zu erfahren, werfen Sie einen Blick auf unsereguide here.
3. Maven Setup
Fügen Sie zunächst die erforderlichen Abhängigkeiten hinzu:
org.javalite
activeweb
1.15
Die neueste Version finden Sie unterhere.
Zum Testen der Anwendung benötigen wir außerdem die Abhängigkeit vonactiveweb-testing:
org.javalite
activeweb-testing
1.15
test
Schauen Sie sich die neueste Versionhere an.
4. Anwendungsstruktur
Wie bereits erwähnt, muss die Anwendungsstruktur einer bestimmten Konvention entsprechen. So sieht das für eine typische MVC-Anwendung aus:
Wie wir sehen können, sollten sichcontrollers,service,config undmodels in ihrem eigenen Unterpaket im Paketapp befinden.
Die Ansichten sollten sich im VerzeichnisWEB-INF/viewsbefinden und jeweils ein eigenes Unterverzeichnis haben, das auf dem Controller-Namen basiert. Zum Beispiel sollteapp.controllers.ArticleController einarticle/-Unterverzeichnis haben, das alle Ansichtsdateien für diesen Controller enthält.
Der Bereitstellungsdeskriptor oder dieweb.xml sollten normalerweise<filter> und die entsprechenden<filter-mapping>. enthalten. Da das Framework ein Servlet-Filter ist, gibt es anstelle einer<servlet>-Konfiguration eine Filterkonfiguration:
...
dispatcher
org.javalite.activeweb.RequestDispatcher
...
...
Wir benötigen auch<init-param>root_controller, um den Standard-Controller für die Anwendung zu definieren - ähnlich einemhome-Controller:
...
root_controller
home
...
5. Controller
Controller sind die Hauptkomponenten einer ActiveWeb-Anwendung. Wie bereits erwähnt, sollten sich alle Controller im Paketapp.controllersbefinden:
public class ArticleController extends AppController {
// ...
}
Beachten Sie, dass der Controllerorg.javalite.activeweb.AppController. erweitert
5.1. Controller-URL-Zuordnung
Die Controller werden gemäß der Konvention automatisch einer URL zugeordnet. Zum Beispiel werdenArticleController zugeordnet:
http://host:port/contextroot/article
Damit würde ihnen nun standardmäßig eine Standardaktion in der Steuerung zugeordnet. Aktionen sind nichts anderes als Methoden innerhalb des Controllers. Nennen Sie die Standardmethodeindex():
public class ArticleController extends AppController {
// ...
public void index() {
render("articles");
}
// ...
}
Bei anderen Methoden oder Aktionen hängen Sie den Methodennamen an die URL an:
public class ArticleController extends AppController {
// ...
public void search() {
render("search");
}
}
Die URL:
http://host:port/contextroot/article/search
Wir können sogar Controller-Aktionen basierend auf HTTP-Methoden durchführen. Kommentieren Sie die Methode einfach mit einem der@POST, @PUT, @DELETE, @GET, @HEAD.. Wenn wir eine Aktion nicht mit Anmerkungen versehen, wird sie standardmäßig als GET betrachtet.
5.2. Controller-URL-Auflösung
Das Framework generiert die Controller-URL anhand des Controllernamens und des Unterpaketnamens. Zum Beispielapp.controllers.ArticleController.java die URL:
http://host:port/contextroot/article
Befindet sich der Controller in einem Unterpaket, lautet die URL einfach:
http://host:port/contextroot/example/article
Bei einem Controllernamen mit mehr als einem Wort (z. B.app.controllers.PublishedArticleController.java) wird die URL durch einen Unterstrich getrennt:
http://host:port/contextroot/published_article
5.3. Anforderungsparameter abrufen
Innerhalb eines Controllers erhalten wir Zugriff auf die Anforderungsparameter mit den Methodenparam() oderparams() aus den MethodenAppController class.. Die erste Methode verwendet ein String-Argument - den Namen des abzurufenden Parameters:
public void search() {
String keyword = param("key");
view("search",articleService.search(keyword));
}
Und wir können die später verwenden, um alle Parameter zu erhalten, wenn wir müssen:
public void search() {
Map criterion = params();
// ...
}
6. Ansichten
In der ActiveWeb-Terminologie werden Ansichten häufig als Vorlagen bezeichnet. Dies liegt hauptsächlich daran, dass anstelle von JSPs die Template-Engine von ApacheFreeMarkerverwendet wird. Sie können mehr über FreeMarkerin our guide, here lesen.
Platzieren Sie die Vorlagen im Verzeichnis vonWEB-INF/views. Jeder Controller sollte ein Unterverzeichnis mit allen von ihm benötigten Vorlagen haben.
6.1. Controller View Mapping
Wenn ein Controller getroffen wird, wird die Standardaktionindex() ausgeführt und das Framework wählt die VorlageWEB-INF/views/article/index.ftl aus dem Verzeichnis "Ansichten" für diesen Controller aus. In ähnlicher Weise würde für jede andere Aktion die Ansicht basierend auf dem Aktionsnamen ausgewählt.
Dies ist nicht immer das, was wir möchten. Manchmal möchten wir möglicherweise einige Ansichten zurückgeben, die auf der internen Geschäftslogik basieren. In diesem Szenario stammenwe can control the process with the render() method aus der übergeordneten Klasseorg.javalite.activeweb.AppController:
public void index() {
render("articles");
}
Beachten Sie, dass sich der Speicherort der benutzerdefinierten Ansichten auch im selben Ansichtsverzeichnis für diesen Controller befinden sollte. Ist dies nicht der Fall, stellen Sie dem Vorlagennamen den Verzeichnisnamen voran, in dem sich die Vorlage befindet, und übergeben Sie ihn an die Methoderender():
render("/common/error");
6.3. Ansichten mit Daten
Um Daten an die Ansichten zu senden, bietetorg.javalite.activeweb.AppController die Methodeview():
view("articles", articleService.getArticles());
Dies erfordert zwei Parameter. Erstens der Objektname, mit dem auf das Objekt in der Vorlage zugegriffen wird, und zweitens ein Objekt, das die Daten enthält.
Wir können auch die Methodeassign()verwenden, um Daten an die Ansichten zu übergeben. Es gibt absolut keinen Unterschied zwischen den Methoden von view () undassign()- wir können eine davon auswählen:
assign("article", articleService.search(keyword));
Ordnen wir die Daten in der Vorlage zu:
<@content for="title">Articles@content>
...
<#list articles as article>
${article.title}
${article.author}
${article.words}
${article.date}
#list>
7. Abhängigkeiten verwalten
Um Objekte und Instanzen zu verwalten, verwendet ActiveWeb Google Guice als Framework für die Abhängigkeitsverwaltung.
Nehmen wir an, wir benötigen eine Serviceklasse in unserer Anwendung. Dies würde die Geschäftslogik von den Controllern trennen.
Erstellen wir zunächst eine Serviceschnittstelle:
public interface ArticleService {
List getArticles();
Article search(String keyword);
}
Und die Umsetzung:
public class ArticleServiceImpl implements ArticleService {
public List getArticles() {
return fetchArticles();
}
public Article search(String keyword) {
Article ar = new Article();
ar.set("title", "Article with "+keyword);
ar.set("author", "example");
ar.set("words", "1250");
ar.setDate("date", Instant.now());
return ar;
}
}
Binden wir diesen Dienst nun als Guice-Modul:
public class ArticleServiceModule extends AbstractModule {
@Override
protected void configure() {
bind(ArticleService.class).to(ArticleServiceImpl.class)
.asEagerSingleton();
}
}
Registrieren Sie dies schließlich im Anwendungskontext und fügen Sie es nach Bedarf in die Steuerung ein:
public class AppBootstrap extends Bootstrap {
public void init(AppContext context) {
}
public Injector getInjector() {
return Guice.createInjector(new ArticleServiceModule());
}
}
Beachten Sie, dass dieser KonfigurationsklassennameAppBootstrap sein muss und sich im Paketapp.config befinden sollte.
Zum Schluss injizieren wir es wie folgt in den Controller:
@Inject
private ArticleService articleService;
8. Testen
Unit-Tests für eine ActiveWeb-Anwendung werden mit der BibliothekJSpecvon JavaLite geschrieben.
Wir verwenden die Klasseorg.javalite.activeweb.ControllerSpecvon JSpec, um unseren Controller zu testen, und benennen die Testklassen nach einer ähnlichen Konvention:
public class ArticleControllerSpec extends ControllerSpec {
// ...
}
Beachten Sie, dass der Name dem Controller ähnelt, den es testet, und dass am Ende eine „Spezifikation“ steht.
Hier ist der Testfall:
@Test
public void whenReturnedArticlesThenCorrect() {
request().get("index");
a(responseContent())
.shouldContain("Introduction to Mule ");
}
Beachten Sie, dass die Methoderequest() den Aufruf des Controllers simuliert und die entsprechende HTTP-Methodeget(), den Aktionsnamen als Argument verwendet.
Wir können Parameter auch mit der Methodeparams() an die Steuerung übergeben:
@Test
public void givenKeywordWhenFoundArticleThenCorrect() {
request().param("key", "Java").get("search");
a(responseContent())
.shouldContain("Article with Java ");
}
Mit dieser fließenden API können wir auch Methoden verketten, um mehrere Parameter zu übergeben.
9. Anwendung bereitstellen
Es ist möglich, die Anwendung in einem beliebigen Servlet-Container wie Tomcat, WildFly oder Jetty bereitzustellen. Die einfachste Möglichkeit zum Bereitstellen und Testen ist natürlich die Verwendung des Maven Jetty-Plugins:
...
org.eclipse.jetty
jetty-maven-plugin
9.4.8.v20171121
manual
10000
...
Die neueste Version des Plugins isthere.
Jetzt können wir endlich loslegen:
mvn jetty:run
10. Fazit
In diesem Artikel haben wir die grundlegenden Konzepte und Konventionen des ActiveWeb-Frameworks kennengelernt. Darüber hinaus verfügt das Framework über mehr Funktionen und Fähigkeiten als hier beschrieben.
Bitte beziehen Sie sich auf die offiziellendocumentation für weitere Details.
Und wie immer ist der im Artikel verwendete Beispielcodeover on GitHub verfügbar.