Java体系知识之Ajax&Axios&qs

140 阅读5分钟

Java体系知识之Ajax&Axios&qs

 (1)Ajax
 (2)Axios
 (3)qs
 (4)接口文档
 (5)省市区案例    前后端   MySQL
 ​

1 Ajax(重点)

1.1 传统网站应用

 (1)想在页面中呈现最新的数据:
     需要重新向服务器端发请求,获取最新数据
     假设:网络不太好
     
     form表单,get|post方式
     同步请求
 (2)用户注册:
     用户名
     邮箱
     ...
     客户端需要向服务器端发请求,数据内容验证
     服务器端向客户端写出响应数据,数据是否可用
     
     弊端:
         网络不太好;
         页面跳转|刷新; 页面原有数据不存在->用户重新填写  

1.2 Ajax简介

 (1)Asynchronized JavaScript And Xml
 (2)异步的JavaScript和Xml
 (3)页面不刷新,更新页面局部数据  ***  提高用户体验
 (4)运行在网站环境中
 (5)使用场景:
     表单数据失去焦点数据验证;
     列表数据无刷新分页呈现;  limit m,n;
     页面上拉加载更多数据;
     搜索框提示文字呈现;
     ...
 (6)工作原理:
     传统网站应用:
         客户端->服务端  发请求
         服务端->客户端  发响应
     Ajax:
         浏览器的助手|助理
         Ajax帮助浏览器向服务器发请求;
         Ajax帮助浏览器接收服务器返回的响应数据;
 (7)Ajax使用  ***

1.3 原生JS

1.2.1 get方式

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
 </head>
 <body>
 <form>
     用户姓名:<input type="text" id="userName"/>
     <br>
     用户密码:<input type="password" id="userPwd">
     <br>
     <input type="button" value="注册" id="reg">
 </form>
 </body>
 <script>
     /*当点击注册按钮时*/
     document.getElementById("reg").onclick = function () {
         /*
         * 1.创建Ajax对象
         *   XMLHttpRequest:内置构造函数
         *   XML:数据格式  了解
         *   HttpRequest:HTTP请求
         * */
         var xhr = new XMLHttpRequest();
         /*
         * 2.告知Ajax对象以何种方式向哪个路径发请求
         * 何种方式:GET|POST
         * 哪个路径:请求路径  相对路径|根路径
         *
         * get方式:请求路径后面拼接请求数据
         *
         * */
         var userNameVal = document.getElementById("userName").value;
         var userPwdVal = document.getElementById("userPwd").value;
         var reqData = "userName=" + userNameVal + "&userPwd=" + userPwdVal;
         // console.log(reqData);
         xhr.open("get", "/regist?" + reqData);
         /*
         * 3.发送请求
         * */
         xhr.send();
         /*
         * 4.获取服务端返回的响应数据
         *   onload事件:当服务端有响应数据返回时,该事件被触发
         * */
         xhr.onload = function () {
             // 响应数据
             // JSON格式字符串:{"userName":"tom","userPwd":"1234"}
             console.log(xhr.responseText);
             // JSON格式字符串->JSON对象    JSON.parse()
             console.log(JSON.parse(xhr.responseText));
         }
     }
 </script>
 </html>

1.2.2 post方式

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
 </head>
 <body>
 <form>
     用户姓名:<input type="text" id="userName"/>
     <br>
     用户密码:<input type="password" id="userPwd">
     <br>
     <input type="button" value="注册" onclick="toReg()">
 </form>
 </body>
 <script>
     /*当点击注册按钮时*/
     function toReg() {
         /*
         * 1.创建Ajax对象
         * */
         var xhr = new XMLHttpRequest();
         /*
         * 2.告知Ajax对象以何种方式向哪个路径发请求
         * */
         xhr.open("post", "/regist");
         /*
         * 3.设置请求头信息
         * */
         xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
         /*
         * 4.发送请求
         * */
         var userNameVal = document.getElementById("userName").value;
         var userPwdVal = document.getElementById("userPwd").value;
         var reqData = "userName=" + userNameVal + "&userPwd=" + userPwdVal;
         xhr.send(reqData);
         /*
         * 5.接收响应数据
         * */
         xhr.onload = function () {
             console.log(xhr.responseText);
             console.log(JSON.parse(xhr.responseText));
         }
     }
 </script>
 </html>

2 Axios(重点)

