Spring捕获index.html的所有路由

oli*_*oli 30 spring spring-mvc catch-all single-page-application spring-boot

我正在开发一个基于反应的单页面应用程序的弹簧后端,我正在使用react-router进行客户端路由.

在index.html页面旁边,后端提供路径上的数据/api/**.

为了从我的应用程序src/main/resources/public/index.html的根路径上提供我的index.html,/我添加了一个资源处理程序

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/").addResourceLocations("/index.html");
}
Run Code Online (Sandbox Code Playgroud)

我想要的是在没有其他路由匹配的情况下提供index.html页面,例如当我调用除了以外的路径时/api.

如何在春季配置这种全能路线?

Pet*_*nen 28

由于我的反应应用程序可以使用root作为前向目标,因此最终为我工作

@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:/");
  }
}
Run Code Online (Sandbox Code Playgroud)

说实话,我不知道为什么它必须完全采用这种特定格式才能避免无限转发循环.

  • 你好,请问代码中的“spring”前缀是什么意思? (7认同)
  • 该正则表达式不适用于连字符 (-) 和下划线 (_)。您可以将“\\w”替换为“^[a-zA-Z\d-_]”,使其适用于包含这些字符的 URL (3认同)
  • @hguser `spring` 是分配匹配部分的变量名。但是,它仅在此处用于在 AntMatcher 中使用正则表达式(https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/AntPathMatcher.html)并且由于没有被使用而没有达到目的。您可以将其更改为其他任何内容,但其目的是启用与正则表达式的匹配。要使用is,请在路径中使用“{spring}”进行重定向或转发,然后您将使用匹配的内容。最后一个条目不明确,因为为两个匹配项分配了相同的变量...... (2认同)

Dan*_*tad 12

我在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/");
    }
}
Run Code Online (Sandbox Code Playgroud)

这也适用于Angular和React应用程序.

  • 谢谢,这对我有用 - 只需将 resourcesLocation 更改为 `classpath:/static/` 即可使其与我的 React 应用程序一起运行。请注意,由于 Spring 5.xx 扩展“WebMvcConfigurerAdapter”已被弃用,因此必须实现“WebMvcConfigurer”。 (5认同)

ale*_*xbt 8

避免@EnableWebMvc

默认情况下,Spring-Boot提供静态内容src/main/resources:

  • / META-INF /资源/
  • /资源/
  • /静态的/
  • /上市/

看看这个这个 ;

或者保留@EnableWebMvc并覆盖addViewControllers

你有没说明@EnableWebMvc?看看这个:Java Spring Boot:如何将我的应用程序根目录("/")映射到index.html?

要么删除@EnableWebMvc,要么可以重新定义addViewControllers:

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

或定义一个控制器来捕获 /

您可以在github上看一下这个spring-boot-reactjs示例项目:

它使用Controller做你想做的事:

@Controller
public class HomeController {

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

}
Run Code Online (Sandbox Code Playgroud)

index.html是在src/main/resources/templates

  • 这并不能解决客户端路由所要求的问题。它仅为根路径提供“index.html”。它不会将“/campaigns/33”等 URL 重定向到“index.html”。 (5认同)

小智 8

我在 Spring Boot 应用程序中使用了 react 和 react-router,这就像创建一个控制器一样简单,该控制器映射到/我的网站的子树,例如/users/** Here is my solution

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

此控制器不会捕获 Api 调用,并且会自动处理资源。