Ajax的使用詳解
什麼是Ajax?
簡單說就是頁面傳送請求時,使用者能夠看到頁面,不是空白的而傳統的web應用是同步的,傳送請求,未響應回來(頁面上白色的,體驗不好)Ajax能解決這個問題。頁面不重新載入能完成區域性頁面更新
- Ajax 即“Asynchronous Javascript And XML”(非同步 JavaScript 和 XML),是指一種建立互動式、快速動態應用的網頁開發技術,無需重新載入整個網頁的情況下,能夠更新頁面區域性資料的技術。
通過在後臺與伺服器進行少量資料交換,Ajax 可以使頁面實現非同步更新。這意味著可以在不重新載入整個頁面的情況下,對頁面的某部分進行更新。
Ajax使用
XMLHttp物件
XMLHttpRequest 是瀏覽器介面物件,該物件的 API 可被 JavaScript、VBScript 以及其它 web 瀏覽器內嵌的指令碼語言呼叫,通過 HTTP 協議在瀏覽器和 web 伺服器之間收發 XML或其它資料。XMLHttpRequest 可以與伺服器實現非同步互動,而無需讓整個頁面重新整理,因此成為Ajax程式設計的核心物件。
使用的方法
- 建立XMLHttpRequest物件
var xhr =new XMLHttpRequest();
- 給指定請求方式以及請求地址
xhr.open("get","請求的url");
- 傳送請求
xhr.send()
- 獲取伺服器給客戶端的響應資料
//給onreadystatechange這個屬性附一個函式地址(回撥) xhr.onreadystatechange = function () { // 做狀態判斷,4表示響應結束,以及狀態是200 if(xhr.readyState == 4 && xhr.status==200){ //取響應內容,這個就是服務端響應的內容 alert(xhr.responseText); //新增到span標籤中 document.getElementById("span").innerHTML=xhr.responseText; } }
案例實現
首先建立新的專案,依舊需要進行導包(servletjar包),其次就是在servlet進行響應時不能使用重定向和請求轉發的方式進行(需要使用字元輸出流進行)
//jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script>
function but() {
// 建立物件
var xhr = new XMLHttpRequest();
//給定請求方式和url
xhr.open("get","ajax.do");
//傳送非同步請求
xhr.send();
//給onreadystatechange這個屬性附一個函式地址(回撥)
xhr.onreadystatechange = function () {
// 做狀態判斷,4表示響應結束,以及狀態是200
if(xhr.readyState == 4 && xhr.status==200){
//取響應內容,這個就是服務端響應的內容
alert(xhr.responseText);
//新增到span標籤中
document.getElementById("span").innerHTML=xhr.responseText;
}
}
}
</script>
</head>
<body>
<h3>北京你好</h3>
<hr/>
<span id="span"></span>
<input type="button" value="ok" onclick="but()">
</body>
</html>
//建立servlet
package com.hhxx.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("/ajax.do")
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//響應資料不能使用(處理非同步請求產生響應)重定向和請求轉發,不是讓瀏覽器處理響應
//使用字元流刪除流
PrintWriter pw =resp.getWriter();
pw.println("hello Ajax");
pw.flush();
pw.close();
}
}
實現原理
實現非同步的主要原理
- 我們需要通過一個事件來觸發非同步請求,從而會例項化xhr(ajax核心物件),通過這個物件呼叫send()方法傳送請求,服務端收到請求進行響應(通過字元輸出流的方式。誰來處理我們響應的內容?xhr通過回撥的方式,呼叫xhr.onreadystatechage(呼叫onreadystatechage的函式,而我們的函式就在它呼叫的這個函式裡)從而完成請求的實現
json使用
什麼是json
是基於字串的輕量級的資料互動格式,json是JavaScript資料型別的子集。在json之前會使用xml進行資料格式傳輸資料,而json出現之後則使用json傳輸,因為json比xml更小更快,易於解析
json格式特點
JSON 是按照特定的語法規則所生成的字串結構。
- 大括號表示 JSON 的字串物件。{ }
- 屬性和值用冒號分割。{"屬性":"value"} 若value是數字不用加雙引號
- 屬性和屬性之間用逗號分割。{"屬性":"value","屬性":"value",...} - 中括號表示陣列。[{"屬性":"value"...},{"屬性":"value"...}]
json物件
{"userid":1,"username":"admin","sex":"male"}
[{"userid":1,"username":"admin"},{"userid":2,"username":"oldlu"}]
json資料型別
- string:字串,必須要用雙引號引起來。
- number:數值,與 JavaScript 的 number 一致,
- object:JavaScript 的物件形式,{ key:value }表示方式,可巢狀。
- array:陣列,JavaScript 的 Array 表示方式[ value ],可巢狀。
- true/false:布林型別,JavaScript 的 boolean 型別。
- null:空值,JavaScript 的 null。
Jackson使用
jdk沒有內建操作JSON格式的資料API,因此需要藉助第三方類庫來處理json資料
這裡以Jacson為例,使用之前需要下載3個jar包
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
在響應中通過json格式傳遞資料
在響應中使用jackson處理json步驟
1.新增 jackson-annotations.jar、jackson-core.jar、jackson-databind.jar
2.通過 jackson API 將 Java 物件轉換 JSON 格式
3.修改響應頭,響應型別為 application/json
4.將結果基於字元輸出流推回客戶端瀏覽器
5.在頁面的中通過 JavaScript 的 JSON.parse()函式將 JSON 格式的資料轉換為 JavaScript物件,json屬於特殊格式的字串結構,通過解析來操作js物件,從而方便的獲取響應資料
通過json格式響應傳遞單個物件
需求:
定義一個 Users 類,包含 userid、username 屬性。
例項化一個 Users 物件,通過 JSON 格式將 Users 物件響應到客戶端瀏覽器。 將 Users 物件中的資料插入到頁面中。
省略Users類
/**
* 通過json格式響應單個物件
* */
@WebServlet("/single.do")
public class SingleObjectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//建立users物件
Users users =new Users();
users.setUserid(1);
users.setUsername("jack");
//user物件不能用字元流進行輸出(輸出是物件的引用)
//使用jackson的api將users物件轉換為json格式的字串物件
ObjectMapper objectMapper =new ObjectMapper();
String string = objectMapper.writeValueAsString(users);
System.out.println(string);
//設定響應型別為application/json
resp.setContentType("application/json");
PrintWriter pw = resp.getWriter();
pw.println(string);
pw.flush();
pw.close();
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script>
function but() {
// 建立物件
var xhr = new XMLHttpRequest();
//給定請求方式和url
xhr.open("get","single.do");
//傳送非同步請求
xhr.send();
//給onreadystatechange這個屬性附一個函式地址(回撥)
xhr.onreadystatechange = function () {
// 做狀態判斷,4表示響應結束,以及狀態是200
if(xhr.readyState == 4 && xhr.status==200){
//取響應內容,這個就是服務端響應的內容
alert(xhr.responseText);
//通過javascript的內建物件Jason的parse函式將json格式的字串物件轉換成JavaScript物件
//新增到span標籤中
var obj = JSON.parse(xhr.responseText)
alert(obj.userid+" "+obj.username);
document.getElementById("span").innerHTML=obj.userid+"<br/>"+obj.username;
}
}
}
</script>
</head>
<body>
<h3>json格式的單個物件使用</h3>
<hr/>
<span id="span"></span>
<input type="button" value="ok" onclick="but()">
</body>
</html>
- 對於多個物件使用json格式響應,其實和單個大同小異,這裡list是儲存多個物件的集合,只需要注意:
1.依舊是通過建立ObjectMapper物件和呼叫writeValueAsString()方法
ObjectMapper objectMapper =new ObjectMapper();
//不管什麼物件,都能轉換成字串
String string = objectMapper.writeValueAsString(list);
2.在結果輸出的時候使用迴圈和拼接進行輸出
if (xhr.readyState == 4 && xhr.status==200){
alert(xhr.responseText);
var obj = JSON.parse(xhr.responseText);
var temp ="";
//由於是一個list物件需要進行遍歷
for(i=0;i<obj.length;i++){
alert(obj[i].userid+" "+obj[i].username);
temp += obj[i].userid+" "+obj[i].username+"<br/>"
}
document.getElementById("span").innerHTML = temp;
}
在json中通過map傳遞資料
map屬於通用型的資料,本身就有key和value的結構和json格式物件模型完全匹配,我們可以直接將一個Map物件轉換為json字元物件。
public class MapModelServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//一個Map物件表示的是一個Jason格式物件
Map<String,Object> map =new HashMap<>();
map.put("userid",1);
//不改變實體類
map.put("url","map.do");
ObjectMapper objectMapper =new ObjectMapper();
String string =objectMapper.writeValueAsString(map);
resp.setContentType("application/json");
PrintWriter pw = resp.getWriter();
System.out.println(string);
pw.println(string);
pw.flush();
pw.close();
}
}
請求中通過json格式傳遞資料
請求中傳遞資料,提交方式需要使用Post
請求中使用JackSon處理JSON格式資料步驟
- 新增 jackson-annotations.jar、jackson-core.jar、jackson-databind.jar
- 在頁面的 JavaScript 中通過 JSON.stringify()函式將 JavaScript 物件轉換為 JSON 格式的資料
js物件{屬性名:值,屬性名:值}
json物件{"userid":1,"username":"admin"} - 將請求方式修改為 POST 方式 (tomcat不會處理)
- 通過 send()函式將 JSON 格式的資料提交到服務端。
- 在 Servlet 中通過字元輸入流讀取請求體中 JSON 格式的資料
- 通過 jackson API將獲取到的 JSON 格式的資料轉換為 Java 物件
具體實現
servelt:
**
* 在請求中通過json格式傳遞資料
* */
@WebServlet("/json.do")
public class RequestJSONServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通過字元輸入流從請求體中獲取提交的json格式資料
req.setCharacterEncoding("utf-8");
String s = req.getReader().readLine();
//使用Jackson將JSON格式字串物件轉換成java物件
ObjectMapper objectMapper =new ObjectMapper();
//json物件有哪些屬性,返回Users物件
Users users = objectMapper.readValue(s, Users.class);
System.out.println(users.getUserid()+""+users.getUsername());
resp.setContentType("application/json");
PrintWriter pw = resp.getWriter();
pw.print("ok");
pw.flush();
pw.close();
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script>
function but() {
//取請求的值
var id = document.getElementById("userid").value;
var name =document.getElementById("username").value;
//定義js物件,屬性名要和對應屬性的名字相同(這裡是Users類)
var obj ={userid:id,username:name}
//將js物件轉換成json格式的物件
var content =JSON.stringify(obj);
alert(content);
// 建立物件
var xhr = new XMLHttpRequest();
//給定請求方式和url
xhr.open("post","json.do");
//傳送非同步請求,傳遞到servlet中
xhr.send(content);
//給onreadystatechange這個屬性附一個函式地址(回撥)
xhr.onreadystatechange = function () {
// 做狀態判斷,4表示響應結束,以及狀態是200
if(xhr.readyState == 4 && xhr.status==200){
//取響應內容,這個就是服務端響應的內容
alert(xhr.responseText);
document.getElementById("span").innerHTML=xhr.responseText;
}
}
}
</script>
</head>
<body>
<h3>在請求中通過json格式傳遞資料</h3>
<hr/>
使用者ID:<input name="userid" id="userid"/><br/>
使用者姓名:<input name="username" id="username"/><br/>
<span id="span"></span>
<input type="button" value="ok" onclick="but()">
</body>
</html>
常用註解
- @JsonProperty
此註解用於屬性上,作用是把該屬性的名稱序列化為另外一個名稱,如把 username 屬 性序列化為 name,@JsonProperty("name")。其實就是給json改名 - @JsonIgnore
此註解用於屬性或者方法上(一般都是定義在屬性上),用來完全忽略被註解的欄位和 方法對應的屬性,返回的 json 資料即不包含該屬性。多個註解時有@JsonIgnore則會忽略所有註解 - @JsonFormat
此註解用於屬性或者方法上(一般都是定義在屬性上),可以方便的把 Date 型別屬性的值直接轉化為我們想要的樣式。如:@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss")
jackson工具類使用
我們在使用jackson時,每次都需要呼叫一些物件如:ObjectMapper,因此將重複物件做工具類的封裝方便每次的呼叫
/**
* JSON轉換工具類
*/
public class JsonUtils {
// 定義jackson物件
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 將物件轉換成json字串。
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 將json結果集轉化為物件
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 將json資料轉換成pojo物件list
*/
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Jquery的Ajax使用
JQuery中提供了ajax封裝,可以讓我們使用ajax技術更加方便。
$.ajax()使用
常用的語法結構$({})
data: 規定傳送到伺服器的資料
success():當請求成功執行的函式
type: 規定請求型別(post或get)
url:規定傳送請求的的url,預設是當前頁面
$.ajax()非同步中請求提交資料
$.ajax()方法中通過data屬性來存放提交的資料,支援JSON格式的資料
在date屬性中有兩種方式提交資料資料,標準格式和js物件來指定提交資料。無論使用哪種方式在Servlet中通過request.getParameter方式獲取name來獲取value
- 通過標準格式指定提交資料
data:”name=value&name=value.....” - 通過JavaScript物件指定提交資料
data:{
userid:100
username:jay
}
程式碼例項
/**
* 在$.ajax()方法提交資料
* */
@WebServlet("/data.do")
public class DataServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取Date提交的資料
String userid =req.getParameter("id");
String username =req.getParameter("name");
PrintWriter pw = resp.getWriter();
pw.print("userid="+userid+" username="+username);
pw.flush();
pw.close();
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
function but() {
//獲取瀏覽器輸入的值
var userid =$("#userid").val();
var username =$("#username").val();
$.ajax({
type:"get",
url:"data.do",
//標準方式
//data:"id="+userid+"&name="+username,
//js物件
data:{
id:userid,
name:username
},
success:function (result) {
$("#span").html(result);
}
});
}
</script>
</head>
<body>
使用者ID:<input type="text" id="userid"/><br/>
使用者名稱:<input type="text" id="username"/><br/>
<span id="span"></span>
<input type="button" value="ok" onclick="but()"/>
</body>
</html>
提交json格式資料
在$.ajax()中提交 JSON 格式的資料需要使用post方式提交,通過 JSON.stringify()函式將 JavaScript 物件轉換成 JSON 格式的字串。在 Servlet 中通過字元輸入獲取提交的 JSON 格式 的資料。
data:JSON.stringify({name:value,name:value......})
在 Servlet 中通過 req.getReader().readLine()來獲取提交的資料。
- 需要修改jsp中的type:post
- 將js格式轉換為json格式,以上面的案例為例,將date:後面的內容放入函式中 JSON.stringify()
data:JSON.stringify({
id:userid,
name:username
}),
$ajax()處理響應中JSON格式資料
js格式物件:{userid=aa username=111}
json格式物件:{"id":"aa","name":"111"}
通過新增dataType:“json”,將json格式轉換為js格式物件
- $.ajax()方法會根據 dataType 屬性中的值自動對響應的資料做型別處理。如果響應的是一個 JSON 格式的資料,那麼 dataType 的值為“JSON”,在回撥函式中我們得到的直接就是JSON 字串轉換完的 JavaScript 物件。不需要在使用 JSON.parse()做格式的轉換處理。
/**
* 提交json格式資料在頁面中自動轉換型別
*以json格式提交資料需要通過字元輸入流進行接收
* 若是以標準型別或者js物件提交的話直接獲取相應的值
* */
@WebServlet("/jsonConvert.do")
public class jsonConvertServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json");
//字元輸入流獲取的就是json的資料
req.setCharacterEncoding("utf-8");
String s = req.getReader().readLine();
resp.setCharacterEncoding("utf-8");
PrintWriter pw =resp.getWriter();
pw.print(s);
pw.flush();
pw.close();
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
function but() {
//獲取瀏覽器輸入的值
var userid =$("#userid").val();
var username =$("#username").val();
$.ajax({
//必須使用post提交
type:"post",
url:"jsonConvert.do",
//json格式轉換成js物件
dataType:"json",
//標準方式
//data:"id="+userid+"&name="+username,
//js物件轉換成Json格式進行提交
data:JSON.stringify({
id:userid,
name:username
}),
success:function (result) {
alert(result.id+" "+result.name);
$("#span").html(result.id+" "+result.name);
}
});
}
</script>
</head>
<body>
使用者ID:<input type="text" id="userid"/><br/>
使用者名稱:<input type="text" id="username"/><br/>
<span id="span"></span>
<input type="button" value="ok" onclick="but()"/>
</body>
$.get()的使用
該方法是$.ajax()方法基於 get 方式傳送非同步請求的簡化版。
語法結構 $.get(url,function(result)),不需要再使用$.ajax()
$.get(url,data,function(result))
通過標準格式指定提交資料 $.get(url,”name=value&name=value”,function(result))
通過 JavaScript 物件指定提交資料 $.get(url,{userid:1,username:”oldlu”,......},function(result))
function but() {
//獲取瀏覽器輸入的值,data存放提交的資料
var userid = $("#userid").val();
var username = $("#username").val();
//標準格式資料提交
// $.get("data.do", "id="+userid+"&name="+username,function (result) {
// $("#span").html(result);
// });
//js物件格式,提交資料
$.get("data.do", {id:userid,name:username},function (result) {
$("#span").html(result);
});
}
$.post()的使用
$.post()方法是$.ajax()方法基於 post 方式傳送非同步請求的簡化版。
語法結構 $.post(url,function(result))
$.post(url,data,function(result))
通過標準格式指定提交資料 $.post(url,”name=value&name=value”,function(result))
通過 JavaScript 物件指定提交資料 $.post(url,{userid:1,username:”oldlu”,......},function(result))
$.getJSON()的使用
相當於簡化了dateType設定
$.getJSON()方法是$.ajax()方法基於 get 方式傳送非同步請求,並將響應結果中 JSON 格式 的字串物件自動轉換為 JavaScript 物件。在使用該方法時要求返回的資料必須是JSON格式型別。$.getJSON()方法和 resp.setContentType(“application/json”)是一起使用的。
語法結構 $.getJSON(url,function(result))
$.getJSON(url,data,function(result))
通過標準格式指定提交資料 $.getJSON(url,”name=value&name=value”,function(result))
要求返回的資料格式必須是 JSON 格式。
通過 JavaScript 物件指定提交資料
$.getJSON(url,{userid:1,username:”oldlu”,......},function(result)) 要求返回的資料格式必須是 JSON 格式。
/**
* getJSON方法傳遞資料並返回JSON格式資料
* */
@WebServlet("/getJson.do")
public class GetJSONServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
//這裡的名稱要與jsp中date存放的名稱保持一致
String userid =req.getParameter("id");
String username =req.getParameter("name");
Map<String ,String> map =new HashMap<>();
map.put("userid",userid);
map.put("username",username);
//轉換成Json格式字串物件
String s=JsonUtils.objectToJson(map);
resp.setContentType("appliction/json");
PrintWriter pw =resp.getWriter();
pw.print(s);
pw.flush();
pw.close();
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
function but() {
//獲取瀏覽器輸入的值,data存放提交的資料
var userid = $("#userid").val();
var username = $("#username").val();
//標準格式資料提交
$.getJSON("getJson.do", "id="+userid+"&name="+username,function (result) {
// 這個userid的key要與map(getJSONServlet)中的key相同,返回的是js物件
alert(result.userid+" "+result.username)
$("#span").html(result.userid+" "+result.username);
});
}
</script>
</head>
<body>
使用者ID:<input type="text" id="userid"/><br/>
使用者名稱:<input type="text" id="username"/><br/>
<span id="span"></span>
<input type="button" value="ok" onclick="but()"/>
</body>
</html>
serialize()方法的使用
將 form 表單中的資料自動拼接成 name=value&name=value 結構。
- 語法結構
var param = $(“form”).serialize();
param 的值為:name=value&name=value
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
function but() {
//獲取瀏覽器輸入的值,data存放提交的資料
// var userid =$("#userid").val();
// var username =$("#username").val();
//使用serializa()方法拼接,需放入from表當中,拼接的是name-value,所以標籤中要使用name名,名與servlet的名一致
var param = $("#form").serialize();
alert(param);
//標準方式提交資料
//data:"id="+userid+"&name="+username,
$.get("data.do",param,function(result){
$("#span").html(result);
})
}
</script>
</head>
<body>
<form id="form">
使用者ID:<input type="text" name="id" id="userid"/><br/>
使用者名稱:<input type="text" name="name" id="username"/><br/>
</form>
<span id="span"></span>
<input type="button" value="ok" onclick="but()"/>
</body>
</html>