Vorwort
Nachdem wir nun spring boot start mit maven konfiguriert haben (siehe Beitrag spring-boot-start mit maven), können wir damit beginnen unser erstes Programm zu schreiben. Hierzu gibt es allerdings ein paar Vorbetrachtungen, die berücksichtigt werden sollten. Per default wird mit spring boot start ein integrierter Webserver gestartet. Das hat den Vorteil, dass wir und keine besonderen Gedanken machen müssen – wir können im Standard einen Webservice mit Datenbankanbindung programmieren, obwohl es sich eigentlich um eine Kommandozeilen-Anwendung handelt. Hier liegt im Nutzen auch gleich das Problem: Wir erkaufen uns mit der Möglichkeit auch gleich einen großen Overhead, der beim Starten mit hochgefahren wird. Hierzu bietet spring boot start aber diverse Möglichkeiten, um das zu umgehen.
Erster Schritt
Als erstes benötigen wir eine ganz einfache Klasse mit einer main-Methode.
package org.sudau.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloWorld {
/**
* main.
* @param args
*/
public static void main(final String[] args) {
SpringApplication.run(HelloWorld.class, args);
System.out.println("Hello World");
}
}
Mit diesem Beispiel haben wir unsere erste spring-boot Application erstellt. Wenn wir uns das log anschauen, das von dieser Anwendung geschrieben wird, sehen wir eigenartige Ausgaben, die zeigen, wie ein TomcatEmbeddedServletContainer initialisiert und auf Port 8080 gestartet wird. Außerdem sehen wir, das verschiedene URL-Mappings exportiert und diverse Filter definiert werden. Wenn wir eine Webanwendung oder einen Webservice erstellen, mag das sinnvoll sein, nicht aber, wenn wir eine einfache Kommandozeilen Anwendung oder einen Fat-Client erstellen wollen.
Es stellt sich nun die Frage, wie wir das umgehen können.
CLI-Anwendung
Im nächsten Schritt werden wir mehrere Verbesserungen gleichzeitig machen. Fangen wir an, dass wir generell keine Ausgaben ins System.out schreiben, sondern einen Logger benutzen. Zusätzlich implementieren wir den CommandLineRunner aus dem SpringFramework. Der Runner sorgt nur dafür, dass wir die run-Methode implementieren müssen.
Um nun die Initialisierung und den Start der Web-Umgebung zu verhindern, rufen wir die Methode setWebEnvironment(false) auf.
Somit kommen wir auf folgenden Code:
package org.sudau.helloworld;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloWorldCliApplication implements CommandLineRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldCliApplication.class);
@Override
public void run(final String... args) throws Exception {
LOGGER.debug("HelloWorldCliApplication started.");
}
public static void main(final String[] args) {
final SpringApplication app = new SpringApplication(HelloWorldCliApplication.class);
app.setLogStartupInfo(true);
app.setWebEnvironment(false);
app.run(args);
}
}
In diesem Beispiel ist es zwar nicht notwendig das Interface CommandLineRunner zu implementieren. Ich folge damit nur einer Konvention, die man beachten sollte, denn innerhalb eines ApplicationContextes können mehrere CommandLineRunner implementiert und mit dem Interface Ordered oder der Annotation @Order in eine Reihenfolge gebracht werden. (siehe hierzu auch das JavaDoc).
Wenn wir unser neues Beispiel ausführen und uns die Ausgabe anschauen, sehen wir keine Web-Umgebung und keinen Export von URL-Mappings oder Webfilter Definitionen. Ein weiterer Effekt: nach erreichen des Endes der Main Methode wird das Programm beendet. Ist die Web-Umgebung nicht deaktiviert, wie im ersten Beispiel, so muss man das Programm manuell beenden.