SpringBoot+Vue打包,通过路由直接访问页面
背景目前我所使用的打包方式:首先通过 npm run build命令将前端页面打包成静态资源将静态资源复制到SpringBoot项目的 /resources/static 目录下编写错误页面配置类,统一重定向到/index.html问题按照如上方式操作后,只能通过http://ip:port/index.html访问,然后通过点击按钮/菜单的形式实现路由跳转。成功打包并部署系统...
·
背景
目前我所使用的打包方式:
- 首先通过
npm run build
命令将前端页面打包成静态资源 - 将静态资源复制到SpringBoot项目的 /resources/static 目录下
- 编写错误页面配置类,统一重定向到
/index.html
问题
- 按照如上方式操作后,只能通过http://ip:port/index.html访问,然后通过点击按钮/菜单的形式实现路由跳转。
- 成功打包并部署系统后,用户访问URL收藏页面,下次直接点击收藏的页面会出现一片空白
原因: 用户访问/index.html后,Vue Router会跳转到根路由,此时用户收藏当前页面的URL可能为http://ip:port/login,导致下一次访问页面出现空白
解决
后端配置
自定义 GlobalErrorController
具体原因请参考 https://blog.csdn.net/qq_29684305/article/details/82286469 以及 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;
}
}
前端配置
思路来源: https://segmentfault.com/q/1010000015880077
router.afterEach((to, form) => {
// 添加到后置导航守卫是因为跳转index.html后Vue / Vue Router 实例化完成后路由才会被挂载,如果放在前置导航首位则路由跳转不成功
if (to.path === "/index.html") {
// 获取真实路由参数
var routePath = getQueryVariable("route");
if (routePath) {
// URI解码(将%2F解码为/)
routePath = decodeURIComponent(routePath);
// 如果默认跳转到首页,则不做二次路由跳转
if (routePath !== '/index.html') {
router.replace(routePath);
}
}
}
NProgress.done()
})
通过如上配置后,再次打包,浏览器中直接输入路由地址会改变两次,示例如下:
- 访问http://ip:port/demo
- 后端重定向到/index.html并附带路由地址,此时地址栏url变为http://ip:port/index.html?route=%2Fdemo (/编码后会变成%2F)
- 后置导航守卫通过javascript操作地址栏实现真实路由的跳转:http://ip:port/demo
2020-05-07补充
- 此方法暂时存在问题,如果在开发环境下访问index.html页面会出现无限重定向导致浏览器崩溃问题,暂无解决方案。
更多推荐
已为社区贡献2条内容
所有评论(0)