使用 Spring Boot 的 SPA - 为非 API 请求提供 index.html

问题描述 投票:0回答:2

我目前正在开发一个应该使用单页 React 前端的网页。对于后端,我使用的是 spring boot 框架。

所有 API 调用均应使用前缀为

/api
的 URL,并应由 REST 控制器处理。

所有其他网址应仅提供

index.html
文件。我如何用 Spring 来实现这一目标?

spring spring-mvc spring-boot single-page-application
2个回答
10
投票

实现您想要的最简单方法是实现自定义 404 处理程序。

将这些参数添加到您的 application.properties 中:

spring.resources.add-mappings=false
spring.mvc.throw-exception-if-no-handler-found=true

第一个属性删除所有默认的静态资源处理,第二个属性禁用 Spring 的默认白标签页面(默认情况下 Spring 捕获

NoHandlerFoundException
并提供标准白标签页面)

将 404 处理程序添加到您的应用程序上下文中:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class PageNotFoundController {
    @ExceptionHandler(NoHandlerFoundException.class)
    public String handleError404() {
            return "redirect:/index.html";
    }
}

最后,您需要添加自定义视图解析器来提供静态内容(在本例中为index.html)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

    @Bean
    public ViewResolver viewResolver() {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(InternalResourceView.class);
        return viewResolver;
    }

}

您的

index.html
应放置在
/resources/static/
目录中。


1
投票

也许最好使用 Nginx 将 /api 重定向到 api 路径,并将其他所有内容重定向到 index.html。

但如果真的想要:

请确保在 pom.xml 中包含 thymeleaf:

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

将这些添加到您的 application.properties 中

spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
spring.thymeleaf.check-template-location=true

以下是可选的。例如,如果您想更改存储静态文件的路径,您可能需要这个。

spring.web.resources.static-locations=classpath:/your/path/to/the/*folder*/that/has/index/file
spring.thymeleaf.prefix=classpath:/your/path/to/the/*folder*/that/has/index/file

创建你的 SpaController.java 然后这样写:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SpaController {
    @RequestMapping(value = {"/{path:^(?!api|public)[^\\.]*}", "/**/{path:^(?!api|public).*}/{path:[^\\.]*}"})
    public String get(){
        return "index";
    }
}

或者,在 Kotlin 中:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SpaController {
    @RequestMapping(value = [
        "/{path:^(?!api|public)[^\\.]*}",
        "/**/{path:^(?!api|public).*}/{path:[^\\.]*}"
    ])
    public fun get() : String
    {
        return "index";
    }
}

但请注意,这可能不适用于像

/***/***/***
这样的路径(斜线超过 2 个)。如果您需要这种情况,您需要添加或修改匹配器。

另请参阅:Spring 捕获 index.html 的所有路由

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.