也谈SpringBoot+Vue项目出现Whitelabel Error Page问题的解决
1,项目背景
某项目采用前后端分离,实现基于浏览器的单网页应用。
前端采用vue2.6.14,使用history模式的vueRouter,IDE环境是webStorm
后端采用springboot 2.6.11,IDE环境是IDEA
2,问题描述
该项目在IDE环境下调试正常,在浏览器地址栏中输入地址并直接访问,或者刷新当前网页,显示正常。
但是部署到tomcat9服务器上后发现,页面跳转只能通过网页内部的按钮或菜单点击实现,不能通过浏览器输入或刷新。
否则出现如下404页面, 显示Whitelabel Error Page。
问题在于对前端vueRouter中配置的路径的访问,而对于后端的REST接口的访问是OK的。
3,原因分析
网上关于出现404页面, 显示Whitelabel Error Page的文章多如牛毛。但本人尝试后均告失败。
一个基本说法是,之所以404,是因为浏览器访问vueRouter路径时,均首先按接口方式发送到后端处理,后端找不到接口再返回404错误,然后转前端继续处理。
那么,如何让程序在404时转前端页面(一般是index.html)处理呢?
网上提供了很多方式,如:
- 在tomcat发布目录下的WEB-INF目录下建立web.xml,在其中进行错误处理
- 修改vue.config.js中的publicPath
- 检查router中的base值
- 在routes中设置404处理页面
但本人尝试后均告失败。原因在于后端处理失败后没有转给前端继续处理,所以在前端设计的种种方法无法起到作用。
后来找到一个部署正常的同类项目,比较了二者在刷新网页时web服务器处理逻辑的不同。
刷新正常的项目:
刷新异常的项目:
2023-03-09 14:41:35.105 DEBUG 7212 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : GET "/XXX-1.0-REL/home", parameters={} 2023-03-09 14:41:35.121 DEBUG 7212 --- [nio-8080-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]] 2023-03-09 14:41:35.125 DEBUG 7212 --- [nio-8080-exec-2] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found 2023-03-09 14:41:35.125 DEBUG 7212 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND 2023-03-09 14:41:35.126 DEBUG 7212 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : "FORWARD" dispatch for GET "/XXX-1.0-REL/error", parameters={} 2023-03-09 14:41:35.129 DEBUG 7212 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse) 2023-03-09 14:41:35.151 DEBUG 7212 --- [nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8] 2023-03-09 14:41:35.155 DEBUG 7212 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Exiting from "FORWARD" dispatch, status 404
显然,这就是个转向路径问题。
刷新页面正常的项目,404后能转向index.html页面继续处理;
而刷新页面异常的项目,404后直接转向/error路径,由后端处理结束。
4,解决方案
后经比对两个项目的代码,发现本项目的后端缺少了一个404错误处理机制。
增加一个注册项,让HttpStatus.NOT_FOUND的处理跳转到根目录静态页面即可。
实测通过。以下是代码:
@Component public class ErrorConfig implements ErrorPageRegistrar { @Override public void registerErrorPages(ErrorPageRegistry registry) { ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/"); registry.addErrorPages(error404Page); } }
5,总结
通过spring将后台页面404错误自动转向前端页面处理,无需对web服务器进行任何配置,就能在vue中使用history路径模式,非常简单方便。
本人也是摸索了几天才发现该方案,网上却甚少有该方案的介绍,因此记录在此,以供借鉴。