AJAX
一、介绍
AJAX : Asychronous Javascript And XML,指异步JavaScript及XML。是指一种创建交互式网页应用的网页开发技术。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。
二、使用AJAX
1. JS原生AJAX[了解]
通过查询W3C文档使用JS原生AJAX。
一般可分为五步:
1. 创建AJAX对象
2. 绑定监听事件---监听服务器是否响应数据了
3. 绑定请求的服务器地址
4. 发送请求
5. 服务器响应成功执行的函数
//1.创建对象
xmlhttp = new XMLHttpRequest();
//2.绑定监听事件---监听服务器是否响应
xmlhttp.onreadystatechange = function() {
//5.服务器响应成功执行的函数
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText);
}
}
//3.绑定请求路径
xmlhttp.open("GET", "${pageContext.request.contextPath}/demo", true);
//4.发送请求
xmlhttp.send();
-
服务器状态码(readyState、status):
readyState : 0 : XMLHttpRequest对象没有完成初始化。即:刚刚创建。 1 : XMLHttpRequest对象开始发送请求.调用了open方法,但还没有调用send方法,请求还未发出。 2 : XMLHttpRequest对象的请求发送完成。但服务器还未响应 3 : XMLHttpRequest对象开始读取响应,还没有结束收到了所有的响应消息头,但正文还没有完全收到 4 : XMLHttpRequest对象读取响应结束 status : 200 : OK .服务器接收到请求并已响应。 400 : 无法找到请求的资源。 403 : 没有访问权限 404 : 访问的资源不存在 500 : 服务器内部错误
2. JQurey的AJAX【重点】
2.1 get方式
<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script type = "text/javascript">
$.get(
url, //请求的地址路径
params, //发送到服务器的参数
function(){}, //回调函数,服务器响应成功后执行的函数
type //一般为json和text,默认text。服务器返回的数据格式
);
</script>
例如:
$.get(
"${pageContext.request.contextPath}/demo2",//url,请求访问的路径
{name:"zhangsan",age:20},//要传递到服务器的参数
function(data) { //响应成功后执行的函数,data是服务器返回的数据
alert(data);
},
"text"//服务器返回的数据格式
);
2.2 post方式
与get方式一样,只需要把$.get()改为$.post()即可
<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script type = "text/javascript">
$.post(
url, //请求的地址路径
params, //发送到服务器的参数
function(){}, //回调函数,服务器响应成功后执行的函数
type //一般为json和text,默认text。服务器返回的数据格式
);
</script>
例如:
$.post(
"${pageContext.request.contextPath}/demo2",//url,请求访问的路径
{"name":"yom","age":10},//要传递到服务器的参数
function(data) { //响应成功后执行的函数,data是服务器返回的数据
alert(data);
},
"text"//服务器返回的数据格式
);
2.3 ajax方式
get与post是ajax方式的简化,用get和post方式可以节省不少代码。
但ajax的功能更多,他可以指定是否同步或异步,而get和post方式就不能改变,只能异步请求。
- JQuery的包的路径一定要导入并且要正确否则就会失败,js文件放在web-content下新建的js文件夹中,路径前不要加'/'
- ajax方式和get与post的异步请求格式有个小区别,就是ajax的格式是json格式,前后都有大括号,中间为key:value的键值对形式。两个键值对之间以逗号隔开。
<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<input type="button" value="ajax(ajax方式异步请求)" onclick="fn()" />
<script type="text/javascript">
function fn() {
$.ajax({
type : "POST",//请求方式
async : true,//是否异步,true为异步,false为同步
url : "${pageContext.request.contextPath}/demo3",//请求的服务器路径
data : "name=小明",//请求传递的参数
success : function(data) {//响应成功后执行的函数,这里的data是指服务器传递回来的数据
alert(data.name);
alert(data.age);
},
dataType : "json" //服务器响应的数据格式
});
}
</script>
三、案例
1. 案例一:异步校验用户名是否已经存在
思路:
1. 准备用户数据库,与注册页面。
2. 搭建开发环境,数据库相关的jar包:驱动,c3p0,配置文件,dbutils。
3. 新建工程,创建包结构:web-service-dao
4. 具体实现。servlet---service---dao数据库查询并返回结果.
1. 在jsp页面获取到用户输入的用户名
2. 用异步请求的技术AJAX将用户输入的用户名提交到服务器。
3. dao层查询,返回一个User对象。
4. 新建ResultBean的bean类,servlet判断User对象是否为空设置ResultBean的值。
这个对象存储了返回的消息。将其封装成json响应回客户端。
5. 客户端解析json数据。
代码实现:
1. 准备数据库与注册页面
2. 准备开发需要的jar包与配置文件,工具类JDBCUtils
public class JDBCUtils {
private static DataSource ds = new ComboPooledDataSource();// c3p0默认配置获取连接池
// 可以认为是与线程绑定的获取连接的Map集合
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
// 获取连接池的方法
public static DataSource getDataSource() {
return ds;
}
// 通过连接池获取连接的方法
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
// 从ThreadLocal中获取与线程绑定的连接Connection
public static Connection getConnectionTL() throws SQLException {
Connection connection = threadLocal.get();
if (connection == null) {
threadLocal.set(getConnection());
connection = threadLocal.get();
}
return connection;
}
// 开启事务的方法
public static void startTransaction() throws SQLException {
Connection connection = getConnectionTL();
connection.setAutoCommit(false);
}
// 提交事务并释放资源的方法
public static void commitAndRelease() throws SQLException {
Connection connection = getConnectionTL();
connection.rollback();
if (connection != null) {
connection.close();
// 这里为什么connection关闭后还要设置为null呢?
// 因为在关闭close的时候可能出现了异常导致关闭失败,这个时候connection就处于一种未知的状态,这种情况下垃圾回收器gc就不能将他回收
// 因此在后面将它设为null,这样即使出现异常也能被垃圾回收器关闭
connection = null;
}
threadLocal.remove();
}
// 回滚事务并释放资源的方法
public static void rollbackAndRelease() throws SQLException {
Connection connection = getConnectionTL();
if (connection != null) {
connection.close();
connection = null;
}
threadLocal.remove();
}
}
3. 新建工程,创建包结构:web-service-dao
4. 后台功能的具体实现
1. 在jsp页面获取用户输入框,绑定失去焦点事件,用异步请求将获取到的用户名发送到服务器端。
使用jquery的ajax前一定要导入jquery。
<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
$(function(){ //页面加载完成时间
//获取输入用户名的输入框对象并为其绑定onblur事件
$("#username").blur(function() {
//获取到用户输入的用户名
var $username = $("#username").val();
//使用AJAX技术将获取到的用户名传到服务器后台进行查询
$.post(
"${pageContext.request.contextPath}/checkUsername",//url,发送请求到服务器的地址
"username="+$username,//请求的参数
function(data) {//服务器响应成功后执行的函数
//data为服务器响应回的json数据,将其解析在用户名输入框的下方,获取到该div标签对象
$("#checkUsername").html(data.message);
if(data.isExist) {
$("#checkUsername").css("color","red");
}else {
$("#checkUsername").css("color","green");
}
},
"json"//服务器响应的数据格式
);
});
});
</script>
2. 服务器端servlet接收异步请求发送过来的参数(用户输入的用户名),将它传到service层处理,返回查询到的用户User。
在servlet层对User进行判断,根据User的是否为null设置bean类ResultBean中的isExsit与message值。将bean类写回客户端。
// 编码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 获取异步请求AJAX传递的参数username
String username = request.getParameter("username");
// 调用业务层
try {
CheckNameService service = new CheckNameService();
User user = service.checkUsername(username);
// 在这里使用一个存储用户是否存在boolean和传回客户端信息的bean内来封装数据
ResultBean resultBean = new ResultBean();
// 判断用户名为username的用户是否存在,给resultBean赋值
if (user == null) {
resultBean.setExist(false);// 说明用户名不存在
resultBean.setMessage("用户名不存在,可以使用");
} else {
resultBean.setExist(true);// 说明用户存在
resultBean.setMessage("用户名已存在!");
}
// 将封装后的resultBean转化成json格式的字符串,这里要使用到Gson工具包
Gson gson = new Gson();
String json = gson.toJson(resultBean);
System.out.println(json);
// 将封装好的json字符串写回客户端解析
response.getWriter().write(json);
} catch (SQLException e) {
e.printStackTrace();
}
3. 创建servlet层用到的两个bean类:User与ResultBean
4. service层调用dao层。
CheckNameDAO dao = new CheckNameDAO();
return dao.checkUsername(username);
5. dao层连接数据库查询是否存在该用户名的用户。
QueryRunner runner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from user where name=?";
return runner.query(sql, new BeanHandler<User>(User.class),username);
6. dao层返回值为User,servlet层判断是否存在设置ResultBean的值,客户端接收resultBean的json值进行解析,添加到对应要显示的位置即可。
这在前面的代码中也已经显示了。
5. 效果图
2. 案例二: 站内异步搜索
需求:模仿淘宝搜索宝贝,每次输入一个关键字时,异步请求服务器,去数据库进行模糊查询,将查询到的商品名返回到客户端显示。
分析:
1. 在要添加该功能的div标签后添加一个div标签,完成布局。
2. 获取到搜索框的对象,对其进行mouseup监听,每次触发都发起异步请求,异步请求将搜索框内的数据传送到服务器查询。
3. 服务器servlet接收到异步请求ajax发送过来的参数,将其传递到service--dao进行模糊查询,返回查询到的商品集合,
将其封装成json字符串响应回客户端。
4. 客户端接收到响应的数据,解析json并将其添加到添加的div标签内。
2.1 jsp布局
在用户的search搜索输入框的div中添加一个div,为搜索联想框.
css属性:
1. display为none,不可见,当输入关键字keyup监听时将其设置为block可见。
2. position:absolute。设置该div是独立的,防止对父标签div的布局影响。
3. z-index:999.设置z轴上的优先级,数字越大布局越在上方。
<div id="returnKey" style="display:none;width: 196px;height: 80px;position:
absolute;background-color: white;z-index: 999" ></div>
获取到搜索输入框元素,为搜索输入框添加键盘监听事件:
通过监听事件,用户每次输入关键字,松开键时触发searchKeyWords()方法。
该方法获取到用户输入的关键字数据,利用异步请求ajax技术将其发送到服务器查询数据库。
function中的data为服务器返回的商品List集合,遍历集合,在添加的搜索联想框div中添加div标签,将商品的名字一一添加进去。
//用户输入搜索关键字产生的联想
function searchKeyWords() {
$("#returnKey").css("display","block");
//获取搜索框的输入的关键字
var $keyWords = $("#searchWords").val();
//使用异步请求将获取到的关键字发送到服务器进行查询
if($keyWords!="") {
$.post(
"${pageContext.request.contextPath}/searchWords",//url
"keyWords="+$keyWords,//请求发送的参数
function(data) {//服务器响应成功后执行的函数
//将服务器响应回的数据解析写到id为returnKey的div中
var resultString = "";
for (var i = 0; i < data.length; i++) {
resultString += "<div onclick='insertContent(this)' onmouseover='changeColor(this)' onmouseout='backColor(this)' style='margin-left: 5px;margin-top: 3px'>"+data[i].pname+"</div>";
}
$("#returnKey").html(resultString);
},
"json"//服务器返回的数据格式
);
}
}
</script>
2.2 服务器Servlet处理异步请求发送过来的关键字
servlet将请求的参数keyWords传至service层/dao层在数据库中模糊查询,将查询到的商品数据,转换为json字符串写回客户端。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//编码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//获取ajax传递过来的参数keywords
String keyWords = request.getParameter("keyWords");
try {
//调用业务逻辑层,将获取到的keywords传递到service---dao
SearchKeyWordsService service = new SearchKeyWordsService();
List<Product> list = service.searchKeyWords(keyWords);
//将返回的list商品数据转化为json格式的字符串传回客户端
Gson gson = new Gson();
String json = gson.toJson(list);
//写回客户端
response.getWriter().write(json);
} catch (Exception e) {
e.printStackTrace();
}
2.3 service层
SearchKeyWordsDAO dao = new SearchKeyWordsDAO();
return dao.searchKeyWords(keyWords);
2.4 dao层
sql语句limit限制查询的条数,这样就能控制显示的联想数量
QueryRunner runner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from products where pname like ? limit 3";
return runner.query(sql, new BeanListHandler<Product>(Product.class), "%"+keyWords.trim()+"%");
2.5 jsp界面优化
- 用户选择关键字后,将该关键字添加到输入框中
- 关键字添加到输入框后,联想框的display属性再次设置为none
- 用户将鼠标移至联想条目时,变色,移出时,恢复
<script type="text/javascript">
//鼠标移到条目上方时给搜索条目增加背景色
function changeColor(obj) {
$(obj).css("background-color","#ccc");
}
//鼠标移出条目上方时给搜索条目还原背景色
function backColor(obj) {
$(obj).css("background","white");
}
//用户点击联想商品名称时,将该商品名添加到搜索框中
function insertContent(obj) {
var $pname = $(obj).html();//获得搜索联想的商品名
//点击时将该商品名加入到搜索输入框中
$("#searchWords").val($pname);
//隐藏联想框
$("#returnKey").css("display","none");
}
</script>
***
####~~~欢迎指正交流...