简单vue3前端打包部署到服务器,动态配置http请求头后端ip方法教程
vue3若依框架前端打包部署到服务器,需要部署到多个服务器上,每次打包会很麻烦,今天教大家一个动态配置请求头api的方法,部署后能动态获取(修改)对应服务器的请求ip
介绍两种方法,如有需要可以直接尝试步骤一,不行再用步骤二
方法一 、
只需要在request中获取地址栏的信息,不用新建文件
获取地址栏的http请求头
var baseUrlDt =window.location.protocol + "//" + window.location.hostname + ":8010";
let downloadLoadingInstance; // 动态ip打包时使用这条代码
request.js全部代码:
import axios from "axios";
import {ElNotification,ElMessageBox,ElMessage,ElLoading,
} from "element-plus";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from "@/plugins/cache";
import { saveAs } from "file-saver";
import useUserStore from "@/store/modules/user";var baseUrlDt =window.location.protocol + "//" + window.location.hostname + ":8010";
let downloadLoadingInstance; // 动态ip打包时使用这条代码// 是否显示重新登录
export let isRelogin = { show: false };axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例
const service = axios.create({// axios中请求配置有baseURL选项,表示请求URL公共部分// baseURL: import.meta.env.VITE_APP_BASE_API,baseURL: baseUrlDt, // 动态ip打包时使用这条代码// 超时timeout: 10000,
});// request拦截器
service.interceptors.request.use((config) => {// 是否需要设置 tokenconst isToken = (config.headers || {}).isToken === false;// 是否需要防止数据重复提交const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;if (getToken() && !isToken) {config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改}// get请求映射params参数if (config.method === "get" && config.params) {let url = config.url + "?" + tansParams(config.params);url = url.slice(0, -1);config.params = {};config.url = url;}if (!isRepeatSubmit &&(config.method === "post" || config.method === "put")) {const requestObj = {url: config.url,data:typeof config.data === "object"? JSON.stringify(config.data): config.data,time: new Date().getTime(),};const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小const limitSize = 5 * 1024 * 1024; // 限制存放数据5Mif (requestSize >= limitSize) {console.warn(`[${config.url}]: ` +"请求数据大小超出允许的5M限制,无法进行防重复提交验证。");return config;}const sessionObj = cache.session.getJSON("sessionObj");if (sessionObj === undefined ||sessionObj === null ||sessionObj === "") {cache.session.setJSON("sessionObj", requestObj);} else {const s_url = sessionObj.url; // 请求地址const s_data = sessionObj.data; // 请求数据const s_time = sessionObj.time; // 请求时间const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交if (s_data === requestObj.data &&requestObj.time - s_time < interval &&s_url === requestObj.url) {const message = "数据正在处理,请勿重复提交";console.warn(`[${s_url}]: ` + message);return Promise.reject(new Error(message));} else {cache.session.setJSON("sessionObj", requestObj);}}}return config;},(error) => {console.log(error);Promise.reject(error);}
);// 响应拦截器
service.interceptors.response.use((res) => {// 未设置状态码则默认成功状态const code = res.data.code || 200;// 获取错误信息const msg = errorCode[code] || res.data.msg || errorCode["default"];// 二进制数据则直接返回if (res.request.responseType === "blob" ||res.request.responseType === "arraybuffer") {return res.data;}if (code === 401) {if (!isRelogin.show) {isRelogin.show = true;ElMessageBox.confirm("登录状态已过期,您可以继续留在该页面,或者重新登录","系统提示",{confirmButtonText: "重新登录",cancelButtonText: "取消",type: "warning",}).then(() => {isRelogin.show = false;useUserStore().logOut().then(() => {location.href = "/index";});}).catch(() => {isRelogin.show = false;});}return Promise.reject("无效的会话,或者会话已过期,请重新登录。");} else if (code === 500) {ElMessage({ message: msg, type: "error" });return Promise.reject(new Error(msg));} else if (code === 601) {ElMessage({ message: msg, type: "warning" });return Promise.reject(new Error(msg));} else if (code !== 200) {ElNotification.error({ title: msg });return Promise.reject("error");} else {return Promise.resolve(res.data);}},(error) => {console.log("err" + error);let { message } = error;if (message == "Network Error") {message = "后端接口连接异常";} else if (message.includes("timeout")) {message = "系统接口请求超时";} else if (message.includes("Request failed with status code")) {message = "系统接口" + message.substr(message.length - 3) + "异常";}ElMessage({ message: message, type: "error", duration: 5 * 1000 });return Promise.reject(error);}
);// 通用下载方法
export function download(url, params, filename, config) {downloadLoadingInstance = ElLoading.service({text: "正在下载数据,请稍候",background: "rgba(0, 0, 0, 0.7)",});return service.post(url, params, {transformRequest: [(params) => {return tansParams(params);},],headers: { "Content-Type": "application/x-www-form-urlencoded" },responseType: "blob",...config,}).then(async (data) => {const isBlob = blobValidate(data);if (isBlob) {const blob = new Blob([data]);saveAs(blob, filename);} else {const resText = await data.text();const rspObj = JSON.parse(resText);const errMsg =errorCode[rspObj.code] || rspObj.msg || errorCode["default"];ElMessage.error(errMsg);}downloadLoadingInstance.close();}).catch((r) => {console.error(r);ElMessage.error("下载文件出现错误,请联系管理员!");downloadLoadingInstance.close();});
}export default service;
方法二、
原理:打包的时候将动态的ip排除在打包外,不参与打包,类似于public文件夹下的index.html
步骤一、
在public文件夹下新建config.js文件,有的项目是static文件夹下
var ipConfig = {AXIOS_TIMEOUT: 10000,baseUrl: "http://xxx",//配置服务器IP及端口}

步骤二、
在根目录的index.html引入新增config.js,在项目中就可以使用了
<!-- 动态ip打包时使用这条代码 --><script type="text/javascript" src="/public/config.js"></script>

步骤三、
找到request.js文件,在拦截器中直接调用对象
const baseURL = window.ipConfig.baseUrl; // 动态ip打包时使用这条代码

request.js全部代码:
import axios from "axios";
import {ElNotification,ElMessageBox,ElMessage,ElLoading,
} from "element-plus";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from "@/plugins/cache";
import { saveAs } from "file-saver";
import useUserStore from "@/store/modules/user";// axios.defaults.baseURL = window.ipConfig.BASE_URL//'http://192.168.1.177:8083/'
// // 开启认证
// axios.defaults.withCredentials = true
const baseURL = window.ipConfig.baseUrl; // 动态ip打包时使用这条代码
let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例
const service = axios.create({// axios中请求配置有baseURL选项,表示请求URL公共部分// baseURL: import.meta.env.VITE_APP_BASE_API,baseURL: baseURL, // 动态ip打包时使用这条代码// 超时timeout: 10000,
});// request拦截器
service.interceptors.request.use((config) => {// 是否需要设置 tokenconst isToken = (config.headers || {}).isToken === false;// 是否需要防止数据重复提交const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;if (getToken() && !isToken) {config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改}// get请求映射params参数if (config.method === "get" && config.params) {let url = config.url + "?" + tansParams(config.params);url = url.slice(0, -1);config.params = {};config.url = url;}if (!isRepeatSubmit &&(config.method === "post" || config.method === "put")) {const requestObj = {url: config.url,data:typeof config.data === "object"? JSON.stringify(config.data): config.data,time: new Date().getTime(),};const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小const limitSize = 5 * 1024 * 1024; // 限制存放数据5Mif (requestSize >= limitSize) {console.warn(`[${config.url}]: ` +"请求数据大小超出允许的5M限制,无法进行防重复提交验证。");return config;}const sessionObj = cache.session.getJSON("sessionObj");if (sessionObj === undefined ||sessionObj === null ||sessionObj === "") {cache.session.setJSON("sessionObj", requestObj);} else {const s_url = sessionObj.url; // 请求地址const s_data = sessionObj.data; // 请求数据const s_time = sessionObj.time; // 请求时间const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交if (s_data === requestObj.data &&requestObj.time - s_time < interval &&s_url === requestObj.url) {const message = "数据正在处理,请勿重复提交";console.warn(`[${s_url}]: ` + message);return Promise.reject(new Error(message));} else {cache.session.setJSON("sessionObj", requestObj);}}}return config;},(error) => {console.log(error);Promise.reject(error);}
);// 响应拦截器
service.interceptors.response.use((res) => {// 未设置状态码则默认成功状态const code = res.data.code || 200;// 获取错误信息const msg = errorCode[code] || res.data.msg || errorCode["default"];// 二进制数据则直接返回if (res.request.responseType === "blob" ||res.request.responseType === "arraybuffer") {return res.data;}if (code === 401) {if (!isRelogin.show) {isRelogin.show = true;ElMessageBox.confirm("登录状态已过期,您可以继续留在该页面,或者重新登录","系统提示",{confirmButtonText: "重新登录",cancelButtonText: "取消",type: "warning",}).then(() => {isRelogin.show = false;useUserStore().logOut().then(() => {location.href = "/index";});}).catch(() => {isRelogin.show = false;});}return Promise.reject("无效的会话,或者会话已过期,请重新登录。");} else if (code === 500) {ElMessage({ message: msg, type: "error" });return Promise.reject(new Error(msg));} else if (code === 601) {ElMessage({ message: msg, type: "warning" });return Promise.reject(new Error(msg));} else if (code !== 200) {ElNotification.error({ title: msg });return Promise.reject("error");} else {return Promise.resolve(res.data);}},(error) => {console.log("err" + error);let { message } = error;if (message == "Network Error") {message = "后端接口连接异常";} else if (message.includes("timeout")) {message = "系统接口请求超时";} else if (message.includes("Request failed with status code")) {message = "系统接口" + message.substr(message.length - 3) + "异常";}ElMessage({ message: message, type: "error", duration: 5 * 1000 });return Promise.reject(error);}
);// 通用下载方法
export function download(url, params, filename, config) {downloadLoadingInstance = ElLoading.service({text: "正在下载数据,请稍候",background: "rgba(0, 0, 0, 0.7)",});return service.post(url, params, {transformRequest: [(params) => {return tansParams(params);},],headers: { "Content-Type": "application/x-www-form-urlencoded" },responseType: "blob",...config,}).then(async (data) => {const isBlob = blobValidate(data);if (isBlob) {const blob = new Blob([data]);saveAs(blob, filename);} else {const resText = await data.text();const rspObj = JSON.parse(resText);const errMsg =errorCode[rspObj.code] || rspObj.msg || errorCode["default"];ElMessage.error(errMsg);}downloadLoadingInstance.close();}).catch((r) => {console.error(r);ElMessage.error("下载文件出现错误,请联系管理员!");downloadLoadingInstance.close();});
}export default service;
如果对你有帮助,点个👍
相关文章:
简单vue3前端打包部署到服务器,动态配置http请求头后端ip方法教程
vue3若依框架前端打包部署到服务器,需要部署到多个服务器上,每次打包会很麻烦,今天教大家一个动态配置请求头api的方法,部署后能动态获取(修改)对应服务器的请求ip 介绍两种方法,如有需要可以直接尝试步骤一ÿ…...
C语言关于溢出和不溢出的判断
通过实验来判断整数溢出,浮点数溢出的情况 #include <stdio.h> #include <limits.h> #include <float.h> int main(void) { // 整数溢出 int int_max INT_MAX; // INT_MAX 是 int 类型的最大值 int int_min INT_MIN; // INT_MIN …...
活动预告 |【Part1】Microsoft Azure 在线技术公开课:使用 Microsoft Fabric 实现数据湖仓
课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加“使用 Microsoft Fabric 实现数据湖仓”活动,了解如何在 AI 的帮助下统一数据分析。了解如何简…...
Unreal的Audio::IAudioCaptureStream在Android中录制数据异常
修改OpenAudioCaptureStream启动参数为PCM_32,在PC上正常,在Android系统,读取的的数据计算出的音量值在0.4-0.6之间跳动,数据异常。 Audio::FAudioCaptureDeviceParams Params;/** 设置声卡不支持的采样数和通道数开始音频流不会成…...
6、AI测试辅助-测试报告编写(生成Bug分析柱状图)
AI测试辅助-测试报告编写(生成Bug分析柱状图) 一、测试报告1. 创建测试报告2. 报告补充优化2.1 Bug图表分析 3. 风险评估 总结 一、测试报告 测试报告内容应该包含: 1、测试结论 2、测试执行情况 3、测试bug结果分析 4、风险评估 5、改进措施…...
【第五节】docker应用系列篇: 使用Docker容器实现ElasticSearch+Kibana部署
系列文章目录 【第五节】docker应用系列篇: 使用Docker容器实现ElasticSearchKibana部署 系列文章目录前言一、 docker运行es二、 docker运行kibina 前言 配一次,真觉得方面 一、 docker运行es docker pull elasticsearch:7.17.0# mkdir -p /opt/es/co…...
openwrt 通过DHCP/DNS(Dnsmasq)屏蔽指定域名(hosts)
1、准备好hosts文件 2、登录openwrt后台:系统-TTYD终端-root登录: cd /etc ls vi hosts_by_me vi hosts_by_me 创建/打开 hosts_by_me文件,把准备好的hosts文件的内容复制粘贴进去,然后保存退出:wq cat hosts_by_me查看确认保…...
opencv——识别图片颜色并绘制轮廓
图像边缘检测 本实验要用到Canny算法,Canny边缘检测方法常被誉为边缘检测的最优方法。 首先,Canny算法的输入端应为图像的二值化结果,接收到二值化图像后,需要按照如下步骤进行: 高斯滤波。计算图像的梯度和方向。非极…...
docker简单私有仓库的创建
1:下载Registry镜像 导入镜像到本地中 [rootlocalhost ~]# docker load -i registry.tag.gz 进行检查 2:开启Registry registry开启的端口号为5000 [rootlocalhost ~]# docker run -d -p 5000:5000 --restartalways registry [rootlocalhost ~]# dock…...
etcd常见运维事件
1、etcd扩/缩容 参考:etcd节点扩/缩容-CSDN博客 2、etcd数据备份/恢复 数据备份 数据备份要从leader节点进行备份,否则可能存在数据同步延迟导致数据不一致; etcdctl --endpoints"https://10.119.48.166:2379" snapshot save /d…...
[代码随想录17]二叉树之最大二叉树、合并二叉树、二搜索树中的搜索、验证二叉搜索树。
前言 二叉树的题目还是要会一流程构造函数之类的。其中还有回溯的思想 题目链接 654. 最大二叉树 - 力扣(LeetCode) 一、最大二叉树 思路:还是考察构造二叉树,简单来说就是给你一个数组去构建一个二叉树,递归来解决就…...
前端三大框架 Vue、React 和 Angular 的市场占比分析
一、引言 ?? 随着前端技术的迅速发展,Vue.js、React 和 Angular 已成为全球最受欢迎的三大前端框架。在国内外,不同的框架在市场中的占比和流行程度存在显著差异。本文将从全球和中国市场的角度,对这三大框架的市场占比进行分析࿰…...
12.3【JAVA-EXP4-DEBUGSTUDY】
java升级版本 JDK 1.8 是 Java Development Kit 的第 8 版本,发布于 2014 年 3 月 18 日。这个版本是 Java SE(Standard Edition)的一部分,包含了 Java 编程语言的实现、编译器、调试工具和其他相关组件 JDK 1.8: 这里的 1.8 表…...
flutter命令行直接指定设备
> flutter driver Found 3 connected devices:sdk gphone16k x86 64 (mobile) • emulator-5554 • android-x64 • Android 15 (API 35) (emulator)Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.5 LTS 6.8.0-49-genericChrome (…...
Spring核心--Bean后处理器
Spring的后处理器(Spring核心重点) Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。Spring主要有两种后处理器: BeanFactoryPostProcessor: Bean工…...
Windows子系统Ubuntu本地部署xinference以及接入dify详解
背景介绍 系统:Ubuntu 22.04.5 LTSpython环境管理工具:mincondadify版本:0.13.2本文参考 Xinference在线文档和dify的官方介绍模型接入 1. Github拉取Xinference代码 首选去Xinference的Github地址拉取代码 2. 在minconda创建隔离环境 - xinfernce 是我本地创建的环境名…...
如何实现接口继承与实现继承的区别?如何处理多态性与性能的平衡?
在面向对象编程中,接口继承和实现继承是两个重要的概念,同时多态性也是面向对象编程的一大特性,但在追求多态性的同时,我们也需要考虑性能问题。本文将详细探讨接口继承与实现继承的区别,以及如何处理多态性与性能的平…...
VR虚拟展厅的实时互动是如何实现的?
VR虚拟展厅的实时互动是通过一系列技术和流程实现的,这些技术和流程共同确保了用户在虚拟环境中的互动体验能够及时响应和更新。 接下来,由专业从事VR虚拟展厅制作的圆桌3D云展厅平台为大家介绍一下实现VR虚拟展厅实时互动的几个关键要素: 高…...
Java、鸿蒙与嵌入式开发:技术选择与职业发展分析
在当今快速发展的科技领域中,Java、鸿蒙和嵌入式开发代表着不同的技术方向和职业机遇。每个方向都有其独特的市场价值和发展前景,让我们深入分析这三个领域的特点、发展趋势和职业规划。 Java开发方向已经发展了二十多年,仍然在软件开发领域…...
28. Three.js案例-创建圆角矩形并进行拉伸
28. Three.js案例-创建圆角矩形并进行拉伸 实现效果 知识点 WebGLRenderer (WebGL渲染器) WebGLRenderer 是 Three.js 中用于渲染 3D 场景的主要渲染器。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数,可选。 …...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

