# 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 才行。