# Axios 的请求封装后的使用
# 引子
作为一名不标准的后端 Java 开发工程师,对于前端 HTML5,CSS3,JS 熟悉,对于 Nodojs 却不胜了解,也算接触写过不少 Vue 系列的后端管理页面。对其中的 Axios 的请求封装后的简易接口调用方法感觉很有意思。特地记录
# Axios 实现例子
# Axios 封装请求
Axios 的封装主要围绕三点,第一步创建 Axios 实例,第二步设置实例的请求拦截器,第三步设置实例的相应拦截器
import axios from 'axios' | |
import { Message } from 'element-ui' | |
/** | |
* @description 创建请求实例 | |
*/ | |
function createService () { | |
// 创建一个 axios 实例 | |
const service = axios.create() | |
// 请求拦截 | |
service.interceptors.request.use( | |
config => config,//config 是后期传入的 | |
error => { | |
// 开始请求时出现错误,指还没到对面服务器就发送失败 | |
console.log(error) | |
return Promise.reject(error) | |
} | |
) | |
// 响应拦截 | |
service.interceptors.response.use( | |
response => { | |
//dataAxios 是 axios 返回数据中的 data | |
const dataAxios = response.data | |
// 这个状态码是和后端约定的 | |
const { code } = dataAxios | |
// 根据 code 进行判断 | |
if (code === undefined) { | |
// 如果没有 code 代表这不是项目后端开发的接口 | |
return dataAxios | |
} else { | |
// 有 code 代表这是一个后端接口 可以进行进一步的判断 | |
switch (code) { | |
case 'SUCCESS': | |
localStorage.setItem('token', response.headers.retoken) | |
return dataAxios.data | |
case '400': | |
Message({ | |
message: dataAxios.message, | |
type: 'error', | |
duration: 2 * 1000 | |
}) | |
break | |
case 'xxx': | |
// [示例] 其它和后台约定的 code | |
break | |
default: | |
// 不是正确的 code | |
break | |
} | |
} | |
}, | |
error => { | |
return Promise.reject(error) | |
} | |
) | |
return service | |
} | |
/** | |
* @description 创建请求方法 | |
* @param {Object} service axios 实例 | |
*/ | |
function createRequestFunction (service) { | |
return function (config) { | |
const token = localStorage.getItem('token') | |
const configDefault = { | |
headers: { | |
token: token, | |
}, | |
timeout: 5000, | |
baseURL: 'https://localhost:8080/', | |
data: {} | |
} | |
/** | |
* Object.assign 函数可以理解为,第一个对象 configDefault 融合第二个对象 config 的所有字段 | |
* 第二个对象参数一般是 | |
* { | |
* url: '/app-info/list', | |
* method: 'get', | |
* params: data | |
* } | |
*/ | |
return service(Object.assign(configDefault, config)) | |
} | |
} | |
// 设置请求 | |
export const service = createService() | |
export const request = createRequestFunction(service) |
# 使用封装后的请求
通过上面的例子,我们可以很明显的看出我们的入参和 Ajax 参数神似。而在日常的使用中,大部分人常常忽视 headers 请求头的 Content-Type 属性的作用只会使用如下请求来解决后端 GET 请求键值对传值,POST 请求 JSON 字符串传值。因为这也是后端接口提供入参的常态。
#GET | |
return request({ | |
url: '/app-info/list', | |
method: 'get', | |
params: data | |
}) | |
#POST | |
return request({ | |
url: '/app-info/delete', | |
method: 'post', | |
data: data | |
}) |
但当我前后端开发时,也会写这种正规的接口,但总有那么几次参数是两个,请求是 POST,但又不想改请求类型,也不想把两个键值对参数换 JSON 字符串对象,纠结过几次但都用前面两种方式解决,但对于这件事情耿耿于怀,因为自身对前端的这种请求也属于会用而不能熟练用 Σ(っ °Д °;) っ,也看过很多人写的例子,感觉都不是我想要的。
# 如何实现 POST 请求键值对传值
# JAVA 后端接口例子
@PostMapping("/postTest") | |
@ResponseBody | |
public Object get(String password,String name){ | |
HashMap<String, String> stringStringHashMap = new HashMap<>(); | |
stringStringHashMap.put("name",name); | |
stringStringHashMap.put("password",password); | |
return stringStringHashMap; | |
} |
# Axios 官方介绍
从官方介绍上很直接的可以看到 Axios 会帮我们 转换请求数据和响应数据 以及 自动转换 JSON 数据
随后就在上面直接找到了官方解决方案,有好几种
随后我在源码处也找到了 Axios 关于参数的转换,文件路径:axios/dist/axios.js
然后我再收集了 Axios 的参数及含义
url —— 用来向服务器发送请求的url
method —— 请求方法,默认是GET方法
baseURL —— 基础URL路径,假如url不是绝对路径,如https://some-domain.com/api/v1/login?name=jack,那么向服务器发送请求的URL将会是baseURL + url。
transformRequest —— transformRequest方法允许在请求发送到服务器之前修改该请求,此方法只适用于PUT、POST和PATCH方法中。而且,此方法最后必须返回一个string、ArrayBuffer或者Stream。
transformResponse —— transformResponse方法允许在数据传递到then/catch之前修改response数据。此方法最后也要返回数据。
headers —— 发送自定义Headers头文件,头文件中包含了http请求的各种信息。
params —— params是发送请求的查询参数对象,对象中的数据会被拼接成url?param1=value1¶m2=value2。
paramsSerializer —— params参数序列化器。
data —— data是在发送POST、PUT或者PATCH请求的数据对象。
timeout —— 请求超时设置,单位为毫秒
withCredentials —— 表明是否有跨域请求需要用到证书
adapter —— adapter允许用户处理更易于测试的请求。返回一个Promise和一个有效的response
auth —— auth表明提供凭证用于完成http的身份验证。这将会在headers中设置一个Authorization授权信息。自定义Authorization授权要设置在headers中。
responseType —— 表示服务器将返回响应的数据类型,有arraybuffer、blob、document、json、text、stream这6个类型,默认是json类似数据。
xsrfCookieName —— 用作 xsrf token 值的 cookie 名称
xsrfHeaderName —— 带有 xsrf token 值 http head 名称
onUploadProgress —— 允许在上传过程中的做一些操作
onDownloadProgress —— 允许在下载过程中的做一些操作
maxContentLength —— 定义了接收到的response响应数据的最大长度。
validateStatus —— validateStatus定义了根据HTTP响应状态码决定是否接收或拒绝获取到的promise。如果 validateStatus 返回 true (或设置为 null 或 undefined ),promise将被接收;否则,promise将被拒绝。
maxRedirects —— maxRedirects定义了在node.js中redirect的最大值,如果设置为0,则没有redirect。
httpAgent —— 定义在使用http请求时的代理
httpsAgent —— 定义在使用https请求时的代理
proxy —— proxy定义代理服务器的主机名和端口,auth
cancelToken —— cancelToken定义一个 cancel token 用于取消请求
# 关键词介绍
从前面的信息来看我们已经找到了方向也明白了如何实现,但对于更清晰的使用还是很模糊的,所以我们需要再明白一些信息
# URLSearchParams 对象
URLSearchParams 对象是一个可以将 JSON 对象转换为 name=昔日长廊&password=昔日织
这种字符串对象。而后端的入参也是从这种字符串内取参。而这种格式出现在 form 表单请求时,headers 请求头参数 Content-Type 值为 application/x-www-form-urlencoded 时。也常用于 GET 请求地址后面的拼接带参。如下 POST 请求也能这样传参。
可以看到后台接受到了参数,但注意 headers 请求头参数 Content-Type 值为 application/json;charset=utf-8,这说明参数已经不是一个 URLSearchParams 对象,URL 路径也非常像 GET 请求。而原因的产生是因为 Axios 的参数内的 params
# params 与 data 参数
data 参数没有什么问题,不会做什么数据处理,但 params 参数会做数据处理,它会将 JSON 对象转为 name=昔日长廊&password=昔日织
这种字符串,它和 URLSearchParams 对象的区别你可以理解为 JS 的数组 [] 和 Array 对象的区别,他们本质上数据结构是一样,只是实现的方式不一样,自然这些方式内方法也不一样,在 JAVA 语言中就是继承,实现的效果。所以使用 params 时在对 URLSearchParams 对象处理时就转个字符串就行了。
证明:因为直接打印 URLSearchParams 对象的字符串模式,并使用 data 传参并成功
# 总结
总算解决了心里的一个疑惑。也对 Axios 又有了一个使用方式的经验
# 2021.09.17 补充
经朋友提示后端接口为 List 对象时不转 JSON 格式无法入参,会报找不到接口 java.util.List 的主要或默认构造函数方法。解决办法要么使用数组 [],要么前面加上 @RequestParam 才行。