【JavaWeb】學習筆記——Ajax、Axios
Ajax
Ajax 介紹
AJAX(Asynchronous JavaScript And XML):非同步的JavaScript 和 XML
AJAX 的作用:
- 與伺服器進行資料交換:通過AJAX可以給伺服器傳送請求,並獲取伺服器響應的資料
- 非同步互動:可以在不重新載入整個頁面的情況下,與伺服器互動資料並更新部分網頁的技術
同步和非同步
AJAX 的缺點
- 沒有瀏覽歷史,不能回退
- 存在跨域問題(同源)
- SEO(爬蟲) 不友好,爬不到資料
AJAX 快速入門
GET 請求基本操作
//給button按鈕繫結事件 const btn=document.getElementsByTagName('button')[0]; btn.onclick=function(){ //1.建立核心物件 const xhr=new XMLHttpRequest(); const result=document.getElementById("result"); //2.初始化 設定請求方法和 url xhr.open('GET','http://127.0.0.1:8000/ajaxservlet'); //3.傳送 xhr.send(); //4.事件繫結 處理服務端返回的結果 //on when 當...的時候 //readystate 是 xhr 物件中的屬性表示狀態 // 0:未初始化 1:open()方法呼叫完畢 2:send()方法呼叫完畢 // 3:服務端部分返回結果 4:服務端返回了所以結果 //change 改變 xhr.onreadystatechange =function(){ //判斷(服務端返回了所有結果) if(xhr.readyState===4){ //判斷響應狀態碼 200 404 403 401 500 //2xx 表示成功 if(xhr.status >= 200 && xhr.status < 305){ //處理結果 行、頭、空行(在應用層沒有實際意義)、體 //1.響應行 // console.log(xhr.status);//狀態碼 // console.log(xhr.statusText);//狀態字串 // console.log(xhr.getAllResponseHeaders());//所有頭 // console.log(xhr.response);//響應體 //設定 result 的文字 result.innerHTML=xhr.response;} else{ } } } }
PSOT 請求基本操作
//獲取元素物件 const result =document.getElementById("result"); //繫結事件 result.addEventListener("mouseover",function(){ //1.建立物件 const xhr = new XMLHttpRequest(); //2.初始化 設定型別與 URL xhr.open('POST','http://127.0.0.1:8000/server'); //3.傳送 xhr.send(); //4.事件繫結 xhr.onreadystatechange=function(){ //判斷 if(xhr.readyState===4){ if(xhr.status>=200&&xhr.status<305) { //處理服務端返回的結果 result.innerHTML = xhr.response; } } } });
服務端
@WebServlet("/ajaxservlet") public class ServletDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.響應資料 resp.getWriter().write("hallo ajax"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
案例
使用AJAX驗證使用者名稱是否存在
需求:在完成使用者註冊時,當用戶輸入框失去焦點時,校驗使用者名稱是否在資料庫已存在
前端程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="reg-form" action="#" method="get">
<table>
<tr>
<td>使用者名稱</td>
<td>
<input name="username" type="text" id="username">
<br>
<span id="username_err" style="display: none">使用者名稱已存在</span>
</td>
</tr>
<tr>
<td>密碼</td>
<td>
<input name="password" type="password" id="password">
<br>
</td>
</tr>
</table>
</form>
</body>
<script>
//1. 給使用者名稱輸入框繫結 失去焦點事件
document.getElementById("username").onblur=function (){
//2. 傳送ajax請求
//獲取使用者名稱
var username=this.value;
//建立核心物件
const xhr=new XMLHttpRequest();
const result=document.getElementById("result");
//初始化 設定請求方法和 url
xhr.open('GET','http://localhost:8080/untitled_war/servletUserServlet?username='+username);
xhr.send();//傳送
//事件繫結 處理服務端返回的結果
xhr.onreadystatechange =function(){
if(xhr.readyState===4&&xhr.status >= 200 && xhr.status < 305) {//響應成功
//判斷使用者名稱是否存在
if(this.responseText=="true"){
//存在:顯示提示資訊
document.getElementById("username_err").style.display = '';
}else {
//不存在:清楚提示資訊
document.getElementById("username_err").style.display = 'none';
}
}else {//響應失敗
}
}
}
</script>
</html>
後端程式碼
package com.itheima.web;
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;
@WebServlet("/servletUserServlet")
public class AjaxServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 接收使用者名稱
String username = req.getParameter("username");
//2. 呼叫servlet 查詢User物件
boolean flag = true;
//3. 響應標記
resp.getWriter().write(""+flag);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
AJAX 相關操作
設定請求頭
//設定請求頭
//Content-Type:請求體型別
//application/x-www-from-urllencoded:引數查詢字串型別(固定型別)
xhr.setRequestHeader('Content-Type','application/x-www-from-urllencoded');
xhr.setRequestHeader('name','atguigu');
設定請求引數
//GET請求的引數在位址列中,這種方法容易暴露資料,非常不安全。
xhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');
//POST請求的引數在響應體重,相較於GET資料隱祕性更高。
xhr.send('a=100&b=200&c=300');
xhr.send('a:100&b:200&c:300');/*兩種方式都是有效的*/
JSON物件傳輸方法
- 客戶端
//客戶端我們接收的還是一個字串,如果將這個字串裝為物件呢?
//方法一:手動對資料轉化
let data = JSON.parse(xhr.response);
//方法二:設定響應體資料的型別
xhr.responseType = 'json';
//注意:要在請求初始化的時候就定義
- 服務端
//設定響應頭 設定允許跨域
response.setHeader('Access-Control-Allow-Origin','*');
//設定響應頭
response.setHeader('Access-Control-Allow-Headers','*');
//響應一個數據
const data={
name:'孫悟空'
};
//進行字串轉換
let str=JSON.stringify(data);
//設定響應體
response.send(str);
請求超時與網路異常處理
- 客戶端
//超時設定 超過2s
xhr.timeout=2000;
xhr.ontimeout=function(){//超時回撥
alert("網路異常,請稍後重試");
}
xhr.onerror=function(){//網咯異常回調
alert("你的網路好像有點問題");
}
- 服務端
app.get('/delay',(request,response)=>{
//設定響應頭 設定允許跨域
response.setHeader('Access-Control-Allow-Origin','*');
setTimeout(() => {
//設定響應體
response.send('延時響應');
}, 3000);
});
取消請求
const xhr=new XMLHttpRequest();/*建立物件*/
xhr.abort();
同源策略
- 是瀏覽器的一種安全策略。
- 同源: 協議、域名、埠號 必須完全相同。 違背同源策略就是跨域
不過AJAX是預設滿足同源策略的
跨域解決方案一(只支援 get 請求。
在網頁中有一些標籤天生具有跨域能力,比如:img link iframe script。於是我們可以利用一個非官方的跨域解決方案JSONP 來解決跨域問題,它純粹憑藉程式設計師的聰明才智開發出來的,JSONP 就是利用script 標籤的跨域能力來發送請求的。
JSONP 使用
//1.動態的建立一個 script 標籤
var script = document.createElement("script");
//2.設定 script 的 src,設定回撥函式
script.src = "http://localhost:3000/testAJAX?callback=abc";
function abc(data)
{
alert(data.name);
};
//3.將 script 新增到 body 中
document.body.appendChild(script);
// 4.伺服器中路由的處理
router.get("/testAJAX",function(req , res){
console.log("收到請求");
var callback = req.query.callback;
var obj = {name:"孫悟空", age:18 }
res.send(callback+"("+JSON.stringify(obj)+")");
});
跨域問題解決方案二(支援 get 和 post 請求。
通過設定一個響應頭來告訴瀏覽器,該請求允許跨域,瀏覽器收到該響應以後就會對響應放行。
於是官方給我們提供了一個跨域解決方案 CORS(Cross-Origin Resource Sharing:跨域資源共享)。它的特點是不需要在客戶端做任何特殊的操作,完全在伺服器中進行處理,跨域資源共享標準新增了一組 HTTP 首部欄位,允許伺服器宣告哪些 源站通過瀏覽器有許可權訪問哪些資源
官方文件:https://developer.mozilla.org/zh-CN/docs/web/http/cors
CORS 使用
router.get("/testAJAX" , function (req , res) {
//通過 res 來設定響應頭,來允許跨域請求
//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
res.set("Access-Control-Allow-Origin","*");
res.send("testAJAX 返回的響應");
})
Axios
Axios 非同步框架
Axios 是一個基於 promise 網路請求庫,作用於node.js 和瀏覽器中。 它是 isomorphic 的(即同一套程式碼可以執行在瀏覽器和node.js中)。在服務端它使用原生 node.js http 模組, 而在客戶端 (瀏覽端) 則使用 XMLHttpRequests。Axios 對原生的Ajax進行封裝,簡化書寫
官方網站:https://www.axios-http.cn/docs/intro
特性
- 從瀏覽器建立 XMLHttpRequests
- 從 node.js 建立 http 請求
- 支援 Promise API
- 攔截請求和響應
- 轉換請求和響應資料
- 取消請求
- 自動轉換JSON資料
- 客戶端支援防禦XSRF
安裝
用 npm:
$ npm install axios
使用 bower:
$ bower install axios
使用 yarn:
$ yarn add axios
使用 jsDelivr CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
使用 unpkg CDN:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
快速入門——使用axios 傳送請求,並獲取響應結果
//GET
axios({
method:"get",
url:"http://localhost:8080/ajax-demo/aJAXDemo1?username=zhangshang"
}).then(function(resp)){
alert(resp.data);
}
//POST
axios({
method:"post",
url:"http://localhost:8080/ajax-demo/aJAXDemo1"
data:"username=zhangshang"
}).then(function(resp)){
alert(resp.data);
}
Axios 請求別名
為了方便起見,Axios 已經為所有支援的請求方法提供了別名。
非常方便,閱讀性不強。根據開發場景自行選擇
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.options(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
注意:在使用別名方法時, url、method、data 這些屬性都不必在配置中指定。
示例
//GET請求
axios.get("url")
.then(function(resp)){
alert(resp.data);
});
//POST請求
axios.post("url","引數")
.then(function(resp)){
alert(resp.data);
});