问题场景
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:
- 跳到某个浏览记录:back(), forward(), go(),
- 添加/修改历史记录:pushState(), replaceState()
3、也是通过window.addEventListener('popstate', fun); 监听url改变,通过调用pushState(),replaceState()来修改当前的url,但是这种调用api的修改只会更新视图,不会向服务器发请求
4、当手动修改url地址并访问或者刷新页面,这种方式修改url访问请求会直接发送到服务器,比如我直接访问http://localhost:9080/dzjz/fljdyypt/home中,如果服务器没有配置对应的视图或者静态资源,那么就会404
springboot 静态资源
static
- 存放静态资源 css js 图片等
- 只要静态资源放在类路径下叫做/static、/public、/resources、 /META-INF/resources 就可以用 当前项目根路径/ + 静态资源名
- 请求进来,先找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等
<link href="/dzjz/fljdyypt/css/index.1b92b919.css" rel="stylesheet">
问: 你publicPath设置成 '' 或者用'dzjz' 之类的 用相对路径行不行呢? 我试了不行 不知道是我配置有问题还是咋的, 咱先回避下这个问,先保证功能好用
前端打包
npm run build
后端创建静态资源目录,并把dist的东西分类往里面塞
后端设置下resources 创建目录并 把dist打包后对应的文件放里面
-resources
-static
-fljdyypt
-css
-fonts
-img
-js
-favicon.ico
-templates
-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转发
期待批评指正