2.1 技术简介

 (1)易用、简洁且高效的http库
 (2)引入axios.js文件:
     任选其一即可,详情如下:
     <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
     <script         
         src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js">
     </script>
 (3)参照文档:
     http://axios-js.com/docs/#axios-post-url-data-config
 (4)使用步骤:
     get方式:
         // Make a request for a user with a given ID
         axios.get('/user?ID=12345')
           .then(function (response) {
             // handle success  处理成功
             console.log(response);
           })
           .catch(function (error) {
             // handle error  处理失败
             console.log(error);
           })
 ​
     post方式:
         axios.post('/user', {
             firstName: 'Fred',
             lastName: 'Flintstone'
           })
           .then(function (response) {
             console.log(response);
           })
           .catch(function (error) {
             console.log(error);
           });

2.2 案例

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
     <!--引入axios的库文件-->
     <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
 </head>
 <body>
 <form>
     用户姓名:<input type="text" id="userName"/>
     <br>
     用户密码:<input type="password" id="userPwd">
     <br>
     <input type="button" value="注册" id="reg">
 </form>
 </body>
 <script>
     /*当点击注册按钮时*/
     document.getElementById("reg").onclick = function () {
         var userNameVal = document.getElementById("userName").value;
         var userPwdVal = document.getElementById("userPwd").value;
         var reqData = "userName=" + userNameVal + "&userPwd=" + userPwdVal;
         // get方式
         /*axios.get("/regist?" + reqData)
             .then(function (resp) {// 成功
                 console.log(resp);
                 console.log(resp.data.userName);
             }).catch(function (error) {//失败
             console.log(error);
         });*/
 ​
         // post方式
         axios.post("/regist", reqData)
             .then(function (resp) {// 成功
                 console.log(resp);
                 console.log(resp.data.userName);
             })
             .catch(function (error) {//失败
                 console.log(error);
             });
     }
 </script>
 </html>

3 案例-用户名验证

3.1 案例分析

 (1)需求:
     判断用户名内容是否可用
 (2)过程:
     name.html->发异步请求->NameServlet->xxService->xxDao
     NameServlet:模拟操作,假设数据表中已有用户lucy,利用输出流写出响应数据
     响应数据:包含提示信息,用户名可用 | 用户名被占用;
     name.html:给用户提示
 (3)技术:
     Servlet+Vue+Axios+JSON

3.2 案例实现

3.2.1 name.html

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
     <!--Vue.js文件-->
     <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
     <!--引入axios的库文件-->
     <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
     <style>
         .red {
             color: red;
         }
 ​
         .green {
             color: green;
         }
 ​
     </style>
 </head>
 <body>
 <!--根标签-->
 <div id="root">
     <input type="text" v-model="userName" @change="judgeName()">
     <span :class="msgCls">{{nameMsg}}</span>
 </div>
 </body>
 <script>
     new Vue({
         el: "#root",
         data: {
             userName: '',
             nameMsg: '',
             msgCls: ''
         },
         methods: {
             /*向服务器端发异步请求*/
             judgeName() {
                 axios.post("/name", "userName=" + this.userName)
                     .then(resp => {
                         console.log(resp)
                         // 设置提示信息
                         this.nameMsg = resp.data.returnMsg;
                         // 设置字体颜色
                         this.msgCls = resp.data.returnData;
                     })
                     .catch(error => {
                         console.log(error);
                     });
             }
 ​
         },
         mounted() {
 ​
         }
     })
 ​
 </script>
 </html>

3.2.2 NameServlet

 package com.javasm.servlet;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;
 ​
 /**
  * @author: ShangMa
  * @className: NameServlet
  * @description: 控制层-验证用户名
  * @date: 2022/8/24 16:39
  */
 @WebServlet("/name")
 public class NameServlet extends HttpServlet {
     @Override
     protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         // 接收请求数据
         req.setCharacterEncoding("utf-8");
         String userName = req.getParameter("userName");
         // 写出响应数据
         resp.setContentType("application/json;charset=utf-8");
         PrintWriter writer = resp.getWriter();
         // 假设数据表中已有用户lucy,判断
         if ("lucy".equals(userName)) {
             // 用户名不可用 {"returnMsg":"用户名不可用","returnData":"red"}
             writer.print("{"returnMsg":"用户名不可用","returnData":"red"}");
         } else {
             // 用户名可用
             writer.print("{"returnMsg":"用户名可用","returnData":"green"}");
         }
         writer.flush();
         writer.close();
     }
 }

4 qs(重点)

