文章目录
前言
ajax原理图:
一、入门
可以去w3shcool文档查询
代码示例:
demo1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
//1.获取一个XMLHttpRequest对象
var xmlhttp = null;
function sendAjax() {
if (window.XMLHttpRequest) {// code for all new browsers
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {// code for IE5 and IE6
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.设置一个回调函数,处理服务器响应数据
xmlhttp.onreadystatechange = callback;
//3.设置请求方式以及url
var url = "http://localhost:8080/jquery/ajax";
xmlhttp.open("GET", url, true);
//4.向服务器发送请求
xmlhttp.send(null);
}
//回调函数
function callback() {
if (xmlhttp.readyState == 4) {// 4 = "loaded"
if (xmlhttp.status == 200) {// 200 = OK
// 5.得到响应数据
alert(xmlhttp.responseText);
} else {
alert("Problem retrieving XML data");
}
}
}
</script>
</head>
<body>
<input type="button" value="按钮" onclick="sendAjax()">
</body>
</html>
AjaxServlet
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AjaxServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("hello ajax");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
运行后点击按钮弹框,hello ajax
二、XMLHttpRequest 详解
1.属性
onreadystatechange
它是用于绑定回调函数,当服务器响应数据回来后,我们可以在指定的回调函数中进行数据处理。
readyState
HTTP 请求的状态.
status
由服务器返回的 HTTP 状态代码
responesText 或 responseXML
获取服务器响应数据
2.方法
open
它是用于设置请求方式,url及是否异步
参数1:HTTP请求方式POST/GET。
参数2:url路径,
参数3:true/false代表是否异步。
send
它是真正向服务器发送请求。如果请求方式是get,那么我们使用send(null)原因:get请求方式是没有http请求体只有post请求方式时,才有请求体。所以send 的参数只是在post请求时使用,例如:Xmlhttp.send(“username=xxx&password=xxx")。
setRequestHeader
注意:如果请求方式是 POST,那么我们在使用时,必须设置一个请求头,就需要使用setRequestHeader方法来完成。
xmlhttp.open("POST",url,true);//如果是post方式,则需要如下设置请求头
xmlhttp.setRequestHeader("content-type","application/x-www-form-urlencoded");
3.练习案例
检验用户名是否可以使用
下列例子不适用数据库,假设数据库中有tom用户名
my.js
function getXmlHttpRequest(){
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else if(window.ActiveXObject){
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlhttp;
}
demo2.html
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/jquery/js/my.js"></script>
<script type="text/javascript">
function checkUsername() {
//1.得到文本框信息
var usernameValue = document.getElementById("username").value;
//2.使用ajax向服务器发送请求,并且携带username信息
var xmlHttp = getXmlHttpRequest();
xmlHttp.onreadystatechange = function(){
if (xmlHttp.readyState == 4) { // 4 = "loaded"
if (xmlHttp.status == 200) { // 200 = OK
var responseMsg = xmlHttp.responseText;
document.getElementById("username_msg").innerHTML=responseMsg;
}
}
};
xmlHttp.open("POST","/jquery/UserServlet");
xmlHttp.setRequestHeader("content-type","application/x-www-form-urlencoded");
//3.处理服务器响应的数据,在span块中显示信息
xmlHttp.send("username="+usernameValue);
}
</script>
</head>
<body>
<input type="text" id="username" onblur="checkUsername()"><span id="username_msg"></span>
</body>
</html>
UserServlet
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UserServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
String msg = "";
if("tom".equals(username)) {
msg="<font color='red'>用户名已经被占用</font>";
}else {
msg="<font color='green'>用户名可以使用</font>";
}
response.setCharacterEncoding("utf-8");
response.getWriter().write(msg);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
运行后效果如下:
省市二级联动
练习:
demo3.html
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="/jquery/js/my.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
function getProvince(){
//向服务器请求获取省份信息
var xmlHttp = getXmlHttpRequest();
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4){
if(xmlHttp.status == 200){
//将服务器得到的信息处理填充到省份下拉框
var provinces = xmlHttp.responseText; //辽宁,黑龙江,吉林
var ps = provinces.split(",");
for(var i=0;i<ps.length;i++){
var option=document.createElement("option");
option.text = ps[i];
document.getElementById("province").add(option);
}
}
}
};
xmlHttp.open("POST","/jquery/ProvinceServlet");
xmlHttp.setRequestHeader("content-type","application/x-www-form-urlencoded");
xmlHttp.send(null);
}
function getCity(){
var provinceElement = document.getElementById("province");
var ops = provinceElement.options;
var option = ops[provinceElement.selectedIndex];
var pname = option.text;
//向服务器发送请求
var xmlHttp = getXmlHttpRequest();
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4){
if(xmlHttp.status == 200){
//清空城市下拉框信息
document.getElementById("city").innerHTML = "<option>--请选择城市--</option>";
var citys = xmlHttp.responseText; //辽宁,黑龙江,吉林
var cs = citys.split(",");
for(var i=0;i<cs.length;i++){
var option=document.createElement("option");
option.text = cs[i];
document.getElementById("city").add(option);
}
}
}
};
xmlHttp.open("POST","/jquery/CityServlet");
xmlHttp.setRequestHeader("content-type","application/x-www-form-urlencoded");
xmlHttp.send("pname="+pname);
}
</script>
</head>
<body onload="getProvince()">
<select id="province" onchange="getCity()">
<option>--请选择省份--</option>
</select>
<select id="city">
<option>--请选择城市--</option>
</select>
</body>
</html>
ProvinceServlet
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.CityUtil;
public class ProvinceServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String province = CityUtil.getProvince();
response.setCharacterEncoding("utf-8");
response.getWriter().write(province);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
CityServlet
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.CityUtil;
public class CityServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String pname = request.getParameter("pname");
String citys = CityUtil.getCitys(pname);
response.setCharacterEncoding("utf-8");
response.getWriter().write(citys);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
CityUtil
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class CityUtil {
private static final Map<String, String> citys=new HashMap<String,String>();
static {
citys.put("黑龙江","哈尔滨,大庆,齐齐哈尔");
citys.put("吉林","长春,吉林,四平");
citys.put("辽宁","沈阳,大连,葫芦岛");
}
//获取省份方法
public static String getProvince() {
Set<String> set = citys.keySet();
String provinces = "";
for(String p: set) {
provinces+=p+",";
}
return provinces.substring(0,provinces.length()-1);
}
//获取城市信息
public static String getCitys(String provinceName) {
return citys.get(provinceName);
}
}
运行如下图:
三、jQueryAjax
1.$ .ajax()它是jquery,提供的最基本的ajax编程方式。它的功能比较强大,但是使用比较麻烦,一般不使用,它是将远程数据加载到XMLHttpRequest对象中。
2.load get post它们简化了$.ajax操作,get post针对get与post请求的,它们是开发中使用的比较多。
3.getScript getJSON它们是用于解决ajax跨域问题的。
1. load使用(了解)
载入远程HTML文件代码并插入至DOM中
load方法是将服务器响应的数据直接插入到指定的dom元素中
那么jquery 中的 load方法它的请求方式是什么?
1.如果有参数请求方式是post
2.如果没有参数请求方式是get
例子:
验证用户名是否可以使用
LoadServlet
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
if("tom".equals(username)) {
response.getWriter().write("<font color='red'>用户名被占用</font>");
}else {
response.getWriter().write("<font color='green'>用户名可以使用</font>");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
demo4.html
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/jquery/js/jquery.js"></script>
<script type="text/javascript">
$(function(){
//添加失焦事件
$("#username").blur(function(){
var usernameValue = $("#username").val();
var url="/jquery/LoadServlet";
$("#username_span").load(url,{'username':usernameValue},function(){
});
});
})
</script>
</head>
<body>
<input type="text" name="username" id="username">
<span id="username_span"></span><br>
<input type="password" name="password"><br>
</body>
</html>
2. $.ajax介绍(了解)
$ .ajax它是jquery中最基本的 ajax操作,load get post都简化了$.ajax操作
例子:如果使用$.ajax那么上述的demo4.html则修改为
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/jquery/js/jquery.js"></script>
<script type="text/javascript">
$(function(){
//添加失焦事件
$("#username").blur(function(){
var usernameValue = $("#username").val();
//使用$.ajax完成操作
$.ajax({
url:"/jquery/LoadServlet",
data:{'username':usernameValue},
type:"POST",
dataType:"html",
success:function(data){
$("#username_span").html(data);
}
});
});
})
</script>
</head>
<body>
<input type="text" name="username" id="username">
<span id="username_span"></span><br>
<input type="password" name="password"><br>
</body>
</html>
3. $.psot 与 $.get(了解)
例子:如果使用$.psot 与 $.get那么上述的demo4.html则修改为
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/jquery/js/jquery.js"></script>
<script type="text/javascript">
$(function(){
//添加失焦事件
$("#username").blur(function(){
var usernameValue = $("#username").val();
var url="/jquery/LoadServlet"
//使用$.post完成操作
$.post(url,{"username":usernameValue},function(data){
$("#username_span").html(data);
},"html");
//使用$.get完成操作
//$.get(url,{"username":usernameValue},function(data){
// $("#username_span").html(data);
//},"html");
});
})
</script>
</head>
<body>
<input type="text" name="username" id="username">
<span id="username_span"></span><br>
<input type="password" name="password"><br>
</body>
</html>
4. json(重点)
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式
json,简单说就是 javascript中的对象和数组.
对象:{key: value,key:value…}
数组:[“java”," javascript",“vb”…]
注意:在 json中它的两种结构可以互相嵌套{key:[value1,value2],key:value}
[{name:xxx},{key:value}, {key:value}]
例子:fastjson将java对象转换为json数据
Project
public class Project {
private int id;
private String name;
private int count;
private double price;
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 int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
JsonTest
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.alibaba.fastjson.JSONObject;
public class JsonTest {
@Test //将一个Project对象转化成json
public void test1() {
Project p1 = new Project();
p1.setId(1);
p1.setCount(100);
p1.setName("电视机");
p1.setPrice(2000);
String json = JSONObject.toJSONString(p1);
System.out.println(json);
}
@Test //将List<Project>对象转换成json
public void test2() {
Project p1 = new Project();
p1.setId(1);
p1.setCount(100);
p1.setName("电视机");
p1.setPrice(2000);
Project p2 = new Project();
p2.setId(2);
p2.setCount(200);
p2.setName("手机");
p2.setPrice(1000);
List<Project> list = new ArrayList<Project>();
list.add(p1);
list.add(p2);
String json = JSONObject.toJSONString(list);
System.out.println(json);
}
}
注意:
1.将对象转换为json数据的时候,名称可以自己指定
在Project类中使用如下的注解即可
@JSONField(name = "编号")
private int id;
@JSONField(name = "产品名")
private String name;
@JSONField(name = "数量")
private int count;
@JSONField(name = "价格")
private double price;
2.如果 java对象中存在日期类型属性java.util.Date可以用指定的格式来转换成json
如果没有指定格式,则输出的数据是毫秒值
例子:
在Project中进行如下设置即可
@JSONField(format = "yyyy年MM月dd日")
private Date pDate;
3.如果java类中的某些属性不想生成json中?
指定filter
只需要在jsonTest中添加如下过滤器即可
SerializeFilter filter = new PropertyFilter() {
public boolean apply(Object arg0, String arg1, Object arg2) {
//System.out.println(arg0);//类名
//System.out.println(arg1);//属性名
//System.out.println(arg2);//属性值
if("编号".equals(arg1)) {//如果有别名,则需要使用别名
return false;
}
return true;
}
};
String json = JSONObject.toJSONString(p1,filter);
如果需要指定想要的属性,如下操作更方便
//简化上述操作,将需要的属性指定
SerializeFilter filter = new SimplePropertyPreFilter("产品名","价格");
4.fastjson将java数据转换为json时的循环引用问题
例:
执行如下操作时(集合内有多个重复元素),数据有问题
@Test //将List<Project>对象转换成json
public void test3() {
Project p1 = new Project();
p1.setId(1);
p1.setCount(100);
p1.setName("电视机");
p1.setPrice(2000);
List<Project> list = new ArrayList<Project>();
list.add(p1);
list.add(p1);
list.add(p1);
String json = JSONObject.toJSONString(list);
System.out.println(json);
}
运行如下图:
是因为json发现元素一样,所以直接循环引用。
解决方式:只需要添加取消循环引用即可
String json = JSONObject.toJSONString(list,SerializerFeature.DisableCircularReferenceDetect);
上述操作即可解决。
5.练习案例
显示商品信息
代码示例:
demo5.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/jquery/js/jquery.js"></script>
<script type="text/javascript">
$(function(){
$("#content").hide();
$("#a").toggle(function(){
//向服务器发送请求,得到商品信息,在页面上展示
var url="/jquery/ProductServlet";
$.post(url,function(data){
var jsonObj = eval(data);
//处理响应的json数据,封装成table的html代码
var tab = $("<table border='1px'><tr><td>编号</td><td>名称</td><td>数量</td><td>价格</td></tr></table>");
for(var i=0;i<jsonObj.length;i++){
var obj = jsonObj[i];
var tr = $("<tr><td>"+obj.id+"</td><td>"+obj.name+"</td><td>"+obj.count+"</td><td>"+obj.price+"</td></tr>");
tab.append(tr);
}
$("#content").append(tab);
$("#content").show();
},"json");
},function(){
//将商品的信息隐藏
$("#content").hide();
$("#content").html("");
});
});
</script>
</head>
<body>
<a href="javascript:void(0)" id="a">显示商品信息</a>
<hr>
<div id="content">
</div>
</body>
</html>
ProductServlet
package com.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.domain.Project;
public class ProductServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
Project p1 = new Project();
p1.setId(1);
p1.setCount(100);
p1.setName("电视机");
p1.setPrice(2000);
Project p2 = new Project();
p2.setId(2);
p2.setCount(200);
p2.setName("手机");
p2.setPrice(1000);
List<Project> list = new ArrayList<Project>();
list.add(p1);
list.add(p2);
String json = JSONObject.toJSONString(list);
response.getWriter().write(json);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
运行如下:
通过一个Servlet处理两次请求,可以通过添加参数的方式来判断
6.XStream (了解)
可以使用XStream工具来完成xml与 java对象之间的转换。它也可以完成java对象与json之间的转换。
代码示例:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.thoughtworks.xstream.XStream;
public class XmlTest {
public static void main(String[] args) {
Map<Province, List<City>> map = new HashMap<Province, List<City>>();
Province p1 = new Province();
p1.setId(1);
p1.setName("浙江");
City c11 = new City();
c11.setId(1);
c11.setName("杭州");
City c12 = new City();
c12.setId(2);
c12.setName("温州");
List<City> l1 = new ArrayList<City>();
l1.add(c11);
l1.add(c12);
map.put(p1, l1);
Province p2 = new Province();
p2.setId(1);
p2.setName("江苏");
City c21 = new City();
c21.setId(1);
c21.setName("南京");
City c22 = new City();
c22.setId(2);
c22.setName("南通");
List<City> l2 = new ArrayList<City>();
l2.add(c21);
l2.add(c22);
map.put(p2, l2);
//使用xstream 完成java对象转换成xml操作
XStream xStream = new XStream();
//设置类或者属性别名
xStream.alias("Province", Province.class);
xStream.alias("City", City.class);
xStream.alias("Citys", List.class);
//给属性设置别名
xStream.aliasField("城市名", City.class, "name");
//忽略省略某些属性
xStream.omitField(Province.class, "id");
//设置java类的属性变成节点属性
xStream.useAttributeFor(Province.class,"name");
String xml = xStream.toXML(map);
System.out.println(xml);
}
}
结果如下:
<map>
<entry>
<Province name="江苏"/>
<Citys>
<City>
<id>1</id>
<城市名>南京</城市名>
</City>
<City>
<id>2</id>
<城市名>南通</城市名>
</City>
</Citys>
</entry>
<entry>
<Province name="浙江"/>
<Citys>
<City>
<id>1</id>
<城市名>杭州</城市名>
</City>
<City>
<id>2</id>
<城市名>温州</城市名>
</City>
</Citys>
</entry>
</map>
以上操作可以通过注解使用
//只需要如下操作就可以
xStream.autodetectAnnotations(true);//开启注解使用
String xml = xStream.toXML(map);
city
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
@XStreamAlias("城市")
public class City {
@XStreamOmitField //忽略属性
private int id;
@XStreamAsAttribute
@XStreamAlias("城市名")
private String name;
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;
}
}
运行结果如下
<map>
<entry>
<com.domain.Province>
<id>1</id>
<name>江苏</name>
</com.domain.Province>
<list>
<城市 城市名="南京"/>
<城市 城市名="南通"/>
</list>
</entry>
<entry>
<com.domain.Province>
<id>1</id>
<name>浙江</name>
</com.domain.Province>
<list>
<城市 城市名="杭州"/>
<城市 城市名="温州"/>
</list>
</entry>
</map>
四、跨域问题
跨域它是不同的域名(服务器)之间的相互的资源的访问
当协议,域名,端口号任意一个不相同,它们就是不同的域。
正常情况下,因为浏览器安全问题,不同域的资源是不可以访问的。
什么情况下会使用到跨域?
一般情况是在自己的内部的工程中会出现跨域情况。有三种解决方案:
1代理方案前端页面访间本地的服务器,本地服务器访问其它域的资源,它是服务器
端的跨域问题解决。
2.JSONP可用于解决主流浏览器的跨域数据访问的问题。HTML 的script元素的src是一个例外,不受同源约束。利用script元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON资料,而这种使用模式就是所谓的JSONP。用JSONP抓到的资料并不是JSON,而是任意的JavaScript,用JavaScript直译器执行而不是用JSON解析器解析。
3.XHR2全称xMLHttpRequest Level2它是HTML5提供的方法,一般是在移动开发中使用。
在jauery中我们可以使用$.ajax, $.getJSON, $.getScript,来解跨域问题。
跨域服务器修改的地方
//跨域问题开头
String callback = request.getParameter("callback");
。。。。
。。。
//结尾响应
//跨域响应需要修改
response.getWriter().write(callback+"("+json+")");
页面修改
$("#a").toggle(function(){ //事件例子
//跨域问题
var url="http://localhost:8080/jquery/ProductServlet";
$.ajax({
url:url,
type:"get",//只能是get解决
dataType:"jsonp",
jsonpCallback:"cb",//指定名字
success:function(data){
。。。。
。。。。
}
});
原理分析
$.getJSON 它就是 $.ajax解决跨域问题的简化操作。
需要的时候查看文档即可
var url="http://localhost:8080/jquery/ProductServlet?callback=?";// callback=?不要落下
$.getJSON(url,function(data){
})