javascript jsonp
ajax在使用中会受到同源策略限制,当目标url的协议,域名,端口之一与脚本所在文档不一致时就不能访问并获取数据。解决这一问题的方案有很多:
- 服务器端代理
- 跨域资源共享
- 通过含有src属性的元素请求资源:,<script>,<iframe>,<img>
其中jsonp属于第三种。主要思路是:
- 在请求文档中编写好对请求数据进行处理的回调函数
- 通过<script>请求需要的数据并以参数形式告知服务器,支持jsonp的服务器在响应时返回以json作为参数的函数调用表达式
- 在服务器端接收回调函数名并生成对应字符串
- 客户端收到服务器返回的字符串然后调用
下面是一个简单的例子。服务器端使用普通jsp文件
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 3 <% 4 String users = "[{\"name\": \"zhao\", \"age\": \"24\"}," 5 + "{\"name\": \"qian\", \"age\": \"24\"}," 6 + "{\"name\": \"sun\", \"age\": \"24\"}," 7 + "{\"name\": \"li\", \"age\": \"24\"}" 8 +"]"; 9 String callback = request.getParameter("callback"); 10 11 if (callback == null) 12 { 13 out.println(users); 14 } // end if 15 else 16 { 17 out.println(callback + "(" + users + ")"); 18 } // end else 19 20 %>
客户端使用普通html
1 <!doctype html> 2 <html lang="zh"> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta name="description" content=""> 7 <meta name="author" content=""> 8 9 <title>Template Index</title> 10 11 </head> 12 <body> 13 <h1 id="jsonp">json-p</h1> 14 <div id="container"> 15 </div> 16 <script> 17 var showUsers = function (list) 18 { 19 var container = document.getElementById("container"); 20 list.forEach(function (d, i) { 21 var item = document.createElement("p"); 22 item.innerHTML = "id: " + i + " name: " +d.name + " age: " + d.age; 23 container.appendChild(item); 24 }); 25 }; // end showUsers() 26 27 window.addEventListener("load", function () { 28 var url = "http://localhost:8080/ajax/userList.jsp"; // 根据实际url设置 29 var jsonp = document.getElementById("jsonp"); 30 31 jsonp.addEventListener("click", function () { 32 var script = document.createElement("script"); 33 script.src = url + "?callback=showUsers"; 34 var head = document.getElementsByTagName("body")[0]; 35 head.appendChild(script); 36 }); 37 }); 38 39 </script> 40 </body> 41 </html>
相比跨源资源共享和服务器端代理jsonp相对简单,也存在一定缺点:
- script标签的局限性使得只支持GET方法
- 缺少对传输的状态控制