尚学堂_马士兵_AJAX_学习笔记
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
AJAX:Asynchronous Javascript And XML
核心是JavaScript 不是XML
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
web2.0 的应用:
web2.0 的核心:XML + AJAX:博客 就是web2.0 的应用:
RSS也叫聚合RSS是在线共享内容的一种简易方式
(也叫聚合内容,Really Simple Syndication)
Really Simple Syndication是一种描述和同步网站内容的格式
RSS:
web2.0 的应用
我博客上的所有的文章,转换成一种XML 格式,就有一个好处
1.
文章名是什么,文章内容是什么,大家认同这种写法,
搜索引擎就可以直接搜到你们家博客上
2.
我给你一个客户端,这个客户端可以读任何博客,任何的网站博客都会公布一个RSS
RSS 的标签是固定的,任何的客户端都可以进行分析,分析好后给读者做展现
说白了还是一个XML 的应用
有人叫推模式(push):服务器端直接推给客户端,不需请求,每个人要一个客户端。
网络经济,就是客户端的经济,给你装插件,任意给你推东西
发请求的是拉模式(pull)。
我们要打好底子,迎接将来的各种潮流。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
正常情况下,到服务器取东西:
要点连接,发请求,等待处理(刷新整个页面),拿到结果(显示)
AJAX情况下,不刷新页面,发起请求
AJAX:我不再刷新页面,就能从服务器取东西。看起来像本机的应用程序了
拿到处理,只刷新一部分页面,
AJAX 实例:使用不刷新页面的验证方法:注册的时候提示用户名已经被使用
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
AJAX 基本概念:
* 构建网页的一种综合使用JavaScript 和 XML 的技术(XML 可有可无)
* 不是什么划时代的技术(javascript 旧的,只是刷新了人的脑子)
* HTML 网页的异步传输技术
* 在等待网页的传输过程中,用户依然可以和系统进行交互
* 页面不用刷新就可以更新内容
* 合理的运用可以让用户感觉更好更方便
* 但也不要滥用
* Asynchronous Javascript and XML :可以不用XML
同步:一直等小孩醒,什么事都不干(一直的等待)
异步:你一边干别的事,小孩醒了调用一个方法给你一个通知(网络传输的过程中,可以干别的)
AJAX 就是异步的Javascript ,有没有 XML 无所谓
客户端发出请求,继续干别的,服务器端处理好请求后,调用事先写好的JS 代码
* 典型的流程
1. 客户端触发异步操作
2. 创建新的XMLHttpRequest 对象(关键)
3. 与 Server 进行连接
4. 服务器端进行连接处理
5. 返回包含处理结果的XML 文档
6. XMLHttpRequest 对象接收处理结果并分析
7. 更新页面
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
XMLHttpRequest(浏览器内置的一个对象,内置的一个组件)
* 重要的JavaScript 对象,通过它提起对服务器端的(http)请求
这个请求提起后不会刷新页面,只是在背后运行
* 可以通过JavaScript 提起请求
* 如果要提起多个请求,需要多个XHR 对象
* 请求的结果被预先定义好的方法处理(处理好后,调用预先定义好的方法)
平常我们要访问一个http server ,要在浏览器里敲http://www...
这是直接敲,手动来敲。
编程上,我们可以使用XMLHttpRequest 这个对象来自动的发起一个向服务器端某个页面的请求
★★★★★★★★★★
XMLHttpRequest 属性:(particl list)
* readyState (this is a property of many JavaScript objects)
XHR 对象自己有一下内部的状态,状态值是一些int 类型的数
- 0 = UNINITIALIZED; open not yet called
//还没有初始化
- 1 = LOADING; send for request not yet called
//请求还没有发到服务器端,打开了,跟服务器端建立连接了
- 2 = LOADED; send called, headers and status are avalilable
//调用了一个方法,已经把我的请求发过去了,服务器端给了反馈
//http 头信息
- 3 = INTERACTIVE; downloading response,
responseText only partially set
//头信息拿到了,正在取得服务器给我的内容
- 4 = COMPLETED; finished downloading response
//取得服务器端的信息完成
//usually wait for XHR.readyState == 4
* responseText //反馈回来的当成纯文本
- response as text; null if error occurs of ready state < 3
* responseXML //反馈回来的当成XML 文档对象,一个 DOM 模型
- response as DOM Document object; null if error occurs or ready state < 3
* status
- integer status code
* statusText
- string status
★★★★★★★★★★
XMLHttpRequest 方法:(partial list)
* Basic methods
- open(method, url[, async]) -initializes a new HTTP request
* method can be "GET", "POST", "PUT"or"DELETE"
* url must be an HTTP URL(start with "http://")
* async is a boolean indicating whether request should be sent
saynchronously - defaults to true
- send(body) -sends HTTP request //body can be null
//可以传XRH 的内容(body),一般情况下,参数跟后面就ok,传null
- abort() - called after send() to cancel request
* Herder methods
- void setRequestHeader(name, value)
- String getResponseHeader(name)
- String getAllResponseHeaders()
* return a string where
"header: value" pairs
are delimited y carriage returns
Example return value:
Connection: Keep-Alive
Date: Sun, 15 May 2005 23:55:25 GMT
Content-Type:text/xml
Server:WEBrick/1.3.1 (Ruby/1.8.2/2004-12-25)
Content-Length:1810
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
示例: 检查用户名是否被注册:register.jsp 25:25
写javascript 不要全部写好再调试,定义方法后,马上看能不能调用
写一个方法就alert 一下,看他有没有执行
★★★★★★★★★★★★★★★
1. 客户端触发:
<input type="text" size="20" id="userid"
name="username" onblur="validate();" >
<span id="usermsg"></span>
★★★★★★★★★★★★★★★
2. JavaScript 写触发的方法,向服务器端发起一个请求,让服务器端去处理
必须创建XHR 对象:
不刷新页面向服务器端发起请求
<script type="text/javascript" >
var req; //定义一个全局的对象
//validate() 方法初始化 req 对象
function validate() {
var idField = document.getElementById("userid");
//拿到id是userid的元素
var url = "validate.jsp?id=" + escape(idField.value);
//发起请求的页面url:escape:返回url编码的字符串(识匹码)
//不同的浏览器,req 对象创建的语句不同
if(window.XMLHttpRequest) {
//netscape 浏览器,if window 的属性
req = new XMLHttpRequest();
} else if(window.ActiveXObject) { //IE
req = new ActiveXObject("Microsoft.XMLHttp");
}
//req对象在后面(悄悄的)调用url 页面
//1.什么方法open(get: 参数接后面),2.打开的网址 3.使用异步的模式
req.open("GET", url, true);
req.onreadystatechange = callback;
//callback 函数回调,函数指针:不用(),多次调用,
//改变一次状态调用一次函数指针指向的函数
//处理完状态变化的时候调用callback 方法
req.send(null);
//发送HTTP 请求
}
function callback() {
alert(req.readyState);
}
</script>
★★★★★★★★★★★★★★★
3. Server 端进行处理,JSP 在Server 端是万能的
创建要访问的JSP 页面:validate.jsp
<%
//设置反馈页面信息,不能出现中文,要加上一个JSP 头
<%@ page contentType="text/html; charset=gb2312"%>
response.setContentType("text/xml");
//return XML file
response.setHeader("Cache-Control", "no-store");
//HTTP 1.1 prevents caching at IE
response.setHeader("Pragma", "no-cache");
//HTTP 1.0
response.setDateHeader("Expires", 0);
//prevents caching at the proxy server
//no chinese
//处理
response.getWriter().write("<msg>invalid</msg>");
%>
用户存在:在UserManager 中添加 boolean userExists,连上数据库,查一下,存在返回true
JSP 中根据 JavaBean userExists 方法 返回的boolean 值,
判断返回给客户端的是valid 还是 invalid
客户端根据你返回的是valid 还是invalid,设定相关的DIV 里的内容
★★★★★★★★★★★★★★★
4. Server 端反馈,客户端接收
Server 处理请求的方式不变,输出内容不一定是XML,
可以输出一个JS 语句,直接传到客户端运行
服务器端反馈给客户端信息
找不到validate.jsp TomCat 也会给你一个状态4 的反馈:404:没有
判断Server 的反馈是正确的反馈
拿到 Server 端的反馈后,在 客户端进行展现
:解析XML
function callback() {
//alert(req.readyState);
if(req.readyState == 4) {
if(req.status == 200) {
var msg = req.responseXML.getElementsByTagName("msg")[0];
//可能拿到标签的很多元素,是一个数组
//当一个元素里有一个text 文本的时候,相当于这个元素下面有子元素(数组)
//alert(msg.childNodes[0]);
setMsg(msg.childNodes[0].nodeValue);
}
}
}
function setMsg(msg) { //把拿到的结果显示在<span> 里
if(msg == "invalid")
document.getElementById("usermsg").innerHTML =
"<font color='red'>用户名无效</font>";
else
document.getElementById("usermsg").innerHTML =
"<font color='black'>用户名可以使用</font>";
//getElementsByName name 可能多个元素
//getElementById id 就一个元素
}
这就是AJAX 基础 OVER ,不复杂,但很灵活
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
调试记录:
JavaScript 最常错误:少写 } ,单词拼写错误
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
示例:下拉条的连动
首页:
1. 分类显示,可以分无限层,把原来的分类都删了
2. 搜索分类,第一个分类select 显示根分类,第二个分类显示根分类对应的子分类
★★★★★★★★★★★★★★
删除旧商品:product.jsp
删除的时候,给一个提示,是不是确定删,取消就不执行(javascript 实现)
<a href="productdelete.jsp?id=<%=p.getId() %>"
target="detail" onclick="return confirm('确定删除')">删除</a>
return false 就不执行链接
★★★★★★★★★★★★★★
1. 直接在数据库删:
delete from product;
delete from category;
2. 添加新类别,添加的是根类别
2.1 电脑/软件/网络/办公
2.2 珠宝首饰/礼品
2.3 运动/户外/休闲
一般根类别确定后很少改变
添加子类别:
2.1 笔记本、台式机、掌上电脑、应用软件
2.2 项链、戒指
★★★★★★★★★★★★★★
非AJAX 动态生成二级连动菜单:
非 AJAX: 一次性拿到全部的菜单项,一级,二级都拿到
AJAX:根据一级,到数据库拿二级
开始写菜单连动,首先写一个静态的让他能动起来
左右显示,别上下显示:放table 里,左一个td 右一个td
非AJAX 不适合多级,
<%!
//定义一个内部使用方法,每当拿到一个topCategories 就为这个Category 生成一段二级目录JavaScript 代码
private String getSecondCategoryStr(List<Category> categories,
Category topCategory) {
StringBuffer buf = new StringBuffer();
//buf.append("if(document.getElementById('cat1').
options[document.getElementById('cat1').selectedIndex].value == "
+ topCategory.getId() + ") {");
int childCount = 1; //请选择二级目录头,默认有一个
for(int i=0; i<categories.size(); i++) {
Category c = categories.get(i);
if(c.getPid() == topCategory.getId()) { //根类别的孩子
//显示二级的后面代码,字符串要加引号,有双引号,用单引号
buf.append("document.getElementById('cat2').options["
+ childCount + "].text = '" + c.getName() + "';\n");
buf.append("document.getElementById('cat2').options["
+ childCount + "].value = '" + c.getId() + "';\n");
childCount ++;
}
}
//有双引号了,里面用单引号
buf.insert(0, "document.getElementById('cat2').options[0].text
= '请选择二级目录';\n");
buf.insert(0, "document.getElementById('cat2').options[0].value = '-1';\n");
buf.insert(0, "document.getElementById('cat2').selectedIndex = 0;\n");
buf.insert(0, "document.getElementById('cat2').options.length = " + childCount + ";\n");
buf.insert(0, "if(document.getElementById('cat1').
options[document.getElementById('cat1').selectedIndex].value == "
+ topCategory.getId() + ") {\n");
buf.append("}\n");
return buf.toString();
}
%>
<%
//10 个最新商品
List<Product> latestProducts = ProductMgr.getInstance().getLatestProducts(10);
//拿到全部的类别 grade 为1 的就是根类别
List<Category> categories = CategoryMgr.getCategories();
List<Category> topCategories = new ArrayList<Category>();
//定义一个 String 放前面生成的代码
String str = "";
for(int i=0; i<categories.size(); i++) {
Category c = categories.get(i);
if(c.getGrade() == 1) {
topCategories.add(c);
str += getSecondCategoryStr(categories, c);
}
}
%>
<!-- 类别连动 搜索开始 -->
<script type="text/javascript">
<!--
function changeCategory() {
//可以在后台打印str 看看
<%=str %>
}
-->
</script>
<table>
<tr>
<td>
<select onchange="changeCategory()" id="cat1">
<option value=0 >查询所有一级目录</option>
<%
for(int i=0; i<topCategories.size(); i++) {
Category c = topCategories.get(i);
%>
<option value=<%=c.getId() %> ><%=c.getName() %></option>
<%
}
%>
</select>
</td>
<td>
<select id="cat2" > <!-- 根据一级目录的变化而变化 -->
<option value=5 >查询有二级目录</option>
</select>
</td>
<td>
<input type="text" />
</td>
<td align="center" >
<input type="image" height=19 width=61 />
</td>
</tr>
</table>
<!-- 类别连动 搜索结束 -->
★★★★★★★★★★★★★★
使用AJAX 生成二级连动菜单:反馈字符串
changeCategory()
1. 把选择后,第一级菜单的id 传到服务器,
2. 服务器从数据库里取出来第二级Category 的,id,name...
3. 传递到客户端,客户端拿到后,进行分析,(不一定用XML 传递,可以用字符串)
4. 分析完成后形成JavaScript 代码,
5. 最后显示出来
实现:照猫画虎,模仿register.jsp AJAX 实现用户名是否存在
反馈的不是XML 是字符串
★★★★★★★★★★★★★★
调试记录:
调试,就是打印错误
1.
打印,sql 语句正确,打印,返回的list.size()->错
装到list 的时候 while 写成了 if 只有装一条了
2.
javascript 中的for 语句
for(var i=0; i<categories.length; i++)
3.
alert("id=" + id ",name=" + name); 少一个加号,后面的不显示
alert("id=" + id + ",name=" + name);
4. 选择的一级列表是空,二级列表还是上次选择的二级列表
选空的时候,客户端没有接到任何反馈,后台报错
经典调试疑难杂症: 商城视频_75_index_search_ajax.avi
老师手段多的很,解决它
5.
javascript 都写完了再调试那是相当的愚蠢的
6.
JSP 不能写中文:编码问题,要加头
<%@ page contentType="text/html; charset=gb2312"%>
★★★★★★★★★★★★★★
使用AJAX 生成二级连动菜单:反馈XML
1.
JSP 生成XML
for(int i=0; i<childs.size(); i++) {
Category c = childs.get(i);
buf.append("<category><id>" + c.getId() + "</id><name>" +
c.getName() + "</name></category>");
}
//添加一个根节点,XML
buf.insert(0, "<categories>");
buf.append("</categories>");
System.out.println(buf);
XML 文件头:
<?xml version="1.0" encoding="gb2312"?>
< >
< >
< />
< />
加上XML 文件头,IE就可以显示了,说明生成的XML 没有问题
2.
客户端解析XML :
req.responseXML 是一个object 对象
req.responseText 拿到对象的信息
可以使用XML 组件解析XML
javascript 解析XML ,对语法不确定,写几句就alert 一下
javascript 都写完了再调试那是相当的愚蠢的
视频_78 必看,不能错过 节点解析问题
一级目录空,没有问题,
★★★★★★★★★★★★★★
完全抛弃XML 使用原始的一次性拿出全部二级目录,生成JS 代码,反馈给客户端
另一种写法:很多大公司都这么写,中小型项目
(可以让二级列表字符串 在服务器端生成,动态生成javascript 代码)
让传递过来的javascript 代码执行
callback() 中:eval(req.responseText());
视频_77 找不到JSP XML输出错误,拖延时间
这种写法很多:
产品翻页的时候,只刷新某一个东西:在服务器端动态生成这些JS 代码
客户端eval 执行,写起来就是麻烦一点
二级连动 4 种方法:
1. 原始一次拿出所有一级二级目录(所有从数据库里预先取出)
2. AJAX 反馈:字符串
3. AJAX 反馈:XML,麻烦,
4. AJAX 反馈:JSP 动态执行 JavaScript ,原理:原始,一次拿出所有一级二级目录
还有一种使用内桢,不太用了
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
AJAX 总结:
AJAX 很多东西都在发展之中,
很简单 提交到服务器去,处理后传回来
有人就根据这个做出各种框架帮助你使用:
比如生成字符串很麻烦,就有人给你写专门的类库来帮你实现
form 不完善,写类库,帮你实现相应的form
AJAX 框架无数,没有一统天下的
我们学的是底层,框架怎么变,都知道背后的原理,练习熟练掌握
不用框架也能写出东西,到时候用哪种学哪种
灰狐开源站点:http://docs.huihoo.com/
框架汇总:http://docs.huihoo.com/web/ajax/ajax-frameworks.html
介绍一下哪些有名:BackBase, DOJO,Google AJAXSLT,Sarissa
JSON(Javascript Object Notation):不考虑XML:专门和JS 联系
AJAX_JSP_Tag_Library,
其他:DWR(Web Remoting) 远程方法调用....
框架:
有的是远程的方法调用,
有的是针对于XML来回传,
有的就是动态生成JS 代码
有的就是生成自定义的字符串(面向对象的字符串Jason)
浙公网安备 33010602011771号