學習B站狂神的視頻,轉載狂神的博客
文章鏈接:https://www.cnblogs.com/hellokuangshen/p/11283224.html#springmvcajax和json
什麼是JSON?
JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式,目前使用特別廣泛。
採用完全獨立於編程語言的文本格式來存儲和表示數據。簡潔和清晰的層次結構使得 JSON 成爲理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提升網絡傳輸效率。
在 JS 語言中,一切都是對象。因此,任何JS支持的類型都可以通過 JSON 來表示,例如字符串、數字、對象、數組等。看看他的要求和語法格式:
- 對象表示爲鍵值對
- 數據由逗號分隔
- 花括號保存對象
- 方括號保存數組
JSON 鍵值對是用來保存 JS 對象的一種方式,和 JS 對象的寫法也大同小異,鍵/值對組合中的鍵名寫在前面並用雙引號 "" 包裹,使用冒號 : 分隔,然後緊接着值:
{"name": "QinJiang"}
{"age": "3"}
{"sex": "男"}
很多人搞不清楚 JSON 和 Js 對象的關係,甚至連誰是誰都不清楚。其實,可以這麼理解:
JSON 是 JS 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質是一個字符串。
var obj = {a: 'Hello', b: 'World'}; //這是一個對象,注意鍵名也是可以使用引號包裹的
var json = '{"a": "Hello", "b": "World"}'; //這是一個 JSON 字符串,本質是一個字符串
JSON 和 JS 對象互轉
要實現從JSON字符串轉換爲JS對象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //結果是 {a: 'Hello', b: 'World'}
要實現從JS對象轉換爲JSON字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'}); //結果是 '{"a": "Hello", "b": "World"}'
我們去代碼中測試下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON_秦疆</title>
</head>
<body>
<script type="text/javascript">
//編寫一個js的對象
var user = {
name:"秦疆",
age:3,
sex:"男"
};
//將js對象轉換成json字符串
var str = JSON.stringify(user);
console.log(str);
//將json字符串轉換爲js對象
var user2 = JSON.parse(str);
console.log(user2.age,user2.name,user2.sex);
</script>
</body>
</html>
運行:
使用Controller實現返回JSON數據
Jackson應該是目前比較好的json解析工具了,當然工具不止這一個,比如還有阿里巴巴的fastjson等等。
我們這裏使用Jackson,使用它需要導入它的jar包;
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
我們隨便編寫一個User的實體類,然後我們去編寫我們的測試Controller;這裏我們需要兩個新東西,一個是@ResponseBody,一個是ObjectMapper對象,我們看下具體的用法
package com.kuang.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kuang.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@RequestMapping("/json")
@ResponseBody
public String json1() throws JsonProcessingException {
//創建一個jackson的對象映射器,用來解析數據
ObjectMapper mapper = new ObjectMapper();
//創建一個對象
User user = new User("秦疆1號", 3, "男");
//將我們的對象解析成爲json格式
String str = mapper.writeValueAsString(user);
return str; //由於@ResponseBody註解,這裏會將str轉成json格式返回;十分方便
}
}
我們運行測試一下:
發現出現了亂碼問題,我們需要設置一下他的編碼格式爲utf-8,以及它返回的類型;通過@RequestMaping的produces屬性來實現,修改下代碼
//produces:指定響應體返回類型和編碼
@RequestMapping(value = "/json",produces = "application/json;charset=utf-8")
再次測試:
注意:使用json記得處理亂碼問題
上一種方法比較麻煩,如果項目中有許多請求則每一個都要添加,可以通過Spring配置統一指定,這樣就不用每次都去處理了!
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
我們去打印一個集合試試;
@RequestMapping("/json3")
@ResponseBody
public String json3() throws JsonProcessingException {
//創建一個jackson的對象映射器,用來解析數據
ObjectMapper mapper = new ObjectMapper();
//創建一個對象
User user1 = new User("秦疆1號", 3, "男");
User user2 = new User("秦疆2號", 3, "男");
User user3 = new User("秦疆3號", 3, "男");
User user4 = new User("秦疆4號", 3, "男");
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
//將我們的對象解析成爲json格式
String str = mapper.writeValueAsString(list);
return str; //由於@ResponseBody註解,這裏會將str轉成json格式返回;十分方便
}
運行結果 : 十分完美,沒有任何問題!
我們創建一個時間日期的對象試試,看看能不能轉換成功!
@RequestMapping("/time")
@ResponseBody
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//創建時間一個對象
Date date = new Date();
//將我們的對象解析成爲json格式
String str = mapper.writeValueAsString(date);
return str; //由於@ResponseBody註解,這裏會將str轉成json格式返回;十分方便
}
運行結果:
默認日期格式會變成一個數字,是1970年1月1日到當前日期的毫秒數!Jackson 默認是轉成timestamps形式
解決方案:取消timestamps形式 , 自定義時間格式
@RequestMapping("/time")
@ResponseBody
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//不使用時間戳的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定義日期格式對象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//指定日期格式
mapper.setDateFormat(sdf);
Date date = new Date();
String str = mapper.writeValueAsString(date);
return str; //由於@ResponseBody註解,這裏會將str轉成json格式返回;十分方便
}
結果:完美解決OK!
如果要經常使用的話,這樣是比較麻煩的,我們可以將這些代碼封裝到一個工具類中;我們去編寫下
package com.kuang.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtils {
public static String getJson(Object object) {
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
public static String getJson(Object object,String dateFormat) {
ObjectMapper mapper = new ObjectMapper();
//不使用時間差的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定義日期格式對象
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
//指定日期格式
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
我們使用工具類,代碼就更加簡潔了!
@RequestMapping("/utils")
@ResponseBody
public String json3() throws JsonProcessingException {
Date date = new Date();
String json = JsonUtils.getJson(date);
return json;
}
我們上面都是用的是 @ResponseBody 註解,它就是把後臺的對象轉換成json對象,返回到頁面 , 和它對應的當然就是@RequestBody,一般用來負責接收前臺的json數據,把json數據自動封裝到pojo中;我們之後Ajax來測試這一塊。這兩個註解一般都會在異步獲取數據中使用到;
1|2AJAX
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。
AJAX 是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。
Ajax 不是一種新的編程語言,而是一種用於創建更好更快以及交互性更強的Web應用程序的技術。
在 2005 年,Google 通過其 Google Suggest 使 AJAX 變得流行起來。
Google Suggest 使用 AJAX 創造出動態性極強的 web 界面:當您在谷歌的搜索框輸入關鍵字時,JavaScript 會把這些字符發送到服務器,然後服務器會返回一個搜索建議的列表。
就和國內百度的搜索框一樣:
傳統的網頁(即不用ajax技術的網頁),想要更新內容或者提交一個表單,都需要重新加載整個網頁。
使用ajax技術的網頁,通過在後臺服務器進行少量的數據交換,就可以實現異步局部更新。
使用Ajax,用戶可以創建接近本地桌面應用的直接、高可用、更豐富、更動態的Web用戶界面。
利用AJAX可以做:
註冊時,輸入用戶名自動檢測用戶是否已經存在。
登陸時,提示用戶名密碼錯誤
刪除數據行時,將行ID發送到後臺,後臺在數據庫中刪除,數據庫刪除成功後,在頁面DOM中將數據行也刪除。
我們可以使用前端的一個標籤來僞造一個ajax的樣子。 iframe標籤
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>kuangshen</title>
</head>
<body>
<script type="text/javascript">
window.onload = function(){
var myDate = new Date();
document.getElementById('currentTime').innerText = myDate.getTime();
};
function LoadPage(){
var targetUrl = document.getElementById('url').value;
console.log(targetUrl);
document.getElementById("iframePosition").src = targetUrl;
}
</script>
<div>
<p>請輸入要加載的地址:<span id="currentTime"></span></p>
<p>
<input id="url" type="text" value="https://www.baidu.com/"/>
<input type="button" value="提交" onclick="LoadPage()">
</p>
</div>
<div>
<h3>加載頁面位置:</h3>
<iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe>
</div>
</body>
</html>
1|3 jQuery.Ajax
1|3 jQuery.Ajax
純JS實現Ajax我們不去講解這裏,直接使用jquery提供的,更方便學習,避免重複造輪子,有興趣的同學可以去了解下本質XMLHttpRequest !
Ajax的核心是XMLHttpRequest對象(XHR)。XHR爲向服務器發送請求和解析服務器響應提供了接口。能夠以異步方式從服務器獲取新數據。
jQuery 提供多個與 AJAX 有關的方法。
通過 jQuery AJAX 方法,您能夠使用 HTTP Get 和 HTTP Post 從遠程服務器上請求文本、HTML、XML 或 JSON – 同時您能夠把這些外部數據直接載入網頁的被選元素中。
jQuery 不是生產者,而是大自然搬運工。
jQuery Ajax本質就是 XMLHttpRequest,對他進行了封裝,方便調用!我們來看下他的方法;
1. jQuery.get(...)
所有參數:
url: 待載入頁面的URL地址
data: 待發送 Key/value 參數。
success: 載入成功時回調函數。
dataType: 返回內容格式,xml, json, script, text, html
2.jQuery.post(...)
所有參數:
url: 待載入頁面的URL地址
data: 待發送 Key/value 參數
success: 載入成功時回調函數
dataType: 返回內容格式,xml, json, script, text, html
3.jQuery.getJSON(...)
所有參數:
url: 待載入頁面的URL地址
data: 待發送 Key/value 參數。
success: 載入成功時回調函數。
4.jQuery.getScript(...)
所有參數:
url: 待載入頁面的URL地址
data: 待發送 Key/value 參數。
success: 載入成功時回調函數。
5.jQuery.ajax(...)
部分參數:
url:請求地址
type:請求方式,GET、POST(1.9.0之後用method)
headers:請求頭
data:要發送的數據
contentType:即將發送信息至服務器的內容編碼類型(默認: "application/x-www-form-urlencoded; charset=UTF-8")
async:是否異步
timeout:設置請求超時時間(毫秒)
beforeSend:發送請求前執行的函數(全局)
complete:完成之後執行的回調函數(全局)
success:成功之後執行的回調函數(全局)
error:失敗之後執行的回調函數(全局)
accepts:通過請求頭髮送給服務器,告訴服務器當前客戶端課接受的數據類型
dataType:將服務器端返回的數據轉換成指定類型
"xml": 將服務器端返回的內容轉換成xml格式
"text": 將服務器端返回的內容轉換成普通文本格式
"html": 將服務器端返回的內容轉換成普通文本格式,在插入DOM中時,如果包含JavaScript標籤,則會嘗試去執行。
"script": 嘗試將返回值當作JavaScript去執行,然後再將服務器端返回的內容轉換成普通文本格式
"json": 將服務器端返回的內容轉換成相應的JavaScript對象
"jsonp": JSONP 格式使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數
我們來個簡單的測試,使用最原始的HttpServletResponse處理 , .最簡單 , 最通用
編寫一個AjaxController
package com.kuang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/ajax")
public class AjaxController {
@RequestMapping("/a1")
public void ajax1(String name , HttpServletResponse response) throws IOException {
if ("admin".equals(name)){
response.getWriter().print("true");
}else{
response.getWriter().print("false");
}
}
}
編寫index.jsp測試
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head>
<title>ajax</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.min.js"></script>
<script>
/*
jQuery.post(...)
所有參數:
url: 待載入頁面的URL地址 (必填)
data: 待發送 Key/value 參數
success: 載入成功時回調函數
data:請求返回的數據
status:請求返回的狀態
*/
function a1(){
$.post({
url:"${pageContext.request.contextPath}/ajax/a1",
data:{'name':$("#txtName").val()},
success:function (data,status) {
alert(data);
alert(status);
}
});
}
</script>
</head>
<body>
<%--onblur:失去焦點觸發事件--%>
用戶名:<input type="text" id="txtName" onblur="a1()"/>
</body>
我們可以打開瀏覽器測試一下,查看返回的彈窗結果!
SpringMVC實現
我們來獲取一個集合對象,展示到前端頁面
controller
@RequestMapping("/a2")
@ResponseBody
public List<User> ajax2(){
List<User> list = new ArrayList<User>();
list.add(new User("秦疆1號",3,"男"));
list.add(new User("秦疆2號",3,"男"));
list.add(new User("秦疆3號",3,"男"));
return list; ////由於@ResponseBody註解,將list轉成json格式返回
}
前端頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<input type="button" id="btn" value="獲取數據"/>
<table width="80%" align="center">
<tr>
<td>姓名</td>
<td>年齡</td>
<td>性別</td>
</tr>
<tbody id="content">
</tbody>
</table>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.min.js"></script>
<script>
$(function () {
$("#btn").click(function () {
$.post("${pageContext.request.contextPath}/ajax/a2",function (data) {
console.log(data)
var html="";
for (var i = 0; i <data.length ; i++) {
html+= "<tr>" +
"<td>" + data[i].name + "</td>" +
"<td>" + data[i].age + "</td>" +
"<td>" + data[i].sex + "</td>" +
"</tr>"
}
$("#content").html(html);
});
})
})
</script>
</body>
</html>
我們點擊按鈕,成功加載出來我們Controller返回的數據;
成功實現了數據回顯!可以體會一下Ajax的好處!
註冊提示
我們再測試一個小Demo,思考一下我們平時註冊時候,輸入框後面的實時提示怎麼做到的;如何優化
我們寫一個Controller
@RequestMapping("/a3")
@ResponseBody
public String ajax3(String name,String pwd){
String msg = "";
//模擬數據庫中存在數據
if (name!=null){
if ("admin".equals(name)){
msg = "OK";
}else {
msg = "用戶名輸入錯誤";
}
}
if (pwd!=null){
if ("123456".equals(pwd)){
msg = "OK";
}else {
msg = "密碼輸入有誤";
}
}
return msg; //由於@ResponseBody註解,將list轉成json格式返回
}
編寫前端頁面,進行異步處理
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>ajax</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.1.min.js"></script>
<script>
function a1(){
$.post({
url:"${pageContext.request.contextPath}/ajax/a3",
data:{'name':$("#name").val()},
success:function (data) {
if (data.toString()=='OK'){
//學習鏈接:https://www.w3school.com.cn/jquery/css_css.asp
$("#userInfo").css("color","green");
}else {
$("#userInfo").css("color","red");
}
$("#userInfo").html(data);
}
});
}
function a2(){
$.post({
url:"${pageContext.request.contextPath}/ajax/a3",
data:{'pwd':$("#pwd").val()},
success:function (data) {
if (data.toString()=='OK'){
$("#pwdInfo").css("color","green");
}else {
$("#pwdInfo").css("color","red");
}
$("#pwdInfo").html(data);
}
});
}
</script>
</head>
<body>
<p>
用戶名:<input type="text" id="name" onblur="a1()"/>
<span id="userInfo"></span>
</p>
<p>
密碼:<input type="text" id="pwd" onblur="a2()"/>
<span id="pwdInfo"></span>
</p>
</body>
</html>
測試一下效果,動態請求響應,局部刷新,就是如此!