4.1 技术简介

 (1)为简化操作,我们可把整个表单对象中的数据当作一个整体发送到服务器端
 (2)将JSON对象转换成key=val&key=val&...键值对的字符串拼接格式
     Qs.stringify()
 (3)使用步骤:
     A.引入js文件,任选其一即可:
         <script 
             src="https://cdn.bootcdn.net/ajax/libs/qs/6.11.0/qs.js">
         </script>
         
         <script 
             src="https://cdn.bootcdn.net/ajax/libs/qs/6.11.0/qs.min.js">
         </script>
     B.Qs.stringify()

4.2 案例

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
     <!--Vue.js文件-->
     <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
     </script>
     <!--引入axios的库文件-->
     <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
     <!--引入qs的类库文件-->
     <script src="https://cdn.bootcdn.net/ajax/libs/qs/6.11.0/qs.js"></script>
 </head>
 <body>
 <div id="root">
     <form>
         用户姓名:<input type="text" v-model="regForm.userName"/>
         <br>
         用户密码:<input type="password" v-model="regForm.userPwd">
         <br>
         <input type="button" value="注册" @click="reg()">
     </form>
 </div>
 </body>
 <script>
     new Vue({
         el: "#root",
         data: {
             regForm: {
                 userName: '',
                 userPwd: ''
             }
         },
         methods: {
             reg() {
                 // var reqData=this.regForm;
                 /**
                  * Qs.stringify():
                  *  将JSON对象转换成key=val&key=val&...键值对的字符串拼接格式
                  */
                 // userName=tom&userPwd=1234
                 console.log(Qs.stringify(this.regForm));
                 axios.get("/regist?" + Qs.stringify(this.regForm))
                     .then(resp => {
                         console.log(resp);
                     })
                     .catch(error => {
                         console.log(error);
                     })
             }
         }
     })
 </script>
 </html>

5 接口文档

5.1 内容概述

(1)便于前后端同时开发
(2)文档:
	请求路径
	请求参数
	请求方式
	返回数据格式
	返回数据内容

5.2 验证用户名案例-改造版

5.2.1 ReturnEntity

 package com.javasm.entity;
 ​
 import lombok.*;
 ​
 import java.util.Objects;
 ​
 /**
  * @author: ShangMa
  * @className: ReturnEntity
  * @description: 实体类-响应数据
  * @date: 2022/8/25 9:38
  */
 @NoArgsConstructor
 @AllArgsConstructor
 @Setter
 @Getter
 @ToString
 public class ReturnEntity {
     // 状态码
     private Integer returnCode;
     // 描述信息
     private String returnMsg;
     // 数据
     private Object returnData;
     
 }

5.2.2 CodeAndMsg

 package com.javasm.entity;
 ​
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 ​
 /**
  * @author: ShangMa
  * @className: CodeAndMsg
  * @description: 枚举
  * @date: 2022/8/25 9:52
  */
 @AllArgsConstructor
 @Getter
 public enum CodeAndMsg {
     NAME_YES(2000, "用户名可用"),
     NAME_NO(4000, "用户名不可用");
 ​
     // 状态码
     private Integer returnCode;
     // 描述信息
     private String returnMsg;
 ​
 }

5.2.3 NameServlet

 package com.javasm.servlet;
 ​
 import com.alibaba.fastjson.JSON;
 import com.javasm.entity.CodeAndMsg;
 import com.javasm.entity.ReturnEntity;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;
 ​
 /**
  * @author: ShangMa
  * @className: NameServlet
  * @description: 控制层-验证用户名
  * @date: 2022/8/24 16:39
  */
 @WebServlet("/name")
 public class NameServlet extends HttpServlet {
     @Override
     protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         // 接收请求数据
         req.setCharacterEncoding("utf-8");
         String userName = req.getParameter("userName");
         // 写出响应数据
         resp.setContentType("application/json;charset=utf-8");
         PrintWriter writer = resp.getWriter();
         ReturnEntity re = new ReturnEntity();
         // 假设数据表中已有用户lucy,判断
         if ("lucy".equals(userName)) {
             re.setReturnCode(CodeAndMsg.NAME_NO.getReturnCode());
             re.setReturnMsg(CodeAndMsg.NAME_NO.getReturnMsg());
             re.setReturnData("red");
         } else {
             re.setReturnCode(CodeAndMsg.NAME_YES.getReturnCode());
             re.setReturnMsg(CodeAndMsg.NAME_YES.getReturnMsg());
             re.setReturnData("green");
         }
         // JSON.toJSONString():将Object类型值转换成JSON格式字符串值
         // System.out.println(JSON.toJSONString(re));
         writer.print(JSON.toJSONString(re));
         writer.flush();
         writer.close();
     }
 }

