加载中

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之后,在xmlhttponreadystatechange事件函数中响应

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/Testhttp://localhost:8080/AJAX/index.html 属于同源,可以访问。

不受同源策略限制的

  1. <script><link><img><iframe>等js不能读写加载跨域资源
  2. 表单提交,网页中的链接,重定向

利用script接收json实现跨域(JSONP跨域)

原理:

  1. 设置服务器返回类型为json
  2. 服务器返回数据格式为函数名(json数据)
  3. 在前端js中编写响应函数function 函数名(接收数据的变量,名字任意)
  4. 需要发送请求时就向页面添加script标签

原生js实现JSONP跨域

1.创建两个不同源的服务器:AJAXAJAXServlet

http://localhost:8080/AJAX/index.htmlhttp://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头信息AcceptLast-Event-IDAccept-LanguageContent-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则支持老浏览器

posted @ 2019-09-05 22:45  jialeYang  阅读(59)  评论(0编辑  收藏  举报