it-swarm.com.de

Spring catch all route für index.html

Ich entwickle ein Spring-Backend für eine reaktionsbasierte Einzelseitenanwendung, in der ich reaktiver Router für das clientseitige Routing verwende.

Neben der Seite index.html liefert das Backend Daten im Pfad /api/**.

Um meine index.html von src/main/resources/public/index.html im Root-Pfad / meiner Anwendung bereitzustellen, habe ich einen Ressourcen-Handler hinzugefügt

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/").addResourceLocations("/index.html");
}

Ich möchte die index.html-Seite bereitstellen, wenn keine andere Route passt, z. wenn ich einen anderen Pfad als /api anrufe.

Wie konfiguriere ich eine solche Catch-All-Route im Frühjahr?

18
oli

Da meine Reakt-App das Stammverzeichnis als Vorwärtsziel verwenden konnte, funktionierte dies für mich

@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
      registry.addViewController("/{spring:\\w+}")
            .setViewName("forward:/");
      registry.addViewController("/**/{spring:\\w+}")
            .setViewName("forward:/");
      registry.addViewController("/{spring:\\w+}/**{spring:?!(\\.js|\\.css)$}")
            .setViewName("forward:/");
  }
}

Um ehrlich zu sein, habe ich keine Ahnung, warum es genau in diesem speziellen Format sein muss, um eine unendliche Weiterleitungsschleife zu vermeiden.

19
Petri Ryhänen

Ich habe eine Polymer-basierte PWA, die in meiner Spring Boot-App gehostet wird, zusammen mit statischen Webressourcen wie Bildern und einer REST - API unter "/ api/...". Ich möchte, dass die clientseitige App das URL-Routing für die PWA verwaltet. Ich verwende Folgendes:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    /**
     * Ensure client-side paths redirect to index.html because client handles routing. NOTE: Do NOT use @EnableWebMvc or it will break this.
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // Map "/"
        registry.addViewController("/")
                .setViewName("forward:/index.html");

        // Map "/Word", "/Word/word", and "/Word/word/Word" - except for anything starting with "/api/..." or ending with
        // a file extension like ".js" - to index.html. By doing this, the client receives and routes the url. It also
        // allows client-side URLs to be bookmarked.

        // Single directory level - no need to exclude "api"
        registry.addViewController("/{x:[\\w\\-]+}")
                .setViewName("forward:/index.html");
        // Multi-level directory path, need to exclude "api" on the first part of the path
        registry.addViewController("/{x:^(?!api$).*$}/**/{y:[\\w\\-]+}")
                .setViewName("forward:/index.html");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/webapp/");
    }
}

Dies sollte auch für Angular- und React-Apps funktionieren.

7
Dan Syrstad

@EnableWebMvc vermeiden

Standardmäßig liefert Spring-Boot statischen Inhalt in src/main/resources:

  • / META-INF/Ressourcen /
  • /Ressourcen/
  • /statisch/
  • /Öffentlichkeit/

Schauen Sie sich an this und this ;

Oder @EnableWebMvc beibehalten und addViewControllers überschreiben

Haben Sie @EnableWebMvc angegeben? Sehen Sie sich dies an: Java Spring Boot: Wie ordne ich mein App-Root ("/") zu index.html zu?

Entweder entfernen Sie @EnableWebMvc oder Sie können addViewControllers neu definieren:

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("forward:/index.html");
}

Oder einen Controller zum Abfangen von / definieren

Sie können einen Blick auf dieses spring-boot-reactjs-Beispielprojekt auf github werfen:

Es macht was Sie mit einem Controller wollen:

@Controller
public class HomeController {

    @RequestMapping(value = "/")
    public String index() {
        return "index";
    }

}

Sein index.html ist unter src/main/resources/templates

7
alexbt

Ich benutze den reaktions- und reaktionsrouter in meiner Spring-Boot-App, und es war so einfach wie das Erstellen eines Controllers, der Zuordnungen zu / und Unterbäumen meiner Website wie /users/** hat

@Controller
public class SinglePageAppController {
    @RequestMapping(value = {"/", "/users/**", "/campaigns/**"})
    public String index() {
        return "index";
    }
}

Api-Aufrufe werden von diesem Controller nicht abgefangen, und Ressourcen werden automatisch verarbeitet.

1
user3086678

Sie haben eine Antwort gefunden, indem Sie diese Frage

@Bean
public EmbeddedServletContainerCustomizer notFoundCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/"));
        }
    };
}
1
oli

Um Ihre spezifische Frage zu beantworten, die das Einsenden der Single-Page-App (SPA) in allen Fällen beinhaltet: mit Ausnahme von der / api -Route, habe ich die Antwort von Petri geändert.

Ich habe eine Vorlage namens polymer, die die index.html für mein SPA enthält. Die Herausforderung bestand also darin, alle Wege außer/api und/public-api an diese Ansicht weiterzuleiten.

In meinem WebMvcConfigurerAdapter überschreibe ich addViewControllers und verwende den regulären Ausdruck: ^ ((?!/Api/|/public-api /).)*$

In Ihrem Fall möchten Sie den regulären Ausdruck: ^ ((?!/Api /).)*$

public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/{spring:^((?!/api/).)*$}").setViewName("polymer");
    super.addViewControllers(registry);
}

Dies führt dazu, dass Sie in der Lage sind, http: // localhost oder http: // localhost/community zu drücken, um meinen SPA und alle übrigen Aufrufe, die der SPA erfolgreich an http weitergeleitet hat, zu bedienen : // localhost/api/posts , http: // localhost/public-api/posts usw.

0
Gandalf