2016-08-18 1 views
5

Ich verwende SpringBoot 1.3.5 mit Maven.Springboot - DevTools - RestController nicht immer zugeordnet, wenn Projekt neu erstellen

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.3.5.RELEASE</version> 
</parent> 

Und DevTools

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-devtools</artifactId> 
</dependency> 

Ich benutze IntelliJ IDEA 2016,2, zuvor 2014 mit dem gleichen Problem.

Ich starte meine Springboot-App von Intellij Idea, der erste Start ist alles gut geladen und funktioniert, ich kann auf meine statischen Seiten zugreifen und meine 2 Rest-Controller arbeiten.

2016-08-18 15:27:58.771 INFO 26626 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot[email protected]469d0c02: startup date [Thu Aug 18 15:27:57 CEST 2016]; root of context hierarchy 
2016-08-18 15:27:58.789 INFO 26626 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/authentication/introspect],methods=[GET]}" onto public com.myapp.models.TokenIntrospection com.myapp.resources.AuthenticationResources.introspectToken(java.lang.String) 
2016-08-18 15:27:58.790 INFO 26626 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/configuration],methods=[GET]}" onto public com.myapp.models.AppConfiguration com.myapp.resources.ConfigurationResources.getConfiguration() 
2016-08-18 15:27:58.792 INFO 26626 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 
2016-08-18 15:27:58.793 INFO 26626 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 

Weil einfach „Make-Projekt“ für statischen reload nicht gut funktioniert, verwende ich „Projekt neu erzeugen“ und manchmal, wenn app Neustart, ich habe meinen Controller zugeordnet ist, werden manchmal ein fehlt, manchmal beide fehlen.

Ich habe keine Ahnung von diesem :(

EDIT

@Morfic Lösungen nicht funktioniert hat, so habe ich die Intellij lokalen Server statische Inhalte zu dienen und schlucke-livereload statt . Feder-dev-tools

IJ local server

ich hatte gerade in JS REST Anrufe zu verwalten, wenn ich in dev-Modus bin, weil REST-Ressourcen sind auf localhost: 8080, aber mein stati cs auf localhost: 63342, und aktivieren Sie CORS in meinem Springboot (mit einem Flag in der Eigenschaftendatei, um CORS zu aktivieren oder nicht).

@Configuration 
public class CorsConfig extends WebMvcConfigurerAdapter { 

    @Value("${cors.enabled}") 
    private boolean corsEnabled; 

    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
     super.addCorsMappings(registry); 
     if(corsEnabled) { 
      registry.addMapping("/**") 
        .allowedOrigins("*") 
        .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS") 
        .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization") 
        .allowCredentials(true) 
        .maxAge(3600L); 
     } 
    } 
} 

So Frage noch ausstehende für eine funktionierende Lösung.

Antwort

5

Ich habe es gerade geschafft, dies mit einem einfachen Hallo-Welt-Service zu reproduzieren und Rebuild project ein paar Mal zu verwenden, weil es nur hin und wieder reproduziert. Meine Vermutung ist, dass Dev-Tools herauszufinden, eine Änderung aufgetreten ist, bevor IJ eine Chance hat, & Wiederaufbau vollständig zu reinigen. Wahrscheinlich, sobald die Ressourcen veröffentlicht und bevor die Klassen kompiliert werden, was ich gesehen habe, Blick auf den Ausgang dir, Entwickler-Tools beginnt die Klassen Nachladen, die noch nicht vorhanden sind ...

Im Anschluss an diese Vermutung Ich schaute auf die Logs und Klassen Timestamps und es gibt ungefähr eine 1s Lücke zwischen der Zeit, die dev-tools den Kontext neu startet und dem Zeitpunkt, zu dem meine Klassen auf die Festplatte geschrieben werden. Offensichtlich keine meiner Protokolle angezeigt und Frühjahr autoconfig findet nicht meine Klassen ...

Als Workaround können Sie eine trigger-file verwenden. Fügen Sie es entweder als globale Konfiguration in Ihrem Home-Verzeichnis hinzu, wie im Link vorgeschlagen, oder in Ihrer application.properties Datei. Da jede Änderung an dieser Datei (Erstellung, Löschung, Änderung) außerdem einen Neustart auslösen würde und Rebuild project das Ausgabeverzeichnis bereinigen würde, müssten Sie einen zusätzlichen Pfad definieren, um nach dieser Datei zu suchen. So nehmen wir eine regelmäßige IJ Federbootlauf Konfiguration haben, mit den folgenden 2 in den application.properties:

# name of the file to trigger a restart 
spring.devtools.restart.trigger-file=restarttrigger 

# where else to look for it. Also . evaluates to the app's base dir 
spring.devtools.restart.additional-paths=. 

...Sobald Sie sehen, dass IJ den Build-Prozess abgeschlossen hat, gehen Sie zum Stammverzeichnis der App und fügen Sie Ihre Trigger-Datei hinzu oder löschen Sie sie, je nachdem, ob sie bereits vorhanden ist oder nicht, was zu einem Neustart führen sollte. Ich habe das ein paar Mal getestet, ohne dass es bisher gelungen ist. Im Folgenden eine kurze vide Demo des manuellen Neustart Prozess:

