JS-AJAX
JS-AJAX
servlet+ajax实现示例
在web项目中新建一个servlet,访问路径为http://localhost:8080/AJAX/Test
@WebServlet("/Test")
public class Test extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out=response.getWriter();
out.write("hello"); //向浏览器输出 "hello"
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
在WebContent目录下新建一个html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function loadXMLDoc(){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest(); //IE7+,Firefox,Chrome,Safari,Opera
}else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); //IE5,6
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","http://localhost:8080/AJAX/Test",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>
</body>
</html>
此时点击按钮,会请求servlet 得到"hello"
.
发送请求
如示例中的这两句,是用来发送请求的
xmlhttp.open("GET","http://localhost:8080/AJAX/Test",true);
xmlhttp.send();
open(method,url,async)
参数 | 解释 |
---|---|
method | 请求类型(get/post) |
url | 请求地址 |
async | 是否异步(异步/同步) |
解决缓存问题
有时得到的可能会是缓存,可以加一个ID参数
xmlhttp.open("GET","http://localhost:8080/AJAX/Test?t=" + Math.random(),true);
通过get传递参数
例如servlet 需要一个name参数
String name=request.getParameter("name");
PrintWriter out=response.getWriter();
out.write("传递的name是:"+name);
可以在发送请求时传递
xmlhttp.open("GET","http://localhost:8080/AJAX/Test?name=sam",true);
通过post传递参数
使用 setRequestHeader() 来添加 HTTP 头,然后再send方法中添加参数
xmlhttp.open("POST","http://localhost:8080/AJAX/Test",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("name=sam");
url-访问服务器文件
例如在WebContent下有一个a.txt,路径为http://localhost:8080/AJAX/a.txt
,则也可以访问到
xmlhttp.open("POST","http://localhost:8080/AJAX/a.txt",true);
文件类型不限于txt,可以是任何类型,服务器脚本也不限于servlet,也可以是asp,php等
async 是否异步
如下是异步:open,send之后,在xmlhttp的onreadystatechange
事件函数中响应
xmlhttp.onreadystatechange=function(){ //因为是事件响应后才执行,所以顺序先后无所谓
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//处理代码
}
}
xmlhttp.open("GET","http://localhost:8080/AJAX/Test",true);
xmlhttp.send();
如下是同步
xmlhttp.open("GET","http://localhost:8080/AJAX/Test",false);
xmlhttp.send();
document.getElementById("myDiv").innerHTML=xmlhttp.responseText; //等待接收到再执行,所以响应阶段会卡死
同步指的是浏览器暂停,等待服务器的响应,等接收到后再执行,所以网络差或服务器繁忙时会卡死
异步指的是浏览器不暂停,把执行代码放到服务器接收完毕事件中,相当于两个进程
不推荐使用同步
接收响应
responseText
获得字符串形式的响应数据,例如示例
responseXML
获得 XML 形式的响应数据
onreadystatechange事件
XMLHttpRequest 对象有一个onreadystatechange 事件,每当该对象的readyState 属性改变时,就会触发 onreadystatechange 事件.
status 也是该对象的一个属性,表示状态.
属性 | 描述 |
---|---|
readyState | 表示XMLHttpRequest 的状态 |
0:请求未初始化 | |
1:服务器连接已建立 | |
2:请求已接收 | |
3:请求处理中 | |
4:请求已完成,且响应已就绪 | |
status | 状态码 |
200:OK | |
404:Not Find |
所以示例中的响应函数内判断语句如下
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//请求处理完毕且状态OK
}
}
同源策略
转载:Q1mi
如果两个页面的 协议,端口,域名 都相同,则两个页面具有相同的源。
下表给出了相对http://www.baidu.com/map/index.html
同源检测的示例:
URL | 是否同源 | 原因 |
---|---|---|
https://www.baidu.com/music/search.html | 否 | 协议不同 |
http://www.baidu.com:8080/map/other.html | 否 | 端口不同(默认80) |
http://www.sougou.com/map/index.html | 否 | 域名不同 |
http://www.baidu.com/photo/dog.html | 是 |
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,如上面的http://localhost:8080/AJAX/Test 和http://localhost:8080/AJAX/index.html 属于同源,可以访问。
不受同源策略限制的
<script>
,<link>
,<img>
,<iframe>
等js不能读写加载跨域资源- 表单提交,网页中的链接,重定向
利用script接收json实现跨域(JSONP跨域)
原理:
- 设置服务器返回类型为json
- 服务器返回数据格式为
函数名(json数据)
- 在前端js中编写响应函数
function 函数名(接收数据的变量,名字任意)
- 需要发送请求时就向页面添加
script
标签
原生js实现JSONP跨域
1.创建两个不同源的服务器:AJAX 和 AJAXServlet
http://localhost:8080/AJAX/index.html | http://localhost:8081/AJAXServlet/Test |
2.将第一个示例的html代码的loadXMLDoc()
部分进行修改
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function getInfo(i){ //得到服务器响应后执行相应的 回调函数
console.log(i.age); //返回json数据的是一个对象
console.log(i.name);
}
function loadXMLDoc(){
var script = document.createElement('script');
script.src = "http://localhost:8081/AJAXServlet/Test"; //请求地址
document.body.appendChild(script); //添加 script 标签
}
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>
</body>
</html>
3.将第一个示例的servlet代码修改
@WebServlet("/Test")
public class Test extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json"); //重要!设置返回类型为json
String info="{\"name\":\"sam\" , \"age\":\"18\"}"; //{"name":"sam","age":"18"}
PrintWriter out=response.getWriter();
out.write("getInfor("+info+")"); //返回一个 回调函数名 和 参数
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
jQuery实现JSONP跨域
$.getJSON()
1.将上面原生JS实现的html 代码进行修改
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
//callback是用户自定义的一个参数,用来表示回调函数名,可以随意定义
//callback=?中的?会由jQuery自动生成
$.getJSON("http://localhost:8081/AJAXServlet/Test?callback=?",function(res){
console.log(res);
});
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>
</body>
</html>
2.将上面原生JS实现的servlet 代码进行修改
@WebServlet("/Test")
public class Test extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
String info="{\"name\":\"sam\" , \"age\":\"18\"}";
String callback=request.getParameter("callback"); //获得回调函数参数
PrintWriter out=response.getWriter();
out.write(callback+"("+info+")"); //返回数据
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
$.ajax
自动生成回调函数名(推荐)
将上面原生JS实现的html 代码进行修改
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
$.ajax({
url:"http://localhost:8081/AJAXServlet/Test?callback=?",
dataType:"jsonp",
success:function(res){
console.log(res);
}
/*,error:function(){...}*/
});
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>
</body>
</html>
指定回调函数
1.将上面原生JS实现的html 代码进行修改
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function huidiao(res){ //使用服务器指定的函数名
console.log(res);
}
function loadXMLDoc(){
$.ajax({
url:"http://localhost:8081/AJAXServlet/Test",
dataType:"jsonp"
});
}
</script>
</head>
<body>
<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>
</body>
</html>
2.将上面原生JS实现的servlet 代码进行修改
@WebServlet("/Test")
public class Test extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
String info="{\"name\":\"sam\" , \"age\":\"18\"}";
PrintWriter out=response.getWriter();
out.write("huidiao("+info+")"); //返回数据
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
CORS跨域
转载:Q1mi
CORS 允许浏览器向跨源服务器发出请求,CORS需要浏览器和服务器同时支持,目前基本上主流的浏览器都支持CORS,所以只要后端服务支持CORS,就能够实现跨域
浏览器将CORS请求分成两类:
简单请求 | 非简单请求 | |
---|---|---|
请求方法 | head / get / post | 也可其他 |
HTTP头信息 | Accept ,Last-Event-ID ,Accept-Language ,Content-Language | 也可其他 |
Content-Type: [application/x-www-form-urlencoded / multipart/form-data / text/plain] |
简单请求
1.html部分
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function loadXMLDoc(){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
var obj=JSON.parse(xmlhttp.responseText); //String 转 Json
console.log(obj);
}
}
xmlhttp.open("GET","http://localhost:8081/AJAXServlet/Test",true);
xmlhttp.send();
}
</script>
</head>
<body>
<button type="button" onclick="loadXMLDoc()">输出对象</button>
</body>
</html>
2.servlet部分
@WebServlet("/Test")
public class Test extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin","*"); //允许所有ip跨域请求
String info="{\"name\":\"sam\" , \"age\":\"18\"}";
response.getWriter().println(info); //发送String类型简单数据
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
?非简单请求
不理解什么是非简单请求
response.setHeader("Access-Control-Allow-Methods","*"); //允许所有请求类型(简单请求只支持get,post,head)
response.setHeader("Access-Control-Allow-Headers","*"); //允许所有请求头
response.setHeader("Access-Control-Allow-Credentials","true"); //允许携带cookie
response.setHeader("Access-Control-Max-Age","3600"); //重新预检验跨域的缓存时间 (s)
OCRS跨域和JSONP跨域对比
ocrs跨域支持所有请求方式
,而jsonp跨域只支持get
ocrs不是所有浏览器都支持,jsonp则支持老浏览器