Spring Boot整合Vue,解决静态资源映射,页面刷新失效,路径配置等问题
本博文属于本人原创,请尊重本人的劳动成果,如需转载,请标明出处并附上原文链接,谢谢。文章目录前言关于Vue中图片打包的问题(可跳过)准备工作问题描述静态资源访问设置首页出错页面处理另外的处理方式结束前言 为了完成学校的课程设计,我使用了Spring Boot和Vue尝试进行开发并且完成了,由于前...
本博文属于本人原创,请尊重本人的劳动成果,如需转载,请标明出处并附上原文链接,谢谢。如有错误,欢迎指正。
文章目录
前言
为了完成学校的课程设计,我使用了Spring Boot和Vue尝试进行开发并且完成了,由于前后端分离进行开发的,所以开发时Vue使用 npm run server 就能使用浏览器进行测试,Spring Boot则在eclipse上运行后使用 PostMan 进行测试,如果是开发完之后分开部署话,基本没什么问题。
但是,如果要将其合在一起的话,由于我们后端中一般会设置登录拦截器等,它会拦截我们的访问路径,所以需要解决静态资源访问,路径匹配等问题。我经过测试之后,在这里总结一下这些问题的解决方法,供大家参考。
关于Vue中图片打包的问题(可跳过)
在对整合过程中出现的问题的解决方法进行正式的讲解之前,先对Vue中图片打包的问题进行一下说明,如果你是使用Vue脚手架工具 Vue CLI 创建项目并进行开发的,那难免需要在页面中嵌入图片,如果我们将图片放在一个src下的一个文件夹中,并且使用了相对路径来显示,比如这样
loading: './assets/loading.gif'
开发过程中并且在图片比较少,而且图片固定的情况,一般不会出现什么问题。但是打包完成之后,页面有时候会出现图片找不到或者加载不了的情况,像这样
这是因为打包过程中图片的路径出了问题。要解决这个问题,只需要修改成这样即可
loading: require('./assets/loading.gif')
如果页面中需要包含大量的图片,并且图片路径需要从后端获取,比如以下图片这个样子,这个时候图片是不会打包在项目里面的,至于具体的解决方法,我放在后面讲解
准备工作
首先,我们只需要做初步的一个准备工作,其实准备工作挺简单的,在Vue项目所在目录下,使用cmd运行 npm run build 即可在项目下得到dist文件夹,像这样
我们只需要把dist文件夹下的所有内容拷贝到Spring Boot项目下的这个目录 /src/main/resources/static 下面即可。准备工作就算是完成了。
问题描述
在解决问题之前,我们需要先弄清楚我们的问题是什么。
1. Vue的编译好之后的文件是什么?
Vue是用来做单页面应用的,我们最后得到的只有一个html文件,即index.html。当然,我们在实际开发的过程中也会使用 多个页面组件+vue-router 来实现多个页面的效果,但它实质上是通过js来操作DOM,来改变我们的页面。所以,当我们在首页通过导航栏转向其他的页面时,实际上发生的动作是,浏览器直接向服务器发起请求,类似这样子 “/js/…js”,/css/…css,/img/…img,获取到所需要的js文件后,通过操作DOM改变页面。
2. 开发中,Vue使用一套路径,SpringBoot使用一套路径,那么我最后使用的是哪一套?
在浏览器上显示出来的当然是Vue中的那一套路径啦。SpringBoot中的那一套路径用来给前端调用以获取数据。
说实话,我也是第一次做。由于我做的东西比较简单,所以我的思路是这样子的,我后端只通过接口提供数据,并且只有首页一个html文件,前后端只进行纯数据的交互。
后端接收到请求后,只要它有权限并且参数也正确等,OK,我把JSON格式的数据给你。前端通过vue-router实现了页面跳转,在第一点已经讲过,vue实现的页面跳转实际上是获取js文件后通过DOM改变页面。它通过后端提供的接口获取数据后就可以把数据渲染到页面上。当然,vue-router中也要实现一个拦截器,不然的话,是可以通过修改浏览器地址栏的路径,不用登录和具备相应的权限即可访问到目标页面和数据。
3. 我能不能直接访问到项目中的静态资源?
不能,后端配置了拦截器拦截所有的路径之后,我们是无法直接访问到静态资源的(没有配置就可以)会出现类似这种问题
在我们开发的过程一般都会有这样子的要求,比如我想直接通过图片路径访问图片或者访问js文件或者css文件。但是我们的后端没有这样的路径,它会提示No Mapping for /img/…img之类的或者是直接被后端的拦截器拦截掉,这个时候我们就需要这个时候我们就需要做静态资源映射了。我们把请求路径直接映射到存放静态资源的目录下,并且忽略掉对静态资源请求路径的拦截。
Spring Boot 默认为我们提供了静态资源处理,提供的静态资源映射如下:
- classpath:/META-INF/resources
- classpath:/resources
- classpath:/static
- classpath:/public
那我们需要做的就是在拦截器里忽略掉这些请求路径就可以了
4. 无法直接访问页面或者刷新之后页面就丢失了
某些页面不用登录也能访问,我希望直接用网址就能访问到,如果后端不做处理,是访问不到的,因为后端不存在这样的路径。如果页面刷新之后页面丢失也是这个原因。浏览器其中输入的网址实际上是Vue管理的,那怎么解决呢?因为Vue编译打包之后路径跳转和处理逻辑都在index.html中,所以当我们访问的页面找不到时,我们需要转到index.html页面。
在SpringBoot中做的一个具体的处理就是设置ErrorPage为index.html,跳转到index.html之后,我们的请求又会被处理成/js/…js,/css/…css之类的请求直接就去请求静态资源了并且会通过后端提供的接口获取相应的数据。问题就能解决了。
解决方法
在Spring Boot2.0+中,我们可以通过实现WebMvcConfigurer接口来自己的配置类,切记不能加上@EnableWebMvc注解,接下来我们只需要重写接口里面的方法来实现我们自己的配置就可以了。
/**
* @author godelgnis
* @version v1.0
* @date 2019/3/10
*/
@Configuration
//@EnableWebMvc,不能加这个注解,它会使Spring Boot为我们提供的默认配置失效
public class CorsConfig implements WebMvcConfigurer {
}
1. 静态资源访问
如果我们的后端有需要存放用户上传的多张图片,那么我们最好是把用户上传的图片放在一个固定的文件夹,如果项目最后打包成了war包,那可以选择放在static下面,如果是打包从jar包,那么建议把存放图片的文件夹设置在项目之外,不然的随着上传图片的增多,jar包会越来越大,并且不方便管理。
如果是图片放在项目里面,那么直接使用SpringBoot的默认的资源映射,如果是放在项目外,则需要在我们自己的配置类里重写addResourceHandlers方法
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//将图片访问路径映射到D盘
registry.addResourceHandler("/temp/img/**").addResourceLocations("file:D:/temp/img/");
//以下的写法表示将“/img/img/img/**”映射到项目里面resource.static.img,这只是个示例,相信你能够理解
// registry.addResourceHandler("/img/img/img/**").addResourceLocations("classpath:/static/img/**");
}
由于我写了登录拦截器,并且拦截了所有的请求,那么我就需要在拦截器里把静态资源的请求过滤掉
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(
"/temp/img/**", //访问用户上传的图片的途径
"/index.html", //Spring Boot默认使用http://localhost:端口号就能够访问到/index.html,所以要把它忽略掉
"/js/**", //忽略掉js请求
"/img/**", //忽略掉img请求,这里放的是页面需要使用到的固定的图片,像什么error.png,loading.gif之类的
"/css/**", //忽略掉css请求
"/fonts/**", //忽略掉fonts请求
//以下需要根据个人的实际情况来写
//忽略掉项目中不需要登录也能访问的接口...
"/product/get/**",
//以下忽略掉的是Vue中路径,即不用登录就能访问到的页面组件
"/login",
"/register",
"/logout",
"/home"
//...其他需要忽略掉的请求路径
);
}
通过以上配置,你就可以了访问到index.html页面了。图片也能直接访问了
2. 设置Spring Boot首页
如果你的首页名不是index.html,那么你也可以只设置你自己的首页
/**
* SpringBoot设置首页
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
WebMvcConfigurer.super.addViewControllers(registry);
//前一个是请求路径,后一个是首页名
registry.addViewController("/").setViewName("index");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
3. 解决页面刷新失效及错误页设置
在第一点中我们已经解决了静态资源访问的问题了,但是我们刷新页面的时候页面就不行了,或者直接访问那些不用登录也能够访问的页面,会发现还是访问不了,不是已经忽略掉了吗?是的,已经忽略掉了,但是刷新或者直接访问页面的那些路径在后端里并不存在,所以这个时候就属于会出现404错误,Spring Boot会默认会转向/error处理
那么,这个时候我们就需要设置我们的错误页处理了,我们直接把错误页处理设置成我们的首页就可以了(Vue页面跳转是通过js操作DOM来实现的,这点很重要)
@Configuration
public class ServletConfig {
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
return factory -> {
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
factory.addErrorPages(error404Page);
};
}
}
经过这一个处理,,我们现在所有的页面刷新之后也不会有问题了。
另外的处理方式
https://www.cnblogs.com/SamWeb/p/8762098.html
这篇文章提到了可以使Vue在请求静态资源时加上/static/前缀,那么我们就可以在静态资源映射那里直接将/static/**映射到/static/下,然后拦截器就只需要忽略掉/static/ * *就可以了。不过这种方式我没有验证过
其他问题
也许你开发过程中会出现这样子一个问题,就是在Vue中使用了axios进行请求,比如登录操作,但是发现每次登录Spring Boot都会给我们分配一个不同sessionId,正常来说,它应该是能记住我们的登录状态的,之所以没记住我们的登录状态,是因为axios,再次请求时没有使用后端返回给我们的cookie(即sessionId),也就是说再次请求时,请求中并没有带上sessionId,所以后端就认为这是一个未登录的用户或者是新用户,然后就会重新分配一个新的sessionId。要解决这个问题,需要在Vue中这么设置
import axios from 'axios';
axios.defaults.withCredentials=true;
SpringBoot - SpringMVC的默认配置与修改
更多内容,请参考http://www.voidcn.com/article/p-hlrartsj-brp.html
更多推荐
所有评论(0)