背景
在做java端上应用开发的时候,从资源和部署操作成本两方面考虑,一般会将前端的静态资源直接与后端应用一起打包,通过springboot内嵌的Tomcat提供web服务。进入web首页登录一直到后续业务流程正向操作,页面都能正常加载静态资源,但触发页面刷新操作的时候,就出现了Whitelabel Error Page,访问不成功。本文针对此问题做解答。
1. springboot web项目搭建开发
在pom文件中增加thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置静态资源处理器:
java
public class BaseWebConfig implements WebMvcConfigurer {
private LoginInterceptor loginInterceptor;
private PermissionInterceptor permissionInterceptor;
public List<String> whiteUrl = new ArrayList<>(Arrays.asList(
"/login",
"/doLogin",
"/css/**", // 排除css目录下的所有资源
"/js/**", // 排除js目录下的所有资源
"/images/**", // 排除images目录下的所有资源
"/favicon.ico", // 排除favicon.ico
"/static/**" // 排除static目录下的所有资源
));
// 登录拦截器,后端所有的接口都是api/开头
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns(whiteUrl)
.order(1);
}
// 静态资源放到html目录下
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/html/");
}
// 默认进入登录页
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/index.html");
}
}
配置启动thymeleaf
java
spring.thymeleaf.prefix=classpath:/html/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
静态文件结构:
|-- src
| |--main
| | |-- resources
| | |-- application.properties
| | | |-- html
| | | | |-- index.html
| | | | |-- app.js
...
2. 问题暴露
访问后端localhost:8080/login,正常跳转到登录页。登录成功后,浏览器中的地址因为前端自动的路由规则,变成了
localhost:8080/edge?ownerId=jcknuxh&tab=sub1-data-management
看网络请求也都正常

在浏览器页面刷新,直接进入Whitelabel Error Page

查看很多网上的教程,有建议直接拦截所有的请求,转发到index.html视图,如下代码:
java
@Controller
public class IndexController{
@GetMapping("{/path})
public String index(@PathVariable String path){
return "forward:/index.html";
}
}
然后就出现了错误:
circular view path
3. 问题解决
解题的思路是参照NGINX加载静态页面,当有不识别的页面的时候,直接跳转到index.html页面。Nginx中的配置如下:
XML
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
在springboot中怎么配置呢?
java
// 默认进入登录页
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{path;[^\\.]*}").setViewName("forward:/index.html");
}
问题就解决了。原理是当遇到不识别的页面的时候,就跳转到首页,首页有对应的js、css请求路由,从而在刷新页面的时候,正常渲染。