Axios 底层 baseURL 拼接源码解析*

📅 发布时间:2026/7/4 17:48:19 👁️ 浏览次数:
Axios 底层 baseURL 拼接源码解析*
Axios 底层 baseURL 拼接源码解析让我深入 Axios 源码揭示 baseURL 拼接的底层实现机制Axios 源码核心实现1. 请求拦截核心 -dispatchRequest.js// axios/lib/core/dispatchRequest.jsmodule.exportsfunctiondispatchRequest(config){// ⭐ 关键步骤合并 baseURL 和 urlif(config.baseURL!isAbsoluteURL(config.url)){// 如果 url 不是绝对路径就拼接 baseURLconfig.urlcombineURLs(config.baseURL,config.url);}// 继续处理请求...returnadapter(config).then(...);}// 判断是否是绝对URLfunctionisAbsoluteURL(url){// 检查是否以协议开头如 http://, https://或以 // 开头return/^([a-z][a-z\d\\-\.]*:)?\/\//i.test(url);}// 拼接URL的工具函数functioncombineURLs(baseURL,relativeURL){// 去掉 baseURL 末尾的 / 和 relativeURL 开头的 /returnrelativeURL?baseURL.replace(/\/$/,)/relativeURL.replace(/^\//,):baseURL;}2. 实际执行流程// 假设配置constconfig{baseURL:http://localhost:8081/jeecg-boot/,url:/sys/user/list}// 步骤1判断 url 是否是绝对路径isAbsoluteURL(/sys/user/list)// false因为不以 http:// 或 // 开头// 步骤2拼接 baseURL 和 urlcombineURLs(http://localhost:8081/jeecg-boot/,/sys/user/list)// 执行过程// 1. baseURL.replace(/\/$/, ) → http://localhost:8081/jeecg-boot去掉末尾斜杠// 2. relativeURL.replace(/^\//, ) → sys/user/list去掉开头斜杠// 3. 拼接结果http://localhost:8081/jeecg-boot / sys/user/list// 最终http://localhost:8081/jeecg-boot/sys/user/list️完整的底层调用链// 1. 用户调用axios.get(/sys/user/list)// 2. Axios.prototype.request (axios/lib/core/Axios.js)Axios.prototype.requestfunctionrequest(config){if(typeofconfigstring){configarguments[1]||{};config.urlarguments[0];// 设置 url}configmergeConfig(this.defaults,config);// 合并默认配置returndispatchRequest(config);// 调用 dispatchRequest}// 3. dispatchRequest (axios/lib/core/dispatchRequest.js)functiondispatchRequest(config){// ⭐ 核心拼接逻辑if(config.baseURL!isAbsoluteURL(config.url)){config.urlcombineURLs(config.baseURL,config.url);}returnadapter(config);}// 4. adapter (axios/lib/adapters/xhr.js) - 实际发送请求functionxhrAdapter(config){returnnewPromise(function(resolve,reject){varrequestnewXMLHttpRequest();// ⭐ 最终请求地址就是拼接后的 config.urlrequest.open(config.method.toUpperCase(),config.url,true);// 发送请求...});}URL 拼接的几种情况情况1相对路径拼接// baseURL http://localhost:8081/jeecg-boot// url /sys/user/list// 源码处理config.baseURLhttp://localhost:8081/jeecg-bootconfig.url/sys/user/list// 拼接结果config.urlhttp://localhost:8081/jeecg-boot/sys/user/list情况2绝对路径不拼接// baseURL http://localhost:8081/jeecg-boot// url http://other-domain.com/apiisAbsoluteURL(http://other-domain.com/api)// true// 直接返回原 url不拼接config.urlhttp://other-domain.com/api情况3无 baseURL// baseURL undefined// url /sys/user/list// 因为 config.baseURL 为 false跳过拼接config.url/sys/user/listJeecgBoot 中的具体实现1. 配置初始化// src/utils/request.jsconstserviceaxios.create({baseURL:window._CONFIG[domianURL]||/jeecg-boot,// ⭐ 设置 baseURLtimeout:60000})// 这里的 baseURL 会被合并到每个请求的 config 中2. 请求拦截器可查看最终URL// src/utils/request.jsservice.interceptors.request.use(config{console.log(请求前URL:,config.url)console.log(baseURL:,config.baseURL)// 如果想查看最终拼接后的完整URLconstfullUrlconfig.baseURLconfig.url console.log(完整请求地址:,fullUrl)// 添加 token 等returnconfig})3. 响应拦截器service.interceptors.response.use(response{console.log(请求成功URL:,response.config.url)returnresponse.data})手动实现类似功能// 自己实现一个简单的拼接函数classSimpleAxios{constructor(config){this.baseURLconfig.baseURL||}// 判断是否为绝对URLisAbsoluteURL(url){return/^([a-z][a-z\d\\-\.]*:)?\/\//i.test(url)}// 拼接URLcombineURLs(baseURL,relativeURL){if(!baseURL)returnrelativeURLif(this.isAbsoluteURL(relativeURL))returnrelativeURLreturnbaseURL.replace(/\/$/,)/relativeURL.replace(/^\//,)}// 请求方法request(url,options{}){// 拼接 URLconstfinalUrlthis.combineURLs(this.baseURL,url)console.log(最终请求地址:,finalUrl)// 发送请求...returnfetch(finalUrl,options)}get(url){returnthis.request(url,{method:GET})}post(url,data){returnthis.request(url,{method:POST,body:JSON.stringify(data)})}}// 使用示例constaxiosnewSimpleAxios({baseURL:http://localhost:8081/jeecg-boot})axios.get(/sys/user/list)// 输出: 最终请求地址: http://localhost:8081/jeecg-boot/sys/user/list源码关键点总结判断条件if (config.baseURL !isAbsoluteURL(config.url))必须有 baseURLurl 不能是绝对路径拼接函数combineURLs(baseURL, relativeURL)处理多余的斜杠保证格式正确执行时机在dispatchRequest阶段所有拦截器执行之后实际发送请求之前最终使用adapter 中直接使用拼接后的config.url这个设计让 axios 既保持了灵活性支持绝对路径又提供了便利性自动拼接 baseURL。是的axios 会自动拼接 baseURL这是 axios 的核心功能之一让我详细解释axios 的 baseURL 机制1. 基本工作原理importaxiosfromaxios// 创建 axios 实例时设置 baseURLconstserviceaxios.create({baseURL:http://localhost:8081/jeecg-boot,// 基础路径timeout:60000})// 请求时只需写相对路径service.get(/sys/user/list)// 实际请求: http://localhost:8081/jeecg-boot/sys/user/listservice.post(/sys/user/add,{username:张三})// 实际请求: http://localhost:8081/jeecg-boot/sys/user/addservice.put(/sys/user/edit,{id:1,status:1})// 实际请求: http://localhost:8081/jeecg-boot/sys/user/edit拼接规则详解规则1相对路径自动拼接// baseURL http://localhost:8081/jeecg-boot// ✅ 相对路径以 / 开头- 会拼接service.get(/sys/user/list)// 结果: http://localhost:8081/jeecg-boot/sys/user/list// ✅ 相对路径不以 / 开头- 也会拼接service.get(sys/user/list)// 结果: http://localhost:8081/jeecg-boot/sys/user/list规则2绝对路径不拼接// baseURL http://localhost:8081/jeecg-boot// ❌ 绝对路径包含 http://- 不拼接service.get(http://other-domain.com/api/test)// 结果: http://other-domain.com/api/test直接使用不拼接 baseURL// ❌ 绝对路径以 // 开头- 不拼接service.get(//other-domain.com/api/test)// 结果: //other-domain.com/api/test不拼接JeecgBoot 中的实际应用1. request.js 中的配置// src/utils/request.jsimportaxiosfromaxios// 从 window._CONFIG 获取 baseURLconstapiBaseUrlwindow._CONFIG[domianURL]||/jeecg-boot// 创建 axios 实例设置 baseURLconstserviceaxios.create({baseURL:apiBaseUrl,// ⭐ 这里设置全局 baseURLtimeout:60000,withCredentials:true})exportdefaultservice2. api/manage.js 中的使用// src/api/manage.jsimportservicefrom/utils/request// 封装的 GET 请求exportfunctiongetAction(url,params){returnservice({url:url,// 只需传相对路径method:get,params})// service 会自动拼接 baseURL url}// 封装的 POST 请求exportfunctionpostAction(url,data){returnservice({url:url,// 只需传相对路径method:post,data})}// 封装的 PUT 请求exportfunctionputAction(url,data){returnservice({url:url,// 只需传相对路径method:put,data})}3. 在组件中使用// UserList.vueimport{getAction,postAction,putAction}from/api/manageexportdefault{methods:{// 查询列表loadData(){// 只需传相对路径axios 自动拼接 baseURLgetAction(/sys/user/list,{pageNo:1,pageSize:10})// 实际请求: http://localhost:8081/jeecg-boot/sys/user/list},// 新增用户addUser(){postAction(/sys/user/add,{username:张三})// 实际请求: http://localhost:8081/jeecg-boot/sys/user/add},// 编辑用户editUser(){putAction(/sys/user/edit,{id:1,status:1})// 实际请求: http://localhost:8081/jeecg-boot/sys/user/edit}}}查看实际请求地址在浏览器控制台查看// 方法1在 Network 标签查看// F12 → Network → 找到请求 → 查看 Request URL// 方法2在代码中打印service.interceptors.request.use(config{console.log(最终请求地址:,config.baseURLconfig.url)console.log(完整URL:,config.url)returnconfig})实际输出示例// 当 baseURL http://localhost:8081/jeecg-boot// 请求 /sys/user/list 时最终请求地址:http://localhost:8081/jeecg-boot/sys/user/list拼接的三种情况请求的 URLbaseURL最终请求地址说明/sys/user/listhttp://localhost:8081/jeecg-boothttp://localhost:8081/jeecg-boot/sys/user/list✅ 自动拼接sys/user/listhttp://localhost:8081/jeecg-boothttp://localhost:8081/jeecg-boot/sys/user/list✅ 自动拼接http://other.com/apihttp://localhost:8081/jeecg-boothttp://other.com/api❌ 不拼接绝对路径⚠️注意事项1. 不要重复拼接// ❌ 错误手动拼接了 baseURLconstfullUrlhttp://localhost:8081/jeecg-boot/sys/user/listgetAction(fullUrl)// 结果会变成 http://localhost:8081/jeecg-boot/http://localhost:8081/jeecg-boot/sys/user/list// ✅ 正确只需传相对路径getAction(/sys/user/list)2. 处理带参数的 URL// 带查询参数的 URLgetAction(/sys/user/list,{pageNo:1,pageSize:10})// 最终: http://localhost:8081/jeecg-boot/sys/user/list?pageNo1pageSize10// 带路径参数的 URLputAction(/sys/user/edit/1,{status:1})// 最终: http://localhost:8081/jeecg-boot/sys/user/edit/13. 检查 baseURL 是否正确// 在 request.js 中添加调试代码console.log(当前 baseURL:,apiBaseUrl)// 输出: 当前 baseURL: http://localhost:8081/jeecg-boot总结是的axios 会自动拼接 baseURL在 JeecgBoot 中baseURL 在src/utils/request.js中设置组件中调用getAction(/sys/user/list)时axios 会自动拼接成http://localhost:8081/jeecg-boot/sys/user/list这个机制让你只需写相对路径简化了代码便于切换不同环境的 API 地址