文章目录
在学习springboot和vue相关内容后,将学习到的东西记录下来,以便以后温故知新。 首先,使用需要知道,使用springboot和vue搭建项目,就相当于需要部署两个项目,一个是前端项目,另一个是后端项目,我这里都是使用tomcat进行部署,当然,在测试环境中还是使用vue的脚手架进行debug
第一步,搭建vue项目
vue的安装
1.安装node.js(http://www.runoob.com/nodejs/nodejs-install-setup.html)
2.基于node.js,利用淘宝npm镜像安装相关依赖
在cmd里直接输入:npm install -g cnpm --registry=https://registry.npm.taobao.org,回车,等待安装
3.安装全局vue-cli脚手架,用于帮助搭建所需的模板框架,在cmd里
1)输入:cnpm install -g vue-cli,回车,等待安装
2).输入:vue,回车,若出现vue信息说明表示成功
创建项目
1.在你任意喜欢的文件夹中创建一个项目文件夹,如:我创建的是D:/test
2.使用cmd进入D:/test目录中
3.使用vue init webpack vue_test命令,vue_test是项目的名称,然后就会叫你填一些有关于项目的信息,凭感觉填就行,但是,像是否使用vue-router这样的选项,建议还是选y
4.进入,vue_test文件夹(cd vue_test),使用npm install命令
5.使用npm run serve 或者 npm run dev 启动项目
到这里,vue就能顺利启动了,补充:
1.如果启动不成功,找不到原因,就进入到D:/test/vue_test目录中删除node_modules文件夹,再来一次
2.如果需要修改端口,vue3.0以上,在vue.config.js文件中
devServer: {
port: 8083,
open: true
}
springboot项目的创建
我这里使用的是idea,如果使用eclipse也差不多,(但是,eclipse要创建springboot,好像是需要安装一个插件,具体什么插件忘记了,有一段时间没用了,有需要的朋友可以问一下度娘)
idea
1.idea中,File ⇒ New ⇒ Project
2.打开一个界面,选择Spring Initializr ⇒ Next,内容随意填,不满意重新填就好,这步骤简单
3.然后一直Next,最后填一下项目名称就好,最后Finish
eclipse
1.eclipse中,File ⇒ New ⇒ Spring Starter Project
2.打开一个界面,看着填写相应行就好,然后Next
3.在接下来的页面中,可以自己随意选择,我一般就选,WEB中的:Spring Web Starter和SQL中的MySQL Driver,然后Finish
到这里,Springboot项目就创建完成了
vue与springboot之间的交互
跨域问题
在springboot中添加一个配置类就好
package com.coststatistics.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 2允许任何头
corsConfiguration.addAllowedMethod("*"); // 3允许任何方法(post、get等)
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
}
登录拦截问题
1.大致流程:首先是后端,后端在登陆成功之后,必须提供一个token(一串字符串,存在session或者redis中),作用是用于验证这个用户登陆是否有效,另外,会有一个拦截器进行检测(登陆拦截器),如果这个token在session或者redis中过期了,则会返回前端401(也可以是其他,自己设置)的状态码,axios就会通过响应拦截器对这个响应进行拦截,如果拦截到的状态码为401,则会跳转到登陆页面,并且清除vue中的session(注意这里session生效是因为配置了前端访问带cookie,如果没有配置,前端每次访问都是新的session,因此,是获取不到session中的数据的),当然,也可以配合shiro进行使用,我这里没有用shiro
2.后端拦截器:
private static final String accesstokenHeader = "access-token";
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
if (request.getMethod().equals("OPTIONS")) {
return true;
}
//这里为什么不用session存着key呢?因为这里之前没有配置前端访问带cookie,因此,是拿不到
//key的,因此,这里自己封装了一个存放token的方法,并且使用前端传进来的token作为key,如果
//在系统中没有这个token,则直接认为不是合理请求或者已过期
String token = request.getHeader(accesstokenHeader);
String systemToken = TokenManage.getToken(token);
if (!StringUtils.isEmpty(token) && !StringUtils.isEmpty(systemToken) &&
systemToken.equals(token)) {
return true;
} else {
buildGuestResponseBody(response, 401, "sessionId is invalid,please login again!");
return false;
}
}
3.前端配置,分两步:
(1)路由拦截器(主要是拦截路由使用的):
router.beforeEach((to, from, next) => {
if (to.path === '/') {
next();
} else {
let token = window.localStorage.getItem('token');
console.log(token);
if (token === 'null' || token === '' || token === null) {
next('/');
} else {
next();
}
}
});
(2)axios拦截器,主要是拦截接口使用的,并且有一些接口配置
// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(
config => {
if (window.localStorage.getItem('token')) {
config.headers.Authorization = window.localStorage.getItem('token');
}
return config;
},
error => {
return Promise.reject(error);
}
);
// http response 拦截器
axios.interceptors.response.use(
response => {
switch (response.data.code) {
case 401:
router.replace({
name: 'login'
})
break;
}
return response;
},
error => {
return Promise.reject(error.response.data) // 返回接口返回的错误信息
}
);
到这里,基本的配置已经完成了,可以正常使用登陆拦截了,另外,默认情况下,前端访问是不带cookie访问的,这种情况,后端就不能使用session存放数据了,那么要怎么配置呢?
(1))前端:axios.defaults.withCredentials = true,使用axios拦截器就配置上这个
配置这个之后,后端有两个地方需要注意,在跨域请求的配置上得改一下,
(2)后端:
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 1允许任何域名使用;
corsConfiguration.addAllowedOrigin("http://localhost:8080");
// 2允许任何头
corsConfiguration.addAllowedHeader("*");
// 3允许任何方法(post、get等)
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
改成这样,首先corsConfiguration.addAllowedOrigin必须为固定的值,不能是“*”,另外,必须
将corsConfiguration.setAllowCredentials设置成true,要不然不能进行cookie传入
另外,如果有人问,前端这些代码写在哪里,这就是另一个问题了,大概说一下,你可以写在一个js文件中,然后在main.js文件中引用一下,如:
import router from './router/index'
new Vue({
el: '#app',
router
})
还有没有其他的方法,应该是有的,但是我前端只是小小白,这样可以,我就这样用了,也没有深入去研究这个,因此,有需要的朋友可以自行百度,多了解一下
部署问题
springboot的部署
1.进入主类中,让主类继承SpringBootServletInitializer,重写方法:
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(GetDataApplication.class);
}
2.进入pom文件中,将packaging标签中更改成war,如果没有,则增加packging标签:
<packaging>war</packaging>
3.使用cmd,进入项目跟目录,比如:项目为Test,则需要进入到Test文件夹内,执行命令:
mvn clean package
在Test中的target里面会生成一个war包
4.将war包放到Tomcat中的webapp中,直接运行即可
坑点:
1.有可能启动之后会报java.lang.NoClassDefFoundError: javax/el/ELManager异常,原因:
(1)jre中lib里面的el-api版本和tomcat中的el-api版本不匹配,因此,将jre中的版本复制一份即可
(2)如果还是不行,那就是el-api版本没到3.0以上,只有3.0以上才有ELManager,因此,下载一个el-api3.0就可以了
2.在使用mvn clean package打包部署项目的时候,可能会报 test*****,然后打包部署失败之类的错误,只要把测试类注释掉就好了
vue的部署到tomcat中
1.在vue项目下的config/index.js中配置(demo为你在tomcat的webapps目录下新建的文件夹的名称)
assetsPublicPath: ‘/demo/’
2.在配置路由的index.js中,添加一个属性配置,和routes同级(demo同理)
base:’/demo/’,
3.使用cmd进入此文件夹,运行
npm run build
4.将vue项目下的dist文件夹中生成的index.html和statis文件夹复制到tomcat中,另外,在tomcat的webapps的目录下新建一个demo的文件夹,并且将刚刚复制的index.html和statis文件夹粘贴到这个目录下
5.在新建的demo文件夹下新建一个WEB-INF文件夹,并且在里面新建一个web.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<display-name>myword</display-name>
<description>
<error-code>404</error-code>
<location>/index.html</location>
</description>
</web-app>
6.运行tomcat,在网址中访问ip:port/demo,即可访问,另外,如果觉得这个路径中demo是多余的,可以到tomcat的conf文件夹下,找到service.xml文件,配置Host节点下添加一个Context节点即可,内容如下:
<Context docBase="D:\java\environment\tomcat\apache-tomcat-7.0.85\wtpwebapps\TestServlet" path="/TestServlet" reloadable="true" source="org.eclipse.jst.jee.server:TestServlet"/>
需要注意的是,前端和后端的端口需要不一样,另外,如果使用的是同一个tomcat,是不能同时开启两个一样的tomcat的,这里需要另外做配置,可以自行百度,具体忘记了
附录,遇到过的问题
1.前后端分离参数传递问题
后端默认接收的是:application/x-www-form-urlencoded,即:xxxx=ssss&fffff=jjjjj这种格式的参数,但是默认前端传递过来的是:application/json这种content-type(即json格式的数据)
因此,后端接收不到数据
解决方案:
针对后端:可以在参数前加一个@RequestBody注解,在参数是javabean对象的情况下
针对前端:发送报文的时候可以组建xxxx=ssss&fffff=jjjjj这种格式的参数,如:
this.axios.post(
"/singleCost/deleteSingleCost.do",
"id="+this.deleteId
).then((response) => {
if (response.status === 200) {
this.confirmDelete = false;
if(response.data.code == 0){
this.searchSingleCosts('searchForm');
}else{
this.message = response.data.message;
this.showMessage = true;
}
}
}).catch((error) => {
this.message = error;
this.showMessage = true;
});
2.springboot访问静态资源问题
假设我的静态资源都在文件夹/static下
(1)如果还没配置拦截器就找不到静态资源,则需要增加一个config类,如下:
@Configuration
public class StaticResource extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
(2)如果配置了拦截器后找不到静态资源,只需要在拦截器中添加白名单即可:"/static/**"
3.配置拦截器后导致静态资源无法访问
(1)在拦截器配置类中,即继承了WebMvcConfigurationSupport的类中
重写addResourceHandlers方法如下:
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
super.addResourceHandlers(registry);
}