Ich habe eine Spring-Boot-Anwendung, die Folgendes tun muss:
Ich möchte diese Anwendung auch in meiner IDE (Eclipse- oder IntelliJ IDEA Community) ausführen können, indem Sie mit der rechten Maustaste auf main
klicken und sie ausführen.
Hier sind die interessanten Teile meiner pom.xml (Beachten Sie, dass ich nicht von Spring-Boot-Starter-Parent Pom erben):
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>provided</scope>
</dependency>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Hier ist meine SpringBootServletInitializer
:
@Configuration
@EnableAutoConfiguration
@ComponentScan("com.company.theproject")
public class Application extends SpringBootServletInitializer
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(Application.class);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
Beim Ausführen des main in IDE erhalte ich den folgenden Fehler:
org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.Java:183) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.Java:156) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:130) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
... 12 common frames omitted
Scheint, als würde mvn spring-boot:run
etwas mehr Magie bewirken, was nicht der Fall ist, wenn main
direkt ausgeführt wird.
Das Entfernen des Bereichs provided
aus der spring-boot-starter-Tomcat
-Abhängigkeit behebt dieses Problem, verursacht jedoch Probleme, wenn der Krieg in einem Servlet-Container ausgeführt wird.
Im Moment ist der einzige "Fix", den ich gefunden habe, mvn spring-boot:run
innerhalb von IntelliJ IDEA auszuführen, anstatt das main direkt auszuführen. Obwohl dies eine akzeptable Problemumgehung ist, würde ich trotzdem gerne wissen, warum dies nicht funktioniert und ob es behoben werden kann.
Ich glaube, das könnte mit https://youtrack.jetbrains.com/issue/IDEA-107048 zusammenhängen.
IntelliJ IDEA fügt die provided
-Abhängigkeiten nicht in den CLASSPATH ein, und wie Andy bereits erwähnt hat, kann spring den eingebetteten Servlet-Container nicht erstellen.
Sie haben seit 2005 eine Funktionsanforderung dazu: https://youtrack.jetbrains.com/issue/IDEABKL-99
Zu den in den Kommentaren erwähnten Problemumgehungen gehört, dass ein gefälschtes Modul mit den erforderlichen Bibliotheken als Klassenpfad verwendet wird, das JVM-Argument -Xbootclasspath verwendet wird oder benutzerdefinierte Maven-Profile zum Ausführen von (compiled
) vs. building (provided
) verwendet werden.
Eine Problemlösung, die stark von https://youtrack.jetbrains.com/issue/IDEA-140041 inspiriert ist, besteht darin, Ihre Hauptklasse mit dem Testklassenpfad (der das eingebettete Servlet enthält) zu starten.
Run
-> Edit Configurations
-> Add new configuration
-> Wählen Sie Application
type aus.Main class
auf <your.main.class>
Use classpath of module
auf <*>_test
(das Testmodul!)Ok
und Run
es!Ich konnte diese Arbeit machen, indem ich den Bereich der Spring-Boot-Starter-Tomcat-Abhängigkeit in "Projektstruktur"> "Abhängigkeiten" in "Kompilieren" änderte. Dies wirkt sich nicht auf pom.xml aus, ermöglicht jedoch, dass diese Abhängigkeiten für die Konfiguration des Spring-Startlaufs verfügbar sind
Klicken Sie hier, um zu sehen, wo Sie diese Einstellung in der Idee ändern können
mvn spring-boot:run
enthält provided
-Abhängigkeiten, wenn der Klassenpfad erstellt wird. Es klingt wie IntelliJ IDEA nicht. Ohne Tomcat für den Klassenpfad kann Spring Boot keinen eingebetteten Servlet-Container erstellen, der die angegebene Ausnahme verursacht. Dies ist wahrscheinlich ein Fehler in IntelliJ. Wenn es keinen Container gibt, der die Abhängigkeit bereitstellt, muss es wirklich auf dem Klassenpfad liegen.
Sie können das Problem möglicherweise beheben, indem Sie den Standardklassenpfad überschreiben, den IntelliJ beim Ausführen der Hauptmethode verwendet, um die spring-boot-starter-Tomcat
-Abhängigkeit einzuschließen.
Ich konnte dieses Problem in Intellij IDEA 2017.2 umgehen, indem ich die bereitgestellte Libaray (Spring-Boot-Starter-Tomcat) zur Projektkonfiguration hinzufügte.
Wählen Sie Datei -> Projektstruktur. Wählen Sie Bibliotheken aus und fügen Sie eine neue Projektbibliothek hinzu (type = From Maven ...). Suchen Sie mit Hilfe des Dialogs nach Spring-Boot-Starter-Tomcat, wählen Sie die richtige Version aus und fügen Sie diese durch Klicken auf OK hinzu. Die Bibliothek wird der Liste der externen Bibliotheken hinzugefügt.
Der Nachteil ist, dass Sie bei einer Änderung der Spring-Boot-Version daran denken müssen, diese Bibliothek zu löschen und die neue Version hinzuzufügen.
Mit dem folgenden Profil und den folgenden Anweisungen können Sie maven ein Profil hinzufügen, das die Entwicklung in IntelliJ ermöglicht, ohne dass Änderungen an anderen Umgebungen vorgenommen werden müssen.
<!-- Leave original dependency as-is -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<profiles>
<!-- Enable this profile to run in IntelliJ. IntelliJ excludes provided dependencies from compile by default. -->
<profile>
<id>intellij</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
</profiles>
Klicken Sie auf die Schaltfläche Maven Projects auf der rechten Seite von IntelliJ und wählen Sie unter Profiles die Option intellij
aus.
Ich finde diese page und verwende das Maven-Profil, um die Profile zu verwalten.
<profiles>
<profile>
<id>PROD</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>DEV</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-Tomcat</artifactId>
<scope>TEST</scope>
</dependency>
</dependencies>
</profile>
</profiles>
und konfigurieren Sie die Hauptklasse beforeLanuce
, setzen Sie den Befehl
mvn clean compile -Pdev
Folge diesen Schritten:
Klicken Sie oben rechts im intellij-Fenster auf die Dropdown-Liste und wählen Sie Konfiguration bearbeiten. Ein neues Fenster wird geöffnet.
Klicken Sie in diesem Fenster oben links auf die Schaltfläche "+" und wählen Sie "Sprint Boot" aus.
Fügen Sie dann Ihre Hauptklasse und andere Details hinzu (siehe Screenshot . ).
Führen Sie jetzt die Anwendung aus.
Ich hatte das gleiche Problem mit IntelliJ 2018. Meine Lösung ist:
Gehen Sie zu Run
-> Edit Configurations
.
Wählen Sie Application
&& und wählen Sie Ihr aktuelles Projekt.
Include dependencies with "Provided" scope
überprüfen.
OK
-> RUN