🌐 Axios基础学习

一、Ajax初步

1、服务器端渲染

2、Ajax渲染(局部更新)

3、Ajax名词解释

  • 名称:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)

4、对比

非Ajax Ajax
发出请求 超链接、表单 JavaScript代码
响应格式 HTML页面 数据本身(通常是JSON格式)
页面渲染 后端渲染 前端渲染
用户体验 中规中矩 较好

开发方式:

  • 服务器端渲染:页面渲染主要由服务器端渲染实现
  • 前后端分离:所有请求和响应都基于Ajax技术实现
    • 分工明确:前端工程师不必关心数据的来源;后端工程师不必关心数据的显示
    • 代码解耦:前端代码和后端代码充分解耦,分别开发,易于维护

二、Axios框架

框架简介

官方文档:www.axios-http.cn/docs/intro

搭建环境

bash 复制代码
# 创建前端工程
npm create vite

# 进入工程目录
cd xxx

# 安装vue
npm install

# 安装axios
npm install axios@1.5.0

操作1:前端发送请求

html 复制代码
<script setup>  
  
  import axios from 'axios';  
  
  let operation01SendRequest = ()=>{  
    axios({  
      "url":"http://localhost:8080/demo/AjaxServlet/operation01SendRequest", // 请求的目标地址
      "method":"post" // 请求方式
    });  
  };  
</script>  
  
<template>  
  <div>  
    <p><button @click="operation01SendRequest()">操作1:发送请求</button></p>  
  </div>  
</template>

操作2:后端接收请求

①创建后端工程

  • 创建module
  • 添加web.xml
  • 添加Tomcat依赖
  • 创建Servlet(继承ServletPathParent)

②创建具体方法处理请求

java 复制代码
public class AjaxServlet extends ServletPathParent {  
    protected void operation01SendRequest(  
            HttpServletRequest request,   
            HttpServletResponse response) throws ServletException, IOException {  
        System.out.println("AjaxServlet 接收到了 Ajax 请求");  
    }  
}

操作3:解决跨域问题

①概念

  • 在A网站下发送Ajax请求,访问B网站,这样的操作有安全隐患
  • 以下情况我们判断为跨域:

②解决办法

  • 在前端解决:在vite.config.js文件配置代理(使用Vite服务器做一个代理)
  • 在后端解决:CORS(把跨域的网址信息加入到后端服务器的信任列表中)

找到vite.config.js文件:

增加配置:

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {   // 针对 Vite 启动的服务器进行配置
    proxy: {  // 配置 Vite 服务器的代理功能
      "/api": { // 使用代理功能的请求的地址的前缀
        target: 'http://localhost:8080',  // 目标访问地址
        rewrite: (path) => path.replace(/^\/api/, ''),  // 把 /api 从请求地址中去掉
      }
    }
  }
})

注意:做了上面这个配置,以后所有前端请求都必须以/api开头!

③修改Ajax请求地址

text 复制代码
"url":"/api/demo/AjaxServlet/operation01SendRequest"

操作4:后端返回数据:普通文本

java 复制代码
protected void operation01SendRequest(  
        HttpServletRequest request,  
        HttpServletResponse response) throws ServletException, IOException {  
    System.out.println("AjaxServlet 接收到了 Ajax 请求");  
  
    response.setContentType("text/html;charset=UTF-8");  
    response.getWriter().write("快到中午吃饭的时间了!");  
}

操作5:前端接收服务器端返回的响应

javascript 复制代码
axios({  
  "url":"/api/demo/AjaxServlet/operation01SendRequest", // 请求的目标地址  
  "method":"post" // 请求方式  
}).then((response)=>{ // then() 函数在参数中传入了一个回调函数  
  // 回调函数在服务器返回成功响应的时候调用  
  // 回调函数的参数 response 就是对服务器返回响应的封装  
  console.log(response);  
  
  // 访问 response 对象的 data 属性,获得服务器返回响应的响应体
  console.log(response.data);  
});

操作6:后端返回数据:JSON格式

①JSON格式回顾

  • 最外层的符号

    • {}:JSON对象
    • []:JSON数组
  • JSON对象

    • 逗号分开的一组键值对
    • 键和值之间使用冒号隔开
  • JSON数组

    • 逗号分开的一组值
  • 键的类型:固定就是字符串

  • 值的类型:

    • 基本数据类型
    • 引用类型
      • JSON对象
      • JSON数组
  • JSON对象:Java的Map类型、Java的实体类类型

  • JSON数组:Java的List集合、Set集合、数组

②后端操作JSON数据的类库

  • 阿里:FastJSON
  • XXX:Jackson
  • 谷歌:Gson
    • Java类型 --> JSON字符串
    • JSON字符串 --> Java类型

③后端代码

  • 首先在后端工程中导入 Gson jar包
