我目前正在开发一个应该使用单页 React 前端的网页。对于后端,我使用的是 spring boot 框架。
所有 API 调用均应使用前缀为
/api
的 URL,并应由 REST 控制器处理。
所有其他网址应仅提供
index.html
文件。我如何用 Spring 来实现这一目标?
实现您想要的最简单方法是实现自定义 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/
目录中。
也许最好使用 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 个)。如果您需要这种情况,您需要添加或修改匹配器。