背景
目前我所使用的打包方式:
- 首先通过
npm run build
命令将前端页面打包成静态资源 - 将静态资源复制到SpringBoot项目的 /resources/static 目录下
问题
- 按照如上方式操作后,只能通过http://ip:port/index.html访问,然后通过点击按钮/菜单的形式实现路由跳转。
- 成功打包并部署系统后,用户访问URL收藏页面,下次直接点击收藏的页面会出现一片空白
原因: 用户访问URL后,Vue-Router会跳转到首页(/index)或登录页面(/login),此时用户收藏当前页面的URL为http://ip:port/login,导致无法正常访问
解决
后端配置
自定义 GlobalErrorController
具体原因请参考 blog.csdn.net/qq_29684305… 以及 ErrorMvcAutoConfiguration 和 BasicErrorController源码 重写后的代码如下:
@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class GlobalErrorController extends AbstractErrorController {
private static final Logger log = LoggerFactory.getLogger(GlobalErrorController.class);
private final ErrorProperties errorProperties;
public GlobalErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
super(errorAttributes);
errorProperties = serverProperties.getError();
}
@Override
public String getErrorPath() {
return this.errorProperties.getPath();
}
/**
* 通过网页直接访问,出现404错误时会执行此方法,此处将页面重定向到index.html,并添加真实的路由地址交由前台处理
*
*/
@RequestMapping(
produces = {"text/html"}
)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(HttpStatus.FOUND.value());
String routePath = ((String)model.get("path"));
try {
response.sendRedirect("/index.html?route="+routePath);
} catch (IOException e) {
log.error("重定向到首页出错,错误原因: {}",e.getMessage());
}
return null;
}
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = this.getStatus(request);
return new ResponseEntity(body, status);
}
private boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
ErrorProperties.IncludeStacktrace include = this.getErrorProperties().getIncludeStacktrace();
if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
return true;
} else {
return include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM ? this.getTraceParameter(request) : false;
}
}
private ErrorProperties getErrorProperties() {
return this.errorProperties;
}
}
前端配置
router.afterEach((to, form) => {
// 添加到后置导航守卫是因为跳转index.html后Vue / Vue-Router 实例化完成后路由才会被挂载,如果放在前置导航首位则路由跳转不成功
if (to.path === "/index.html") {
// 获取真实路由参数
var routePath = getQueryVariable("route");
if (routePath) {
// URI解码
routePath = decodeURIComponent(routePath);
// 如果默认跳转到首页,则不做二次路由跳转
if (routePath !== '/index.html') {
router.replace(routePath);
}
}
}
NProgress.done()
})