# 通过 Axios 发起 AJAX 请求

Axios 是一个基于 ECMAscript 6 的 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

其特性包括:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

# 1. 简介

要引入并使用 Axios 的最简单的方式是从 CDN 引入:

<script src="https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script>

通过 axios 向后台发送请求,为了方便,axios 已经为所有支持的请求方法提供了别名。

                 axios(config): 最核心、最底层、最根本的方法
         axios.request(config): axios() 方法的别名
        axios.get(url,config): 包装 axios() 方法,专门发起 GET 请求
     axios.delete(url,config): 包装 axios() 方法,专门发起 DELETE 请求
 axios.post(url,data,config): 包装 axios() 方法,专门发起 POST 请求
  axios.put(url,data,config): 包装 axios() 方法,专门发起 PUT 请求
axios.patch(url,data,config): 包装 axios() 方法,专门发起 PATCH 请求
       axios.head(url,config : 包装 axios() 方法,专门发起 HEAD 请求

axios.request() 方法是 axios() 方法的别名,而 axios() 方法则是其它所有方法的底层实现。

关于 axios() 方法的详细配置,可参看官方文档:http://www.axios-js.com/zh-cn/docs/index.html (opens new window)

# 2. 发起 AJAX GET 请求

  • 示例:原始的、底层的、通用的方式

    axios({
        baseURL: '/servlet-example',    // 会拼接在 url 的前面
        url: '/hello.do',
        method: 'get', // default
        params: {
            username: 'tom',
            password: '123'
        }
    }).then(function (response) {
        console.log(response);
    }).catch(function (error) {
        console.log(error);
    });
    
  • 示例:简写方式

    axios
        .get('/servlet-example/hello.do?username=tom&password=123')
        .then(function (response) {
            console.log(response);
        })
        .catch(function (error) {
            console.log(error);
        });
    
  • 示例:也可以通过 params 对象传递参数

    const obj = {
      username: 'tom',
      password: '123'
    };
    
    axios
        .get('/servlet-example/hello.do', { params: obj })
        .then(function (response) {
            console.log(response);
        })
        .catch(function (error) {
            console.log(error);
        });
    
  • 后台代码:

    System.out.println(request.getParameter("username"));
    System.out.println(request.getParameter("password"));
    
    PrintWriter out = response.getWriter();
    out.write("hello world");
    

# 3. 发起 AJAX POST 请求:query-string 方式

注意,axios 常规的 post 请求的 content-type 的默认值就是 application/json 。 因此,在你没有『额外』设置的情况下,你通过 axios 发出的 AJAX Post 请求的参数传递方式都是 json-string 方式,而非 query-string 方式。此时,你在后台的 request.getParameter("...") 是获取不到值的。

注意

post 请求参数传递的 query-string 和 json-string 问题不是 axios 特有的问题,这是 HTTP 协议本身的约定。你使用其它的库、包,例如,jquery 的 $.ajax()$.post() 方法一样也是要面对、处理这个问题。

  • 示例:原始的、底层的、通用的方式

    const obj = {
      username: 'tom',
      password: '123456'
    };
    
    const queryString = Qs.stringify(obj);
    
    axios({
      baseURL: '/servlet-example',    // 会拼接在 url 的前面
      url: '/hello.do',
      method: 'post',
      headers: { 'content-type': 'application/x-www-form-urlencoded' },
      data: queryString   // 注意是 data:... ,不是 get 请求的 params: ...
    })
    .then(function (response) {
        console.log(response);
    }).catch(function (error) {
        console.log(error);
    });
    

    上述的例子中需要引入 Qs 来帮我们将对象转为 Query String 。

    <script src="https://cdn.bootcss.com/qs/6.7.0/qs.min.js"></script>
    

    当然,你自己手动去『拼』一个 Query String 格式的字符串也是可以的。,另外,jquery 里面有一个工具方法也是干这个事的:var queryString= $.param(obj);

    另外,在 ES 6 新增了一个 URLSearchParams 对象,也能间接干这个事:

    const params = new URLSearchParams({
        var1: "hello",
        var2: "world",
    });
    console.log(params.toString()); // var1=hello&var2=world
    
  • 后台代码:

    System.out.println(request.getParameter("username"));
    System.out.println(request.getParameter("password"));
    
    PrintWriter out = response.getWriter();
    out.write("hello world");
    

# 4. 发起 AJAX POST 请求:json-string 方式

注意,在整个二阶段我们都遇不到、用不到这种情况。一直到三阶段的 Spring MVC 的 @RequestBody 部分,我们才会遇到这种 json-string 方式的 Ajax Post 请求。

  • 示例:原始的、底层的、通用的方式

    const obj = {
      username: 'tom',
      password: '123456'
    };
    
    // const queryString = Qs.stringify(obj);
    
    axios({
      baseURL: '/servlet-example',    // 会拼接在 url 的前面
      url: '/hello.do',
      method: 'post',
      headers: {'content-type': 'application/json'}, // 默认值
      data: obj
    }).then(function (response) {
      console.log(response);
    }).catch(function (error) {
      console.log(error);
    });
    
  • 简写

    axios
      .post('/servlet-example/hello.do', obj)
      .then(function (response) {
          console.log(response);
      }).catch(function (error) {
          console.log(error);
      });
    
  • 后台代码

    System.out.println(request.getMethod());
    System.out.println(request.getParameter("username"));   // null
    System.out.println(request.getParameter("password"));   // null
    
    BufferedReader br = request.getReader();
    
    String str, wholeStr = "";
    while ((str = br.readLine()) != null) {
        wholeStr += str;
    }
    System.out.println(wholeStr);   // json-string 格式的请求参数。
    
    PrintWriter out = response.getWriter();
    out.write("hello world");