6 省市区案例

6.1 案例分析

 (1)需求:
     三个下拉选:省|市|区县
 (2)过程:
     Vue+Axios+qs+Servlet+MySQL
     area.html->AreaServlet->AreaService->AreaDao
     AreaServlet->area.html
 (3)数据表
     t_area
     
     area_code   编号
     area_name   名称
     parent_code 上级编号
 (4)持久层:
     String sql = "select area_code,area_name,parent_code from t_area where parent_code=?";

6.2 过程实现

6.2.1 持久层

6.2.1.1 AreaDao
package com.javasm.dao;

import com.javasm.entity.Area;

import java.sql.SQLException;
import java.util.List;

/**
 * @author: ShangMa
 * @className: AreaDao
 * @description: 持久层接口-地区
 * @date: 2022/8/24 19:31
 */
public interface AreaDao {

    /**
     * 根据上级编号查询地区数据
     *
     * @param parentCode 上级编号
     * @return 地区数据
     */
    List<Area> findAreaList(Integer parentCode) throws SQLException;

}
6.2.1.2 AreaDaoImpl
 package com.javasm.dao.impl;
 ​
 import com.javasm.dao.AreaDao;
 import com.javasm.entity.Area;
 import com.javasm.util.DBUtils;
 import org.apache.commons.dbutils.BasicRowProcessor;
 import org.apache.commons.dbutils.GenerousBeanProcessor;
 import org.apache.commons.dbutils.QueryRunner;
 import org.apache.commons.dbutils.handlers.BeanListHandler;
 ​
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.List;
 ​
 /**
  * @author: ShangMa
  * @className: AreaDaoImpl
  * @description: 持久层实现类-地区
  * @date: 2022/8/24 19:31
  */
 public class AreaDaoImpl implements AreaDao {
     QueryRunner runner = new QueryRunner();
 ​
     @Override
     public List<Area> findAreaList(Integer parentCode) throws SQLException {
         Connection conn = DBUtils.getConn();
         String sql = "select area_code,area_name,parent_code from t_area where parent_code=?";
         BeanListHandler<Area> listHandler = new BeanListHandler<>(Area.class, new BasicRowProcessor(new GenerousBeanProcessor()));
         List<Area> areaList = runner.query(conn, sql, listHandler, parentCode);
         DBUtils.getClose(conn, null, null, null);
         return areaList;
     }
 }
 ​
 实体类
 ​
 @NoArgsConstructor
 @AllArgsConstructor
 @Setter
 @Getter
 @ToString
 public class Area {
     // 编号
     private Integer areaCode;
     // 名称
     private String areaName;
     // 上级编号
     private Integer parentCode;
 ​
 }

6.2.2 业务层

6.2.2.1 AreaService
 package com.javasm.service;
 ​
 import com.javasm.entity.Area;
 ​
 import java.util.List;
 ​
 /**
  * @author: ShangMa
  * @className: AreaService
  * @description: 业务层接口-地区
  * @date: 2022/8/24 19:32
  */
 public interface AreaService {
     /**
      * 根据上级编号查询地区数据
      *
      * @param parentCode 上级编号
      * @return 地区数据
      */
     List<Area> findAreaList(Integer parentCode);
 }
6.2.2.2 AreaServiceImpl
 package com.javasm.service.impl;
 ​
 import com.javasm.dao.AreaDao;
 import com.javasm.dao.impl.AreaDaoImpl;
 import com.javasm.entity.Area;
 import com.javasm.service.AreaService;
 ​
 import java.sql.SQLException;
 import java.util.List;
 ​
 /**
  * @author: ShangMa
  * @className: AreaServiceImpl
  * @description: 业务层实现类-地区
  * @date: 2022/8/24 19:32
  */
 public class AreaServiceImpl implements AreaService {
     AreaDao areaDao = new AreaDaoImpl();
 ​
     @Override
     public List<Area> findAreaList(Integer parentCode) {
         List<Area> areaList = null;
         try {
             areaList = areaDao.findAreaList(parentCode);
         } catch (SQLException e) {
             throw new RuntimeException(e);
         }
         return areaList;
     }
 }

