ajax
Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
响应只返回页面需要的部分,而不是整个页面的内容;
通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面
XMLHttpRequest:js中的对象,也是用来向服务器发送请求;
功能:在页面发送请求时,页面不会跳转;
XMLHTTPRequest对象基本使用
- 创建xhr对象;
var xhr=new XMLHttpRequest();
- 发送请求
xhr.open("get|post",请求地址,true|false); //发请求前准备
xhr.send(); //真正发送请求
- 接受响应
xhr.responseText;
表单提交之后响应返回整个页面;
xhr需要的响应通常不是一个完成整的html,而是一个html的部分内容;
- open的第三个参数
true 默认值 异步请求:send方法不会阻塞,发完请求之后立刻
结束,执行下面代码,不会等到响应返回才执行;
false 同步请求:响应没有返回之前,页面代码、视频都会暂停,
直到响应返回前,send方法一直处于阻塞状态;
异步请求下要用onload事件,响应返回的时候触发onload函数,所以不管响应多长时间返回;
- onload
xhr.onload=function() {
document.getElementById("result").innerText=xhr.responseText;
}
- onreadystatechange
发送请求时会触发,响应返回时会触发,响应完全返回时也会触发
xhr.onreadystatechange=function() {
xhr.readyState; //状态字,表示请求和响应的状态
//xhr 创建时 0
//xhr.send 0->1
//xhr.responseText 1->2
//响应完全返回时 3—>4
if(xhr.readyState==4){
//表示响应完全返回
}
}
- post请求
- get请求只有请求头和请求行
- post 请求行、请求头、请求体
var xhr=new XMLHttpRequest();
xhr.onload=function () {};
//发请求
xhr.open("post",url,true);
//如果没有请求体则send没参数,否则是请求体的内容
xhr.setRequestHeader("content-type","application/www-form-urlencoded");//告诉服务器,请求体格式是表单格式
xhr.send(参数=请求体的内容); //参数名=参数值&参数名=参数值
function sendRequest() {
var xhr = new XMLHttpRequest(); //创建xhr对象
xhr.onload=function () {
document.getElementById("result").innerText=xhr.responseText;
};
xhr.open("post","/commentServlet",true);
xhr.setRequestHeader("content-type","application/www-form-urlencoded");
xhr.send("comment="+document.getElementById("c").value); //将评论内容发送给servlet
console.log("send之后执行的方法");
}
- 简化xhr对象的使用
//url 请求地址
//param 请求参数
//callback 回调函数
function c (x) {
document.getElementById("result").innerText = x.responseText;
}
post("/commentServlet", "comment=" + document.getElementById("c").value, c)
funciton post(url, param, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() { // 当 onload 事件发生时,才会执行 c 函数
c(xhr); // 调用 c 函数
};
xhr.open("post", url, true);
xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xhr.send(param);
}
下面的写法不正确:
funciton post(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = c(xhr); // 立刻执行c的内容,将结果赋值给了 onload
xhr.open("post", url, true);
xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xhr.send("comment=" + document.getElementById("c").value);
}
- 响应格式
主流的响应格式有两种:
- xml(可扩展标记语言)
<response>
<time>2019-1-19 13:30:34</time>
<author>张三</author>
<content>还不错</content>
<score>11</score>
</response>
获取xml内容
var xml=xhr.responseXML;
xml.getElementsByTagName("time")[0].innerText;
- json(javascript object 对象 notation 标记)
{
"time":"2019-1-19 13:30:34",
"author":"张三",
"content":"还不错",
"score":11
}
var obj=...
obj.time
json中除了解析方便外,还支持更多类型 字符串、数字、布尔值、数组、对象等;
-
Ajax的定义
a——>asynchronous 可通过xhr对象发送异步请求
j——>javascript
a——>and
x——>xml 响应格式 -
XMLHttpRequest 完整api
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest -
json
- 把java对象转换成json字符串
转换json的第三方api、gson(谷歌)、jsckson(spring)、fastjson(阿里); - json字符串如何转为java对象
- js对象和json字符串相互转换
将响应中的json字符串转换为javaScript中的对象数组
var js对象=JSON.parse(json);
逆过程
var json字符串=JSON.stringify(js对象);
jackson
重要的类:
ObjectMapper om=new ObjectMapper();
String json=om.writeValueAsString(java对象);
- 如果要对日期进行控制,在日期属性上加上注解
@JsonFormat(patter="yyyy-MM-dd HH-mm-ss" timezone="GMT+08"")
- 忽略转换某个对象属性加上注解
@JsonIgnore
- 如果要转换后改变属性名:
@JsonProperty("新属性名")
java中的map,domain==>都会转为json的对象{}
java中的list,set,数组==>都会转为json中的数组[]
package domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Date;
public class Student {
private int id;
private String password;
private String name;
private String sex;
private Date birthday;
public Student(int id, String password, String name, String sex, Date birthday) {
this.id = id;
this.password = password;
this.name = name;
this.sex = sex;
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+08")
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@JsonIgnore
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", password='" + password + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
'}';
}
}
package day35;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import domain.Student;
import org.junit.Test;
import org.omg.CORBA.PUBLIC_MEMBER;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
public class JsonTest {
// @Test
// public void test1() throws JsonProcessingException {
// Student student = new Student();
// student.setId(1);
// student.setName("张三");
// student.setBirthday(new Date());
// student.setPassword("12345");
// student.setSex("男");
//
// ObjectMapper om = new ObjectMapper();
// String s = om.writeValueAsString(student);
// System.out.println(s);
// //{"id":1,"name":"张三","sex":"男","birthday":"2019-01-19 15:56:41"}
//
// }
@Test
public void test2() throws JsonProcessingException {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(list);
System.out.println(s);
//[1,2,3,4,5]
}
@Test
public void test3() throws JsonProcessingException {
HashMap<String, String> map = new HashMap<>();
map.put("beijing","北京");
map.put("shanghai","上海");
map.put("shenzhen","深圳");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(map);
System.out.println(s);
//{"shanghai":"上海","shenzhen":"深圳","beijing":"北京"}
}
@Test
public void test4() throws JsonProcessingException {
Student s1 = new Student(1, "123", "张三", "男", new Date());
Student s2 = new Student(2, "123", "李四", "男", new Date());
Student s3 = new Student(3, "123", "王五", "男", new Date());
Student s4 = new Student(4, "123", "赵六", "男", new Date());
Student s5 = new Student(5, "123", "周七", "男", new Date());
ArrayList<Student> studentArray = new ArrayList<>();
studentArray.add(s1);
studentArray.add(s2);
studentArray.add(s3);
studentArray.add(s4);
studentArray.add(s5);
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(studentArray);
System.out.println(s);
/*[{"id":1,"name":"张三","sex":"男","birthday":"2019-01-19 16:04:08"},
{"id":2,"name":"李四","sex":"男","birthday":"2019-01-19 16:04:08"},
{"id":3,"name":"王五","sex":"男","birthday":"2019-01-19 16:04:08"},
{"id":4,"name":"赵六","sex":"男","birthday":"2019-01-19 16:04:08"},
{"id":5,"name":"周七","sex":"男","birthday":"2019-01-19 16:04:08"}]
*/
}
}
还原操作
ObjectMapper om=new ObjectMapper();
类型 java对象=om.readValue(json字符串,类.class);
servlet中结合jackson
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
Student s1 = new Student(1, "123", "张三", "男", new Date());
Student s2 = new Student(2, "123", "李四", "男", new Date());
Student s3 = new Student(3, "123", "王五", "男", new Date());
Student s4 = new Student(4, "123", "赵六", "男", new Date());
Student s5 = new Student(5, "123", "周七", "男", new Date());
ArrayList<Student> studentArray = new ArrayList<>();
studentArray.add(s1);
studentArray.add(s2);
studentArray.add(s3);
studentArray.add(s4);
studentArray.add(s5);
ObjectMapper om = new ObjectMapper();
//方法一: String s = om.writeValueAsString(studentArray);
// resp.getWriter().print(s);
//方法二:
om.writeValue(resp.getWriter(),studentArray);
}
ajax应用
视频网站的评论
案例:评论正在播放的视频,并且请求只发送评论内容,从而使视频页面不跳转也能显示评论。响应只返回评论框里的内容并显示在页面,而不是返回整个页面,或跳转页面,这样可以使页面不刷新,这是ajax技术最简单最直接的体现;
<html>
<head>
<title>Title</title>
<script>
function sendRequest() {
var xhr = new XMLHttpRequest(); //1. 创建xhr对象
var v=document.getElementById("c").value; //获取文本框里的内容
xhr.open("get","/commentServlet?comment="+v,false);
xhr.send(); // 2.将评论内容发送给servlet
//5. 返回的响应触发下面函数,获取相应中的内容,并显示到指定标签
console.log("send方法之后执行");
/ xhr.onload=function (){
// document.getElementById("result").innerText=xhr.responseText;
// };
xhr.onreadystatechange=function () {
if(xhr.readyState==4){
document.getElementById("result").innerText=xhr.responseText;
}
};
//document.getElementById("result").innerText=xhr.responseText;
//将从servlet获取到的响应评论给内容显示到指定id的span标签里
console.log(xhr.responseText);
}
</script>
</head>
<body>
<video src="video/1.mp4" controls width="500"></video>
<hr>
请输入评论:<input type="text" name="conment" id="c">
<input type="submit" value="提交评论">
<input type="button" value="用xhr发送请求" onclick="sendRequest()">
</hr>
<p><span id="result"></span></p>
</body>
</html>
@WebServlet(urlPatterns = "/commentServlet")
public class servlet.Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String comment = req.getParameter("comment"); 3. //接收到jsp发送过来的comment内容
//模拟响应延迟
Thread.sleep(4000);
resp.setCharacterEncoding("utf-8");
resp.getWriter().print(comment); 4. //响应显示到页面
}
}
省市县联动
region.jsp
<body>
省份<select id="province" onchange="findCity()"></select>
城市<select id="city" onchange="findCounty()"></select>
县区<select id="county"></select>
<script>
function findCounty() {
var parentId = document.getElementById("city").value;
var xhr = new XMLHttpRequest();
xhr.onload=function () {
var jsonS = xhr.responseText;
var list = JSON.parse(jsonS);
console.log(jsonS);
//清除下拉列表的内容
document.getElementById("county").innerHTML="";
for (var i=0;i<list.length;i++){
var region=list[i];
//生成option标签内容
var option = document.createElement("option");
option.value=region.id;
option.innerText=region.name;
//把option标签添加给父标签select id="province"
document.getElementById("county").appendChild(option);
}
};
//页面刚开始刷新的时候省份上要出现第一个省
xhr.open("get","/region?parentId="+parentId,true);
xhr.send();
}
function findCity() {
var parentId = document.getElementById("province").value;
var xhr = new XMLHttpRequest();
xhr.onload=function () {
var jsonS = xhr.responseText;
var list = JSON.parse(jsonS);
console.log(jsonS);
//清除下拉列表的内容
document.getElementById("city").innerHTML="";
for (var i=0;i<list.length;i++){
var region=list[i];
//生成option标签内容
var option = document.createElement("option");
option.value=region.id;
option.innerText=region.name;
//把option标签添加给父标签select id="province"
document.getElementById("city").appendChild(option);
}
//联动县
findCounty();
};
//页面刚开始刷新的时候省份上要出现第一个省
xhr.open("get","/region?parentId="+parentId,true);
xhr.send();
}
function findProvince() {
var xhr = new XMLHttpRequest();
xhr.onload=function () {
var jsonS = xhr.responseText;
var list = JSON.parse(jsonS);
for (var i=0;i<list.length;i++){
var region=list[i];
//生成option标签内容
var option = document.createElement("option");
option.value=region.id;
option.innerText=region.name;
//把option标签添加给父标签select id="province"
document.getElementById("province").appendChild(option);
}
//联动市
findCity();
};
//页面刚开始刷新的时候省份上要出现第一个省
xhr.open("get","/region?parentId=1",true);
xhr.send();
}
findProvince();
</script>
</body>
RegionServlet.class
@WebServlet(urlPatterns = "/region")
public class RegionServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Double parentId = Double.valueOf(req.getParameter("parentId"));
RegionFindDao rd = new RegionFindDao();
//按parentId查找信息
List<Region> list = rd.findByParentId(parentId);
resp.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
ObjectMapper om = new ObjectMapper();
//将json响应给页面
om.writeValue(resp.getWriter(), list);
}
自动完成模糊查询
<html>
<head>
<title>Title</title>
<style>
li {
list-style: none;
}
li:hover {
background: blue;
color:white;
}
ul {
display: none;
border: 1px solid rgb(238,238,238);
margin: 0;
padding: 0;
width: 160px;
box-shadow: 0px 1px 6px rgba(0,0,0,0.2);
border-radius: 4px ;
font-size: 13px;
}
</style>
</head>
<body>
<input type="text" id="like" onkeyup="likefind()" onblur="hideResult()" onclick="toggleResult()">
<ul id="result">
</ul>
<script>
//让列表在显示和隐藏之间切换,鼠标焦点触发
function toggleResult() {
if(document.getElementById("result").style.display == "none") {
document.getElementById("result").style.display = "block";
} else {
document.getElementById("result").style.display = "none";
}
}
//让焦点离开文本框时,列表隐藏延迟,先让选中li填入文本框,再隐藏列表
function hideResult() {
setTimeout(function () {
document.getElementById("result").style.display="none";
},300);
}
function likefind() {
var xhr = new XMLHttpRequest();
xhr.onload=function () {
var responseText = xhr.responseText;
var json=JSON.parse(responseText);
document.getElementById("result").innerHTML="";
//js6 中存在let和var关键字功能一样:声明变量;
// 但是可以定义块作用域变量而不像var定义全局变量
for (let i=0;i<json.length;i++){
var region=json[i];
let li = document.createElement("li");
li.innerHTML=region.name;
//使选中的列表内容填入文本框
//如果不使用let 则这个函数里li永远取的是最后一个列表元素的值
li.onclick=function () {
document.getElementById("like").value=li.innerText;
document.getElementById("result").style.display="none";
};
document.getElementById("result").appendChild(li);
}
};
var name = document.getElementById("like").value;
xhr.open("get","/likefind?likeString="+name,true);
xhr.send();
}
</script>
</body>
</html>