java 复制代码
protected void operation02ReceiveJSON(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
    // 1、创建集合  
    List<Company> companyList = new ArrayList<>();  
  
    // 2、在集合中添加对象  
    companyList.add(new Company(1, "name01", 100.00));  
    companyList.add(new Company(2, "锤子科技", 200.00));  
    companyList.add(new Company(3, "name03", 300.00));  
  
    // 3、创建 Gson 对象(前提是把 gson-2.2.4.jar 导入)  
    Gson gson = new Gson();  
  
    // 4、把 Java 类型转换为 JSON 字符串  
    String json = gson.toJson(companyList);  
  
    // 5、为 JSON 格式的响应体设置内容类型  
    response.setContentType("application/json;charset=UTF-8");  
  
    // 6、把 JSON 字符串作为响应体返回给前端  
    response.getWriter().write(json);  
  
}

④前端代码

javascript 复制代码
axios({  
  "url":"/api/demo/AjaxServlet/operation02ReceiveJSON",  
  "method":"get"  
});

操作7:前端从JSON数据中读取属性

javascript 复制代码
axios({  
  "url":"/api/demo/AjaxServlet/operation02ReceiveJSON",  
  "method":"get"  
}).then((response)=>{  
  // 获取响应体对象  
  let companyList = response.data;  
  
  // ※axios框架,底层已经帮我们把 JSON 字符串转换为了 JSON 数组  
  // JSON.parse(JSON字符串) 解析得到 JSON 对象或数组  
  // 所以对于服务器端返回的 JSON 数据,直接操作即可  
  // JSON 对象:JSON 对象.属性名  
  // JSON 数组:JSON 数组[index]  
  // 遍历数组  
  for (let i = 0; i < companyList.length; i++) {  
    let company = companyList[i];  
    console.log(company.companyId);  
    console.log(company.companyName);  
    console.log(company.companyPrice);  
  }  
});

操作8:前端发送请求参数

①前端代码

javascript 复制代码
axios({  
  "url":"/api/demo/AjaxServlet/operation03SendParam",  
  "method":"post",  
  "params":{  
    "userName":"pig2023",  
    "userPwd":"smallPig"  
  }  
});

即使是使用POST请求方式,axios在通过params发送请求参数的情况下,仍然是把请求参数放在URL地址后面

②后端代码

java 复制代码
protected void operation03SendParam(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
    // 1、接收请求参数  
    String userName = request.getParameter("userName");  
    String userPwd = request.getParameter("userPwd");  
  
    // 2、打印  
    System.out.println("userName = " + userName);  
    System.out.println("userPwd = " + userPwd);  
  
}

操作9:前端发送JSON数据

①前端代码

javascript 复制代码
axios({  
  "url":"/api/demo/AjaxServlet/operation04SendJSON",  
  "method":"post",  
  "data":{  
    "companyId": 8,  
    "companyName": "小猪猪肉联厂",  
    "companyPrice": 100000.00  
  }  
});

②请求体

请求体是JSON格式:

以POST请求方式提交普通表单:

所以服务器端接收这样的参数就不能再使用传统的方式了:request.getParameter("xxx")

③后端代码

java 复制代码
protected void operation04SendJSON(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
    // 1、通过 request 对象获取能够读取请求体的字符输入流  
    BufferedReader reader = request.getReader();  
  
    // 2、创建 StringBuffer 对象用于保存请求体读取过程中每一行的数据  
    StringBuffer stringBuffer = new StringBuffer("");  
  
    // 3、声明一个字符串类型变量,用来临时保存读取到的每一行  
    String line = null;  
  
    // 4、循环读取请求体  
    while ((line = reader.readLine()) != null) {  
        stringBuffer.append(line);  
    }  
  
    // 5、把 StringBuffer 转为 String 类型  
    String requestBody = stringBuffer.toString();  
    System.out.println("requestBody = " + requestBody);  
  
    // 6、创建 Gson 对象  
    Gson gson = new Gson();  
  
    // 7、从请求体 JSON 字符串中解析得到 Java 类型  
    Company company = gson.fromJson(requestBody, Company.class);  
    System.out.println("company = " + company);  
  
}

操作10:后端处理请求失败

javascript 复制代码
axios({
  "url":"/api/demo/AjaxServlet/not/found"
}).catch((axiosError)=>{ // 服务器端处理请求失败,执行 catch() 里面设置的回调函数  
  
  // 回调函数的参数这里会传入 axios 封装的错误信息对象  
  console.log(axiosError);  
  
  // 访问 axiosError 的 response 属性得到响应对象  
  console.log(axiosError.response);  
  
  // 访问响应对象的 status 属性得到响应状态码  
  console.log(axiosError.response.status);  
  
  // 访问响应对象的 statusText 属性得到响应状态码的说明信息  
  console.log(axiosError.response.statusText);  
  
});

操作11:封装统一响应结果

①提出问题

  • 不同功能模块:返回的数据不同
  • 不同开发人员:返回的数据不同

造成:前端工程师针对每个请求的响应都需要进行识别,增加了工作量

②解决方案

开发一个通用的类型,从而保证项目中每个模块、每个功能、每个请求返回的数据,结构都是一样的

  • 后端声明一个类:Result
  • 每个请求处理的结果,封装到Result对象中
  • 把Result对象转换为JSON字符串
  • 把JSON字符串作为响应返回给前端

③声明Result