6.2.3 控制层

 package com.javasm.servlet;
 ​
 import com.alibaba.fastjson.JSON;
 import com.javasm.entity.Area;
 import com.javasm.entity.CodeAndMsg;
 import com.javasm.entity.ReturnEntity;
 import com.javasm.service.AreaService;
 import com.javasm.service.impl.AreaServiceImpl;
 ​
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.List;
 ​
 /**
  * @author: ShangMa
  * @className: AreaServlet
  * @description: 控制层-地区
  * @date: 2022/8/24 19:30
  */
 @WebServlet("/area")
 public class AreaServlet extends HttpServlet {
     @Override
     protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         // 接收数据->处理请求->返回响应数据
         req.setCharacterEncoding("utf-8");
         String parentCodeStr = req.getParameter("parentCode");
         // 转型
         Integer parentCode = null;
         if (parentCodeStr != null && !"".equals(parentCodeStr)) {
             parentCode = Integer.valueOf(parentCodeStr);
         }
         // 调用业务层方法
         AreaService areaService = new AreaServiceImpl();
         List<Area> areaList = areaService.findAreaList(parentCode);
         // 写出响应数据
         resp.setContentType("application/json;charset=utf-8");
         PrintWriter writer = resp.getWriter();
         ReturnEntity re = new ReturnEntity();
         // 判断
         if (areaList.size() > 0) {
             re.setReturnCode(CodeAndMsg.DATA_SUCCESS.getReturnCode());
             re.setReturnMsg(CodeAndMsg.DATA_SUCCESS.getReturnMsg());
             re.setReturnData(areaList);
         } else {
             re.setReturnCode(CodeAndMsg.DATA_FAILURE.getReturnCode());
             re.setReturnMsg(CodeAndMsg.DATA_FAILURE.getReturnMsg());
         }
         writer.print(JSON.toJSONString(re));
         writer.flush();
         writer.close();
     }
 }

6.2.4 area.html

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
     <!--Vue.js文件-->
     <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
     <!--引入axios的库文件-->
     <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
 </head>
 <body>
 <div id="root">
     <select v-model="proCode" @change="getCity()">
         <option value="" disabled>请选择</option>
         <option :value="pro.areaCode" v-for="pro in proList">{{pro.areaName}}</option>
     </select>省
     <select v-model="cityCode" @change="getCoun()">
         <option value="" disabled>请选择</option>
         <option :value="city.areaCode" v-for="city in cityList">{{city.areaName}}</option>
     </select>市
     <select v-model="counCode">
         <option value="" disabled>请选择</option>
         <option :value="coun.areaCode" v-for="coun in counList">{{coun.areaName}}</option>
     </select>区县
 </div>
 ​
 </body>
 <script>
     new Vue({
         el: "#root",
         data: {
             /*省*/
             proCode: '',
             proList: [],
             /*市*/
             cityCode: '',
             cityList: [],
             /*区县*/
             counCode: '',
             counList: []
         },
         methods: {
             /*加载市数据*/
             getCity() {
                 // 将市数据恢复成请选择
                 this.cityCode = "";
                 // 把区县数据恢复成请选择
                 this.counCode = "";
                 this.counList = [];
                 // 获取省数据编号
                 var provinceCode = this.proCode;
                 console.log(provinceCode);
                 axios.get("/area?parentCode=" + provinceCode)
                     .then(resp => {
                         console.log(resp);
                         this.cityList = resp.data.returnData;
                     }).catch(error => {
                 })
             },
 ​
             /*加载区县数据*/
             getCoun() {
                 // 把区县数据恢复成请选择
                 this.counCode = "";
                 // 获取市数据编号
                 var cityCode = this.cityCode;
                 console.log(cityCode);
                 axios.get("/area?parentCode=" + cityCode)
                     .then(resp => {
                         console.log(resp);
                         this.counList = resp.data.returnData;
                     }).catch(error => {
                 })
             }
 ​
         },
         mounted() {
             /*获取省数据*/
             axios.post("/area", "parentCode=0")
                 .then(resp => {
                     console.log(resp);
                     /* data:
                          returnCode: 2001
                          returnData: Array(2)
                              0: {areaCode: 110000, areaName: '北京市', parentCode: 0}
                              1: {areaCode: 130000, areaName: '河北省', parentCode: 0}
                          returnMsg: "数据存在"*/
                     this.proList = resp.data.returnData;
                 }).catch(error => {
                 console.log(error);
             })
         }
     })
 </script>
 </html>