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 () {
var xhr = new XMLHttpRequest();
var userNameVal = document.getElementById("userName").value;
var userPwdVal = document.getElementById("userPwd").value;
var reqData = "userName=" + userNameVal + "&userPwd=" + userPwdVal;
xhr.open("get", "/regist?" + reqData);
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
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() {
var xhr = new XMLHttpRequest();
xhr.open("post", "/regist");
xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
var userNameVal = document.getElementById("userName").value;
var userPwdVal = document.getElementById("userPwd").value;
var reqData = "userName=" + userNameVal + "&userPwd=" + userPwdVal;
xhr.send(reqData);
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:
(4)使用步骤:
get方式:
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (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>
<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;
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>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<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;
@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();
if ("lucy".equals(userName)) {
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>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
</script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<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() {
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;
@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;
@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;
@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();
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");
}
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;
public interface AreaDao {
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;
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;
public interface AreaService {
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;
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
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>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<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);
this.proList = resp.data.returnData;
}).catch(error => {
console.log(error);
})
}
})
</script>
</html>