java 复制代码
package com.atguigu.demo.entity;  
  
/**  
 * 开发一个通用的类型,从而保证项目中每个模块、每个功能、每个请求返回的数据,结构都是一样的  
 */  
public class Result<T> {  
  
    // 声明常量,表示请求处理成功这个状态  
    public static final String SUCCESS = "SUCCESS";  
  
    // 声明常量,表示请求处理失败这个状态  
    public static final String FAILED = "FAILED";  
  
    // 请求处理的结果,是成功还是失败  
    private String processResult;  
  
    // 查询结果  
    private T queryResultData;  
  
    // 请求处理失败时,错误消息  
    private String errorMessage;  
  
    /**  
     * 工具方法:处理请求成功,没有查询结果需要返回  
     * @return  
     */    
     public static Result ok() {  
  
        Result result = new Result();  
          
        result.setProcessResult(SUCCESS);  
  
        return result;  
    }  
  
    /**  
     * 工具方法:处理请求成功,并且有查询结果需要封装  
     * @param queryResultData  
     * @return  
     * @param <T>  
     */  
    public static <T> Result<T> ok(T queryResultData) {  
  
        Result result = new Result();  
  
        result.setProcessResult(SUCCESS);  
        result.setQueryResultData(queryResultData);  
          
        return result;  
    }  
  
    /**  
     * 工具方法:处理请求失败  
     * @param errorMessage  
     * @return  
     */    public static Result failed(String errorMessage) {  
  
        Result result = new Result();  
    
		result.setProcessResult(FAILED);
        result.setErrorMessage(errorMessage);  
  
        return result;  
    }  
  
    public String getProcessResult() {  
        return processResult;  
    }  
  
    public void setProcessResult(String processResult) {  
        this.processResult = processResult;  
    }  
  
    public T getQueryResultData() {  
        return queryResultData;  
    }  
  
    public void setQueryResultData(T queryResultData) {  
        this.queryResultData = queryResultData;  
    }  
  
    public String getErrorMessage() {  
        return errorMessage;  
    }  
  
    public void setErrorMessage(String errorMessage) {  
        this.errorMessage = errorMessage;  
    }  
  
    @Override  
    public String toString() {  
        return "Result{" +  
                "processResult='" + processResult + '\'' +  
                ", queryResultData=" + queryResultData +  
                ", errorMessage='" + errorMessage + '\'' +  
                '}';  
    }  
  
    public Result(String processResult, T queryResultData, String errorMessage) {  
        this.processResult = processResult;  
        this.queryResultData = queryResultData;  
        this.errorMessage = errorMessage;  
    }  
  
    public Result() {  
    }  
}

操作12:封装工具方法从请求体读取JSON数据

java 复制代码
/**  
 * 当请求体是 JSON 格式时,使用这个工具方法,把请求体转换为 Java 类型  
 * @param request  
 * @param clazz  
 * @return  
 * @param <T>  
 */  
public static <T> T readRequestBody(HttpServletRequest request, Class<T> clazz) {  
  
    try {  
        // 1、通过请求对象获取字符输入流  
        BufferedReader reader = request.getReader();
  
        // 2、创建 stringBuilder 对象  
        StringBuilder stringBuilder = new StringBuilder();  
  
        // 3、声明变量,接收读取到的每一行  
        String line = null;  
  
        // 4、读取请求体  
        while ((line = reader.readLine()) != null) {  
            stringBuilder.append(line);  
        }  
  
        // 5、把 StringBuffer 转换为 String        
		String requestBody = stringBuilder.toString();  
  
        // 6、创建 Gson 对象  
        Gson gson = new Gson();  
  
        // 7、把 JSON 字符串解析为 Java 对象  
        T t = gson.fromJson(requestBody, clazz);  
  
        // 8、返回解析得到的 Java 对象  
        return t;  
  
    } catch (IOException e) {  
        throw new RuntimeException(e);  
    }  
}

操作13:封装工具方法把Result对象作为响应体返回

java 复制代码
/**  
 * 每一次返回响应时,Servlet 方法只需要创建 Result 对象即可,当前方法负责把 Result 对象转换为 JSON  
 * 然后作为响应体返回  
 * @param result  
 * @param response  
 */  
public static void generateResponseBody(Result result, HttpServletResponse response) {  
  
    // 0、判空保护  
    if (result == null || response == null) {  
        throw new RuntimeException("result或response对象不能为空!");  
    }  
  
    try {  
        // 1、给响应体设置内容类型  
        response.setContentType("application/json;charset=UTF-8");  
  
        // 2、把 Result 对象转换为 JSON 字符串  
        Gson gson = new Gson();  
        String responseBody = gson.toJson(result);  
  
        // 3、返回响应体  
        response.getWriter().write(responseBody);  
    } catch (IOException e) {  
        throw new RuntimeException(e);  
    }  
  
}
相关推荐
昨天;明天。今天。6 分钟前
案例-任务清单
前端·javascript·css
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己2 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称2 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色2 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2343 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河3 小时前
CSS总结
前端·css
BigYe程普3 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
余生H3 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍3 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发