目录
二、vue.config.js基本配置(配置devServer.proxy,target为接口地址)
一、创建一个request.js文件,请求拦截封装
1.包引入
import axios from "axios";
import { Notification, Message } from "element-ui";
import errorCode from "@/utils/errorCode";
import store from "@/store/index";
2.创建axios实例,相关配置
这里的baseURL配置根据在vue.config中的devServer.proxy而来,具体请看后面vue.config.js基本配置
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 对应国际化资源文件后缀
axios.defaults.headers["Content-Language"] = "zh_CN";
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.NODE_ENV === "production" ? "/api" : "/dev-api",
// 超时
timeout: 30000,
});
//刷新token调用
let tokenHttp = axios.create({
baseURL: process.env.NODE_ENV === "production" ? "/api" : "/dev-api",
// 超时
timeout: 30000,
});
3.拦截器
判断token期限:expires是登录请求或refreshToken请求后,后端反给我们的一个token期限,这里expires后端的处理是,token创建时的时间戳 + token持续时间 = expires。
我这里对token的判断是,在token过期前十秒就去调刷新token的接口,时间据情况自定
如果token过期就将请求挂起并存放到数组中,在token刷新过后再将新的token替换旧的token
let refreshing = false;
// 被挂起的请求数组
let subscribesArr = [];
/* push所有请求到数组中 */
function subscribeTokenRefresh(cb) {
subscribesArr.push(cb);
}
function onRrefreshed(token) {
subscribesArr.map(cb => cb(token))
}
//判断token期限
//expires是登录请求或refreshToken请求后,后端反给我们的一个token期限
//这里expires后端的处理是,token创建时的时间戳+token持续时间=expires
const tokenExpired = (expires) => {
let now = new Date().getTime();
//milliseconds如果大于0说明未过期
let milliseconds = expires - now;
return milliseconds;
};
// request拦截器
service.interceptors.request.use(
(config) => {
let nowToken = localStorage.getItem("token");
//登陆时,会将token以及expires一同存储在localStorage
let expires = localStorage.getItem("expires");
//判断token存在,同时tokenExpired(expires) < 10000
//这样处理是为了在token过期前十秒就去调刷新token的接口,时间据情况自定
if (nowToken && tokenExpired(expires) < 10000) {
// 是否在刷新
if (!refreshing) {
refreshing = true;
let refresh = {}
refresh.refreshToken = localStorage.getItem("refreshToken")
// 刷新token,定义一个get的refreshToken的接口,传的参数据情况自定
tokenHttp
.get("/accessToken/refresh", { params: refresh })
.then((res) => {
refreshing = false;
let param = {
token: res.data.accessToken,
refreshToken: res.data.refreshToken,
expires: res.data.accessTokentime,
};
store.commit("login/login", param)
let newToken = localStorage.getItem('token')
//请求的token替换为新token
onRrefreshed(newToken);
subscribesArr = []
})
.catch(() => { });
//post接口仅供参考
//tokenHttp.post('/accessToken/refresh', qs.stringify(param))
}
const retry = new Promise((resolve, reject) => {
/* (token) => {...}这个函数就是回调函数*/
subscribeTokenRefresh((token) => {
config.headers.Authorization = token
resolve(config);
});
});
return retry;
}
return config;
},
(error) => {
Promise.reject(error);
}
);
二、vue.config.js基本配置(配置devServer.proxy,target为接口地址)
module.exports = {
/**
* 部署生产环境和开发环境下的URL。
* 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
* 例如 https://www.chinatelecom.cn。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。
* 例如,如果你的应用被部署在 https://www.chinatelecom.cn/admin/,则设置 baseUrl 为 /admin/。
*/
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
/**
* 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
*/
outputDir: "dist",
/**
* 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
*/
assetsDir: "static",
/**
* 是否开启eslint保存检测,有效值:ture | false | 'error'
*/
lintOnSave: process.env.NODE_ENV === "development",
/**
* 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
*/
productionSourceMap: false,
/**
* webpack-dev-server 相关配置
*/
devServer: {
/**
* 配置proxy
*/
proxy: {
/**
* 配置开发接口地址
*/
['/dev-api']: {
target: "http://xxx.xxx.xxx.xxx:8082",
changeOrigin: true,
pathRewrite: {
['^/dev-api']: "/",
},
},
/**
* 配置生产接口地址
*/
['/api']: {
target: "http://xxx.xxx.xxx.xxx:8082",
changeOrigin: true,
pathRewrite: {
['^/api']: "/",
},
},
},
},
};