IJ - boot dev tools manual restart

Es gibt ein paar Möglichkeiten, um diesen Prozess zu automatisieren. Neben der Definition eines Artefakts in IJ und der Verwendung einer post-process ant-Aufgabe zum Generieren einer Datei können Sie maven (das Sie bereits verwenden) verwenden, um eine solche Datei zu generieren. Der Nachteil ist, dass Sie maven compile anstelle von Rebuild project verwenden müssen weil IJ Maven nicht aufruft, wenn er die Wiederherstellung durchführt (oder ich habe noch nicht herausgefunden, wie ich das machen soll). Nachfolgend finden Sie eine einfache Konfiguration based on the fact that:

(Anmerkung: In Maven 2.0.5 und höher, mehr Ziele zu einer Phase gebunden sind, in der gleichen Reihenfolge ausgeführt, wie sie in der POM deklariert sind jedoch mehrere Instanzen des Das gleiche Plugin wird nicht unterstützt. Mehrere Instanzen desselben Plugins werden gruppiert, um zusammen ausgeführt und in Maven 2.0.11 und höher geordnet zu werden.

Als solche the compiler plugin is by default bound to the compile phase, also fügen wir eine kleine Aufgabe, die trigger-file mit der application.properties Datei (oder etwas anderes)

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-maven-plugin</artifactId> 
     </plugin> 
     <plugin> 
      <!-- first, compile all we need --> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <version>3.3</version> 
     </plugin> 
     <plugin> 
      <!-- then, generate the trigger-file so dev-tools will restart --> 
      <artifactId>maven-antrun-plugin</artifactId> 
      <version>1.8</version> 
      <executions> 
       <execution> 
        <phase>compile</phase> 
        <configuration> 
         <tasks> 
          <copy file="${project.basedir}/src/main/resources/application.properties" 
            toFile="${project.basedir}/restarttrigger" overwrite="true" /> 
         </tasks> 
        </configuration> 
        <goals> 
         <goal>run</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin> 
    </plugins> 
</build> 

Weitere Update zu generieren:

Suche an den Quellen von FileSystemWatcher.scan() gibt es eine do-while Schleife, die wie folgt interpretiert werden kann: solange es noch sind Änderungen laufend auf dem Dateisystem seit der letzten Überprüfung, warten Sie auf eine (konfigurierbar) Zeit und überprüfen Sie wieder

private void scan() throws InterruptedException { 
    Thread.sleep(this.pollInterval - this.quietPeriod); 
    Map<File, FolderSnapshot> previous; 
    Map<File, FolderSnapshot> current = this.folders; 
    do { 
     previous = current; 
     current = getCurrentSnapshots(); 
     Thread.sleep(this.quietPeriod); 
    } 
    while (isDifferent(previous, current)); 
    if (isDifferent(this.folders, current)) { 
     updateSnapshots(current.values()); 
    } 
} 

Gemäß der documentation, die quietPeriod konfigurierbar ist durch die spring.devtools.restart.quiet-period Eigenschaft, sondern auch Wie oben erwähnt Quelle, muss es einen Wert kleiner als pollInterval konfigurierbar durch spring.devtools.restart.poll-interval sein. So mit den Einstellungen herumgespielt, ich habe ein gutes Ergebnis mit bekam:

# Amount of time (in milliseconds) to wait between polling for classpath changes. 
spring.devtools.restart.poll-interval=3000 

# Amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered. 
spring.devtools.restart.quiet-period=2999 

Am Ende sollten Sie in der Lage sein, diese Werte anpassen, was Ihnen am besten passt.

Nichtsdestotrotz, wenn die Quellen, die Sie ändern, statische Ressourcen wie FE GUI-Seiten sind und abhängig von Ihren Anforderungen, ist es vielleicht besser, ein Tool zu verwenden, das sie von ihrem Standort aus bedient, wie Knoten oder ein ähnlicher einfacher HTTP-Server ...

+0

Wahou sehr schöne Erklärung, danke. Wie Sie wahrscheinlich erraten, kann ich Dateierstellung/Änderung jedes Mal nicht neu laden, wenn ich mein Projekt neu laden möchte :( Und ich habe es nicht erklärt, aber ich benutze Springboot mit 2 Ruhe-Controller und muss oft für statische Dateien – Titmael

+0

I neu erstellen versuchte dies, aber änderte das Problem nicht: http: // stackoverflow.com/a/36839483/1243048 – Titmael

+1

@Titmael mein Vorschlag ist der einfachste und sicherste möglich, da alles kompiliert und verfügbar sein sollte, wenn Sie die Datei erstellen/bearbeiten/entfernen. Leider ist das, was ich gesehen habe, nicht über Mavent möglich, da IJ es nicht für den Build-Prozess aufruft, aber es kann etwas automatisiert sein, ein Artefakt beim Build zu erstellen und die Trigger-Datei mit einem Post-Build-Ant-Target zu kopieren bin interessiert. – Morfic

0

Dieser Teil von @ Morfic Antwort für mich großartig gearbeitet:

# Amount of time (in milliseconds) to wait between polling for classpath changes. 
spring.devtools.restart.poll-interval=3000 

# Amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered. 
spring.devtools.restart.quiet-period=2999 
Verwandte Themen