web-dev-qa-db-ja.com

index.htmlのすべてのルートを春にキャッチ

私は、クライアント側のルーティングに反応ルーターを使用する、反応ベースの単一ページアプリケーション用のスプリングバックエンドを開発しています。

Index.htmlページの他に、バックエンドはパス/api/**でデータを提供します。

アプリケーションのルートパスsrc/main/resources/public/index.html上の/からindex.htmlを提供するために、リソースハンドラーを追加しました

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

私がしたいのは、他のルートが一致しないときは常にindex.htmlページを提供することです。 /api以外のパスを呼び出すとき。

このようなキャッチオールルートを春に設定するにはどうすればよいですか?

26
oli

私の反応アプリはルートを前方ターゲットとして使用できるため、これは私のために機能しました

@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:/");
  }
}

正直に言うと、無限の転送ループを回避するために、この特定の形式にする必要がある理由はわかりません。

25
Petri Ryhänen

Spring Bootアプリ内でホストされるPolymerベースのPWAに加えて、画像などの静的Webリソース、および「/ api/...」の下のREST APIがあります。クライアント側のアプリでPWAのURLルーティングを処理する必要があります。私が使用するものは次のとおりです。

@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/");
    }
}

これは、AngularおよびReactアプリでも機能するはずです。

11
Dan Syrstad

@ EnableWebMvcを避ける

デフォルトでは、Spring-Bootはsrc/main/resourcesの静的コンテンツを提供します。

  • / META-INF/resources /
  • / resources /
  • /静的/
  • /パブリック/

thisthis ;を見てください。

または@EnableWebMvcを保持してaddViewControllersをオーバーライドします

@EnableWebMvcを指定しましたか? Java Spring Boot:アプリのルート(「/」)をindex.htmlにマップする方法?

@EnableWebMvcを削除するか、addViewControllersを再定義できます。

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

または、/をキャッチするコントローラーを定義します

あなたはこれを見ることができます githubのspring-boot-reactjsサンプルプロジェクト

コントローラーを使用して必要なことを行います。

@Controller
public class HomeController {

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

}

そのindex.htmlsrc/main/resources/templatesの下にあります

7
alexbt

私は私のスプリングブートアプリで反応および反応ルーターを使用し、/および/users/**のような私のウェブサイトのサブツリーへのマッピングを持つコントローラーを作成するのと同じくらい簡単でした

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

API呼び出しはこのコントローラーによってキャッチされず、リソースは自動的に処理されます。

2
user3086678

この質問 を見て答えを見つけました

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

すべての場合にシングルページアプリ(SPA)を提供する特定の質問に答えるにはexcept/ api ここでのルートは、ペトリの答えを修正するために私がしたことです。

SPAのindex.htmlを含むpolymerという名前のテンプレートがあります。そのため、チャレンジは/ apiと/ public-apiを除くすべてのルートをそのビューに転送することになりました。

WebMvcConfigurerAdapterでは、addViewControllersをオーバーライドし、正規表現を使用しました:^((?!/ api/|/public-api /).)*$

あなたの場合、正規表現が必要です:^((?!/ api /).)*$

public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

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

これにより、 http:// localhost または http:// localhost/community をヒットして、SPAと、SPAが行う残りのすべての呼び出しを処理できます。 http:// localhost/api/postshttp:// localhost/public-api/posts などに正常にルーティングされました.

0
Gandalf