asynchronous javascript and xml:异步的js和xml
异步交互和同步交互
同步:发送请求后需等待服务器响应结束,才能发送第二个请求
同步:发送一个请求后,无需等待服务器的响应就能发送第二个请求。可以使用js来接收服务器的响应,局部刷新
优缺点:
优点:
异步交互增强用户体验
服务器无需响应整个页面
缺点:
不能应用在所有场景
发送请求多,增加服务器压力
var xmlHttp=new XMLHttpRequest();
var xmlHttp=new ActiveObject("Msml12.XMLHTTP");
xmlHttp.open("GET","/day23_1/AServlet",true);
(三个参数为:请求方式,请求的URL,请求是否为异步)xmlHttp.send(null)
:必须给出null,如果不给会造成部分浏览器无法发送var state=xmlHttp.readyState;
//0、1、2、3、4var status=xmlHttp.status;
//例如为200、404、500var content=xmlHttp.responseText;
//得到服务器响应的文本格式的内容var content=xmlHttp.responseXML;
//得到服务器响应的xml响应的内容(它是Document对象了)xmlHttp.onreadstatechange=function(){/xmlHttp的五种状态都会调用本方法
if(xmlHttp.readyState==4&&xmlHttp.status==200){//双重判断
var text=xmlHttp.responseText;//获取服务器的响应内容
};
ajax1.jsp:客户端
<script type="text/javascript">
function createXMLHttpRequest(){
try{
return new XMLHttpRequest();//大多数浏览器
}catch(e){
try{
return ActiveXObject("Msxm12.XMLHTTP");//IE6.0
}catch(e){
try{
return ActiveXObject("Microsoft.XMLHTTP");//IE5.5及更早
}catch(e){
throw e;
}
}
}
}
window.onload=function(){
var btn=document.getElementById("btn");
btn.onclick=function(){
//1.得到异步对象
var xmlHttp=createXMLHttpRequest();
//2.打开与服务器的连接
xmlHttp.open("GET"," ",true);
//3.发送请求
xmlHttp.send(null);
//4.给异步对象的onreadystatechange事件注册监听器
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4&&xmlHttp.status==200){
var text=xmlHttp.responseText;
var h1=document.getElementById("h1");
h1.innerHTML=text;
}
}
}
}
</script>
</head>
<body>
<button id="btn">点击这里</button>
<h1 id="h1"></h1>
</body>
AServlet:服务端
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
System.out.println("Hello AJAX");
response.getWriter().print("Hello AJAX!!!");
}
}
在点击页面按钮后,页面部分刷新,打印Hello AJAX,地址栏不会刷新
如果发送请求时带有参数,一般使用POST
改变:
xmlHttp.open("GET"," ",true);
xmlHttp.setRequestHeader("Content-Type","application/x-www.form-urlencoded");
btn.onclick=function(){
var xmlHttp=createXMLHttpRequest();
/**************修改请求方式为POST*************/
xmlHttp.open("POST"," ",true);
/**************设置请求头Content-Type***********/
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
/*************发送指定时请求体**************/
xmlHttp.send("username=张三&password=123");
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4&&xmlHttp.status==200){
var text=xmlHttp.responseText;
var h1=document.getElementById("h1");
h1.innerHTML=text;
}
}
}
AServlet
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("UTF-8");
String username=request.getParameter("username");
System.out.println("POST: Hello AJAX "+username);
response.getWriter().print("POST: Hello AJAX!!! "+username);
}
ajax3.jsp
window.onload=function(){
var userEle=document.getElementById("usernameEle");
userEle.onblur=function(){
var xmlHttp=createXMLHttpRequest();
xmlHttp.open("POST"," ",true);
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlHttp.send("username="+userEle.value);
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4&&xmlHttp.status==200){
var text=xmlHttp.responseText;
var span=document.getElementById("errorSpan");
if(text=="1")
span.innerHTML="用户名已被注册!";
else
span.innerHTML="";
}
}
}
}
服务器端:
设置响应头:ContentType,其值为:text/xml;charset=utf-8
客户端:
var doc=xmlHttp.responseXML;
//得到的是Document对象
BServlet
public class BServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String xml = "" +
"" +
"zhangSan " +
"18 " +
"male " +
"" +
"";
response.setContentType("text/xml;charset=utf-8");
response.getWriter().print(xml);
}
}
ajax.4
window.onload = function() {
var btn = document.getElementById("btn");
btn.onclick = function() {
var xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", " ", true);
xmlHttp.send(null);
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var doc = xmlHttp.responseXML;
var ele = doc.getElementsByTagName("student")[0];
var number = ele.getAttribute("number");
var name;
var age;
var sex;
if(window.addEventListener) {
name = ele.getElementsByTagName("name")[0].textContent;//其他浏览器
} else {
name = ele.getElementsByTagName("name")[0].text;//IE支持
}
if(window.addEventListener) {
age = ele.getElementsByTagName("age")[0].textContent;//其他浏览器
} else {
age = ele.getElementsByTagName("age")[0].text;//IE支持
}
if(window.addEventListener) {
sex = ele.getElementsByTagName("sex")[0].textContent;//其他浏览器
} else {
sex = ele.getElementsByTagName("sex")[0].text;//IE支持
}
var text = number + ", " + name + ", " + age + ", " + sex;
document.getElementById("h1").innerHTML = text;
}
};
};
};
</script>
</head>
<body>
<button id="btn">点击这里</button>
<h1 id="h1"></h1>
</body>
首先写表单:
ajax5.jsp
<body>
<h1>省市联动h1>
<select name="province" id="p">
<option>===请选择省===option>
select>
<select name="city" id="c">
<option>===请选择市===option>
select>
body>
选择省份:
页面在加载完成后,读取china.xml中的所有province的name属性,并用“,”连接成字符串返回给页面
public class ProvinceServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
/*
* 创建解析器对象
* 调用读方法得到Document
*/
SAXReader reader=new SAXReader();
InputStream input=this.getClass().getResourceAsStream("/china.xml");
try {
Document doc=reader.read(input);
/*
* 查询所有province的name属性
* 将所有属性值连接成一个字符串发送给客户端
*/
List<Attribute> a=doc.selectNodes("//province/@name");
StringBuilder sb=new StringBuilder();
for(int i=0;i<a.size();i++) {
sb.append(a.get(i).getValue());
if(i<a.size()-1)
sb.append(",");
}
response.getWriter().print(sb);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
}
页面得到text信息,再将字符串分割成数组,为每个数组元素创建一个option,其实际值和显示值都为省份名称,再把每个option加到省份下拉框中
/*
* 请求ProvinceServlet得到所有省份名
* 遍历创建
window.onload=function(){//页面加载完成即执行
var xmlHttp=createXMLHttpRequest();
xmlHttp.open("GET"," ",true);
xmlHttp.send(null);
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4&&xmlHttp.status==200){
var text=xmlHttp.responseText;
var arr=text.split(",");
for(var i=0;i<arr.length;i++){
var op=document.createElement("option");
op.value=arr[i];//设置实际值
var textNode=document.createTextNode(arr[i]);
op.appendChild(textNode);//设置显示值
document.getElementById("p").appendChild(op);
}
}
};
选择市:
在jsp页面添加改变监听器,在选项改变时,发送省份名称给CityServlet,它根据省份名称返回一个省的xml给页面
public class CityServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/xml;charset=utf-8");//注意发送xml时这里要修改
/*
* 获取省份名称
* 使用省份名称查找到对应元素
* 把province元素转换成字符串发送
*/
SAXReader reader=new SAXReader();
InputStream in=this.getClass().getResourceAsStream("/china.xml");
Document doc;
try {
doc = reader.read(in);
String pname=request.getParameter("pname");
Element proEle=(Element) doc.selectSingleNode("//province[@name='"+pname+"']");
String xmlStr=proEle.asXML();//把元素转换为字符串
response.getWriter().print(xmlStr);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
}
页面同样根据xml创建option,添加到市的下拉框中:
/*
* 给province选择添加改变监听
* 使用选择的省份名请求CityServlet元素,得到元素
* 获取元素中所有元素,遍历获取文本内容发送字符串
* 创建
var proSelect=document.getElementById("p");
proSelect.onchange=function(){//添加改变监听
var xmlHttp=createXMLHttpRequest();
xmlHttp.open("POST"," ",true);
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlHttp.send("pname="+proSelect.value);//把下拉列表中选择的值发送给服务器
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4&&xmlHttp.status==200){
//移除上次的结果
var citySelect=document.getElementById("c");
var optionEleList=citySelect.getElementsByTagName("option");
while(optionEleList.length>1)
citySelect.removeChild(optionEleList[1]);
var doc=xmlHttp.responseXML;
var cityEleList=doc.getElementsByTagName("city");
for(var i=0;i<cityEleList.length;i++){
var cityEle=cityEleList[i];
var cityName;
if(window.addEventListener)
cityName=cityEle.textContent;
else
cityName=cityEle.text;
var op=document.createElement("option");
op.value=cityName;
var textNode=document.createTextNode(cityName);
op.appendChild(textNode);
citySelect.appendChild(op);
}
}
};
};
};
从数据库中查询出来的都是JavaBean对象,需要先将其转换为xml才能供页面使用。
XStream就是可以把JavaBean转换(序列化)为xml的工具。
需要先导入两个包:
使用:
XStream xstream=new XStream();
String xmlStr=xstream.toXML(javabean);
但这样生成的xml的格式并不是很好,例如:
public class City {
private String name;//市名
private String description;//描述
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String toString() {
return "City [name=" + name + ", description=" + description + "]";
}
public City(String name, String description) {
super();
this.name = name;
this.description = description;
}
}
public class Province {
private String name;// 省名
private List<City> cities = new ArrayList<City>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<City> getCities() {
return cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
public void addCity(City city) {
cities.add(city);
}
}
public class Demo1 {
public List<Province> getProinvceList() {
Province p1 = new Province();
p1.setName("北京");
p1.addCity(new City("东城区", "DongChengQu"));
p1.addCity(new City("昌平区", "ChangPingQu"));
Province p2 = new Province();
p2.setName("辽宁");
p2.addCity(new City("沈阳", "shenYang"));
p2.addCity(new City("葫芦岛", "huLuDao"));
List<Province> provinceList = new ArrayList<Province>();
provinceList.add(p1);
provinceList.add(p2);
return provinceList;
}
public void fun1() {
List<Province> proList = getProinvceList();
XStream xstream = new XStream();//使用XStream
String s = xstream.toXML(proList);
System.out.println(s);
}
}
得到的xml:
<list> --> List类型显示list
<cn.itcast.demo1.Province> --> javabean的类型为Province,它元素的名称为类的完整名
<name>北京name> --> javabean的属性名
<cities> --> javabean的属性名
<cn.itcast.demo1.City> --> 类名
<name>东城区name> --> 属性名
<description>DongChengQudescription> --> 属性名
cn.itcast.demo1.City>
<cn.itcast.demo1.City>
<name>昌平区name>
<description>ChangPingQudescription>
cn.itcast.demo1.City>
cities>
cn.itcast.demo1.Province>
<cn.itcast.demo1.Province>
<name>辽宁name>
<cities>
<cn.itcast.demo1.City>
<name>沈阳name>
<description>shenYangdescription>
cn.itcast.demo1.City>
<cn.itcast.demo1.City>
<name>葫芦岛name>
<description>huLuDaodescription>
cn.itcast.demo1.City>
cities>
cn.itcast.demo1.Province>
list>
让xml更好看的使用细节:
xstream.alias("china",List.class)
让List类型生成的元素名为chinaxstream.useAttributeFor(Province.class,"name")
name是成员变量,默认生成name元素,这里改为生成province元素的name属性xstream.addImplicitCollection(Province.class,"cities")
让Province类型的cities成员不生成元素,只使用其内容xstream.omitField(City.class,"description")
在生成的xml中不会出现City类的description的元素public void fun5() {
List<Province> proList = getProinvceList();
XStream xstream = new XStream();
xstream.alias("china", List.class);//给List类型指定别名为china
xstream.alias("province", Province.class);//给Province指定别名为province
xstream.alias("city", City.class);//给City类型指定别名为city
xstream.useAttributeFor(Province.class, "name");//把Province类型的name属性,生成元素的属性
xstream.addImplicitCollection(Province.class, "cities");//去除Provice类的名为cities的List类型的属性
xstream.omitField(City.class, "description");//让City类的,名为description属性不生成对应的xml元素
String s = xstream.toXML(proList);
System.out.println(s);
}
得到:
<china>
<province name="北京">
<city>
<name>东城区name>
city>
<city>
<name>昌平区name>
city>
province>
<province name="辽宁">
<city>
<name>沈阳name>
city>
<city>
<name>葫芦岛name>
city>
province>
china>
JSON是js提供的一种数据交换格式
语法:
var str = "{\"name\": \"zhangSan\", \"age\": 18, \"sex\": \"male\"}";
var person = eval("(" + str + ")");//该函数执行字符串
JSON与xml的比较
导包:
commons-beanutils.jar
commons-collections.jar
commons-lang.jar
commons-logging.jar
ezmorph.jar
json-lib-jdk.jar
xom.jar
核心类:
String s=map.toString()
JSONObject map=JSONObject.fromObject(person)
把对象转换成JSONObject对象Strings=list.toString()
JSONArray jsonArray=JSONObject.fromObject(list);
把list转换成JSONArray对象//当做map使用
public void fun1() {
JSONObject map = new JSONObject();
map.put("name", "zhangSan");
map.put("age", 23);
map.put("sex", "male");
String s = map.toString();
System.out.println(s);
}
//已经有一个Person对象时,可以把Person对象转换成JSONObject对象
public void fun2() {
Person p = new Person("liSi", 32, "female");
// 把对象转换成JSONObject类型
JSONObject map = JSONObject.fromObject(p);
System.out.println(map.toString());
}
//当做list使用
public void fun3() {
Person p1 = new Person("zhangSan", 23, "male");
Person p2 = new Person("liSi", 32, "female");
JSONArray list = new JSONArray();
list.add(p1);
list.add(p2);
System.out.println(list.toString());
}
//原来就有一个List,我们需要把List转换成JSONArray
public void fun4() {
Person p1 = new Person("zhangSan", 23, "male");
Person p2 = new Person("liSi", 32, "female");
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
System.out.println(JSONArray.fromObject(list).toString());
}