是什么
同步与异步
- 同步:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待卡死状态
- 异步:客户端发送请求到服务器端,无论服务器是否返回响应,客户端都可以随意做其他事情,不会被卡死
简介
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
- 无需重新加载整个网页,更新部分网页。
- 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
起源
在 2005 年,Google 通过其 Google Suggest 的自动搜索(类似在百度搜索框输入时) 使 AJAX 变得流行起来。
当在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。
就和国内百度的搜索框一样!
运行原理
页面发起请求,会将请求发送给浏览器内核中的Ajax引擎
Ajax引擎会提交请求到 服务器端
在这段时间里,客户端可以任意进行任意操作,直到服务器端将数据返回 给Ajax引擎后,会触发你设置的事件,从而执行自定义的js逻辑代码完成某种 页面功能。
利用AJAX可以做
注册时,输入用户名自动检测用户是否已经存在。
登陆时,提示用户名密码错误
删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。
....等等
Json
- json是一种与语言无关的数据交换的格式,常用于用:
- 使用ajax进行前后台数据交换
- 移动端与服务端的数据交换
格式
- 对象格式:
{"key1":obj,"key2":obj,"key3":obj...}
- 数组/集合格式:
[obj,obj,obj...]
举例
例1:user对象 用json数据格式表示
{"username":"zhangsan","age":28,"password":"123","addr":"北京"}
例2:List
[{"pid":"10","pname":"小米4C"},{},{}]
- 注意:
- 对象格式和数组格式可以互相嵌套
- json的key是字符串 json的value是Object
解析
json是js的原生内容,也就意味着js可以直接取出json对象中的数据
Json的转换插件
将java的对象或集合转成json形式字符串
常用的json转换工具有如下几种:
- jackson
- jsonlib
- Gson:google
- fastjson:阿里巴巴
为什么
使用 Ajax 优点:
- 异步请求,不妨碍用户浏览页面或者其他操作。
- 传统的网页,更新内容或者提交一个表单,都需要重新加载整个网页。
- 使用ajax,可以在提交数据的同时,进行其他操作。
- 局部刷新,无需重新刷新页面。
- 界面与应用分离。有利于分工合作、减少非技术人员对页面的修改造成的WEB应用程序错误、提高效率、也更加适用于现在的发布系统。
- 基于标准被广泛支持。
- 前端和后端负载平衡。最大程度的减少冗余请求和响应对服务器造成的负担,提升站点性能。
怎么做
1.搭建环境(ssm阶段)
(1)创建 maven 工程,并导入 web 支持
(2)pom.xml 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.quan</groupId>
<artifactId>Project-Ajax</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Project-Ajax Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- springmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- json转换 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<!-- 简化实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<finalName>Project-Ajax</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
(3)springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
<context:component-scan base-package="com.quan.controller"/>
<!--可以正常访问静态文件,防止找不到静态文件报404-->
<mvc:default-servlet-handler />
<!-- 注解驱动,以使得访问路径与方法的匹配可以通过注解配置 @RequestMapping -->
<mvc:annotation-driven />
<!-- 乱码处理 -->
<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>
<!-- 视图解析器 用于检测到 jsp -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
(4)web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--乱码处理 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
</web-app>
(5)User.java
此类只是为了测试,可根据自己实际情况改变
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
(6)AjaxController.java
//此注解会将 类中方法的返回值 转换成json返回到前端
@RestController
public class AjaxController {
@RequestMapping("/test")
public User test(){
......
return user;
}
}
2.快速测试
(1)例1:伪造 Ajax 效果(可跳过)
利用 iframe ,创造出 异步显示的效果
创建 test1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</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>
测试
localhost:8080/test1.jsp
(2)Ajax使用形式
Ajax使用形式
- $.get(url, [data], [callback], [type])
- $.post(url, [data], [callback], [type])
- 其中:
- url:代表请求的服务器端地址
- data:代表请求服务器端的数据(可以是key=value形式也可以是json格式)
- callback:表示服务器端成功响应所触发的函数(只有正常成功返回才执行)
- type:表示服务器端返回的数据类型(jquery会根据指定的类型自动类型转换)
- 常用的返回类型:text、json、html等
- $.ajax( { option1:value1,option2:value2... } );
- 常用的option有如下:
- async:是否异步,默认是true代表异步
- data:发送到服务器的参数,建议使用json格式
- dataType:服务器端返回的数据类型,常用text和json
- success:成功响应执行的函数,对应的类型是function类型
- type:请求方式,POST/GET
- url:请求服务器端地址
万能示例
<script>
$.ajax({
// 向后端 controller 发送的请求
url:"${pageContext.request.ctoontextPath}/a3",
//请求的方式一般 POST 或者 GET
type:"POST";
//json格式,控制器 返回的数据为json格式的。
dataType: "json",
// 向后端发送的数据 一般以 json 形式
data:{'name':$("#name").val()},
// 请求成功后,前端调用此函数
// data:后端返回给前端的数据 status:请求的状态 若后端成功返回数据,即为success
success:function (data,status){
//因为使用@Response注解,后端传回来的数据是json,需toString转换
// 若date中有user数据等其他数据 可以用date.username date.pwd 等来拿
if (data.toString()=='OK'){
//根据后端校验结果,给前端加样
$("#userInfo").css("color","green");
}else {
$("#userInfo").css("color","red")
}
//把后端返回数据放到前端标签中
$("#userInfo").html(data);
}
});
</script>
(3)例2:用户名校验
AjaxContraller.java 加入
@RequestMapping("/a1")
public void ajax1(String name , HttpServletResponse response) throws IOException {
if ("admin".equals(name)){
//把数据写到前端 由ajax接收
response.getWriter().print("true");
}else{
//把数据写到前端 由ajax接收
response.getWriter().print("false");
}
}
test2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户名校验</title>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
function a1(){
$.post({
//向后端发送的请求地址
url:"${pageContext.request.contextPath}/a1",
//像后端发送的数据,是json形式
data:{'name':$("#txtName").val()},
//后端成功返回数据后调用
success:function (data,status) {
// date 是 后端返回的数据
// status 是 后台相应的状态
alert(data);
alert(status);
}
});
}
</script>
</head>
<body>
<%--onblur:失去焦点触发事件--%>
用户名:<input type="text" id="txtName" onblur="a1()"/>
</body>
</html>
测试
localhost:8080/test2.jsp
(4)例3:集合展示
AjaxContraller.java 加入
@RequestMapping("/a2")
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,"男"));
//由于@RestController注解,将list转成json格式返回
return list;
}
test3.html
<%@ 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.1.1.min.js"></script>
<script>
$(function () {
$("#btn").click(function () {
$.post("${pageContext.request.contextPath}/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>
测试
localhost:8080/test3.jsp
(5)例4:表单校验
AjaxContraller.java 加入
@RequestMapping("/a3")
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; //由于@RestController注解,将msg转成json格式返回
}
test4.html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>表单校验</title>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
//鼠标离开用户名时
function a1(){
$.post({
url:"${pageContext.request.ctoontextPath}/a3",
data:{'name':$("#name").val()},
success:function (data) {
//因为使用@Response注解,后端传回来的数据是json,需toString转换
if (data.toString()=='OK'){
//根据后端校验结果,给前端加样式
$("#userInfo").css("color","green");
}else {
$("#userInfo").css("color","red");
}
//把后端返回数据放到前端标签中
$("#userInfo").html(data);
}
});
}
//鼠标离开密码时
function a2(){
$.post({
url:"${pageContext.request.contextPath}/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>
测试
localhost:8080/test4.jsp
(6)例5:baidu搜索
test5.html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSONP百度搜索</title>
<style>
#q{
width: 500px;
height: 30px;
border:1px solid #ddd;
line-height: 30px;
display: block;
margin: 0 auto;
padding: 0 10px;
font-size: 14px;
}
#ul{
width: 520px;
list-style: none;
margin: 0 auto;
padding: 0;
border:1px solid #ddd;
margin-top: -1px;
display: none;
}
#ul li{
line-height: 30px;
padding: 0 10px;
}
#ul li:hover{
background-color: #f60;
color: #fff;
}
</style>
<script>
// 1.步骤一
window.onload = function(){
// 获取输入框和ul
var Q = document.getElementById('q');
var Ul = document.getElementById('ul');
// 事件鼠标抬起时候
Q.onkeyup = function(){
// 如果输入框不等于空
if (this.value != '') {
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆JSONPz重点☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
// 创建标签
var script = document.createElement('script');
//给定要跨域的地址 赋值给src
//这里是要请求的跨域的地址 我写的是百度搜索的跨域地址
script.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+this.value+'&cb=demo';
// 将组合好的带src的script标签追加到body里
document.body.appendChild(script);
}
}
}
// 2.步骤二
// 定义demo函数 (分析接口、数据)
function demo(data){
var Ul = document.getElementById('ul');
var html = '';
// 如果搜索数据存在 把内容添加进去
if (data.s.length) {
// 隐藏掉的ul显示出来
Ul.style.display = 'block';
// 搜索到的数据循环追加到li里
for(var i = 0;i<data.s.length;i++){
html += '<li>'+data.s[i]+'</li>';
}
// 循环的li写入ul
Ul.innerHTML = html;
}
}
</script>
</head>
<body>
<input type="text" id="q" />
<ul id="ul">
</ul>
</body>
</html>