1. 首页
  2. 软件开发
  3. JAVA
  4. SpringBoot+Vue2 History路由模式去掉路径中的#

SpringBoot+Vue2 History路由模式去掉路径中的#

  • 发布于 2024-08-16
  • 0 次阅读

本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net

问题场景

1、前端 vue 项目想去掉 http://localhost:9080/dzjz/fljdyypt#/home 中的#

2、vue 打包后放在 jar 包部署

3、contextPath: /dzjz

4、想要不更改 contextPath 的情况下实现用 ip:port/dzjz/fljdyypt/xxx 方式访问

5、index.html 放在 templates 里面了

前置知识

vue 路由模式

hash(默认)

1、URL 标识中的 '#' 和 后面 URL 片段标识符,被称为 hash

2、第一个 '#' 后面所有字符,浏览器会识别成为位置标识符,只用来标识页面的位置,这些字符都不会发送给服务器

3、单改变 #后面的字符,浏览器只会锚点到相应的位置,不会重新加载 url 去加载新网页

4、底层原理通过 window.addEventListener("hashchange", fun) 监听 hash,去更新视图

history

1、url 中没有#

2、window.history 提供了两类 API:

  1. 跳到某个浏览记录:back(), forward(), go(),
  2. 添加 / 修改历史记录:pushState(), replaceState()

3、也是通过 window.addEventListener('popstate', fun); 监听 url 改变,通过调用 pushState(),replaceState() 来修改当前的 url,但是这种调用 api 的修改只会更新视图,不会向服务器发请求

4、当手动修改 url 地址并访问或者刷新页面,这种方式修改 url 访问请求会直接发送到服务器,比如我直接访问 http://localhost:9080/dzjz/fljdyypt/home 中,如果服务器没有配置对应的视图或者静态资源,那么就会 404

springboot 静态资源

static
  1. 存放静态资源 css js 图片等
  2. 只要静态资源放在类路径下叫做 / static、/public、/resources、 /META-INF/resources 就可以用 当前项目根路径 / + 静态资源名
  3. 请求进来,先找 Controller,不能处理的交给静态资源处理器。静态资源也找不到 -> 响应 404 页面
template
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

模板文件夹,该文件下的页面不能通过地址栏地址直接访问,需要经过 Controller 类来访问

如果你的 index.html 是放在这里的

resources
    -templates
        -index.html
@Controller
public class IndexController {
 
    @RequestMapping("/index")
    public String index(){
        // 这两种都可以
        return "index.html"; 
        // return "index" 
    }
}

如果目录是这样放置的

resources
    -templates
        -xxxx
            -index.html
@Controller
public class IndexController {
 
    @RequestMapping("/index")
    public String index(){
        // 这两种都可以
        return "xxxx/index.html"; 
        // return "xxxx/index" 
    }
}

解决步骤

更改路由配置

1、mode:路由模式

2、base:

  • 就是你路由切换时 url 中 不变的那部分啦
  • 如果你配置了 contextPath 那么 dzjz 是一定不能少的
  • fljdyypt 也不能少,要不然刷新之后 url 就只剩 http://localhost:9080/dzjz/home 了(不符合问题场景第 4 条需求)
const router = new VueRouter({
  routes,
  mode:'history',
  base: '/dzjz/fljdyypt'
})

修改前端打包配置

module.exports = {
    publicPath: '/dzjz/fljdyypt',
  // 所有的东西都在dist里面
}
 
 
// 或者
module.exports = {
    publicPath: '/dzjz',
    assetsDir: 'fljdyypt',
  //  js、css、fonts、img在fljdyypt里面  .ico和index.html直接在dist下
}

这样打包完 index.html 里面就变成这种了, 你的 index.html 就会找到对应的的 js、css 等

-resources
    -static
        -fljdyypt
            -css
            -fonts
            -img
            -js
        -favicon.ico
    -templates
        -index.html

问: 你 publicPath 设置成 ''或者用'dzjz' 之类的 用相对路径行不行呢? 我试了不行 不知道是我配置有问题还是咋的, 咱先回避下这个问,先保证功能好用

前端打包

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
 
@Configuration
public class HistoryConfig implements ErrorPageRegistrar {
 
    @Override
    public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
        ErrorPage errorPage = new ErrorPage(HttpStatus.NOT_FOUND, "/fljdyypt");
        errorPageRegistry.addErrorPages(errorPage);
    }
}

后端创建静态资源目录,并把 dist 的东西分类往里面塞

后端设置下 resources 创建目录并 把 dist 打包后对应的文件放里面

@Controller
public class IndexController {
 
    @RequestMapping("/fljdyypt")
    public String aIndex(){
        return "index.html";
    }
    
}

配置 404 转发

由于 history 模式下,手动修改 url 或者手动刷新页面,请求会直接发到服务器 ,比如 http://localhost:9080/dzjz/fljdyypt/home

1、先找 controller 看看有没有对应的视图解析

2、再找静态资源有没有这个东东

都没有肯定 404 啦 路由变化就交给前端处理 所以要转发到 http://localhost:9080/dzjz/fljdyypt/ 交给下一步的视图解析处理

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
 
@Configuration
public class HistoryConfig implements ErrorPageRegistrar {
 
    @Override
    public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
        ErrorPage errorPage = new ErrorPage(HttpStatus.NOT_FOUND, "/fljdyypt");
        errorPageRegistry.addErrorPages(errorPage);
    }
}

配置视图解析

由于 fljdyypt 不是 contextPath 所有我们要手动写一个 controller

@Controller
public class IndexController {
 
    @RequestMapping("/fljdyypt")
    public String aIndex(){
        return "index.html";
    }
    
}

至此大功告成

总结

我这个需求有点麻烦奥(比如不想改 contextPath、前后端不分离部署 有点反人类),如果你的项目只有 contexPath, 那么只需

1、改个路由配置

2、改个前端打包配置

3、配个 404 转发

期待批评指正