在jQuery中如果使用JSONP只需要将返回数据类型设置为jsonp就可以了,但是这种方法只支持get请求,不支持post请求;请求是同步的;服务器返回数据要处理,要添加回调函数,麻烦。
3.4、跨域资源共享(CORS)
跨域资源共享(CORS)是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源。
CORS与JSONP相比:
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
CORS有两种模型可以实现:
1.简单模型
支持get/post/put/delete请求,例如返回Access-Control-Allow-Origin:*,但是不允许自定义header且会忽略cookies,且post数据格式有限制,只支持‘text/plain','application/x-www-urlencoded'and'multipart/form-data',其中'text/plain'默认支持,后面两种需要下面的预检请求和服务器协商。
2.协商模型/预检请求(Preflighted Request)
举例:浏览器发出PUT请求,OPTION请求返回Access-Control-Allow-Origin:*,Access-Control-Allow-Methods:'PUT',服务器同意所有域的PUT请求,浏览器收到并继续发出真正的PUT请求,服务器响应并再次返回Access-Control-Allow-Origin:*,允许浏览器的脚本执行服务器返回的数据。
response.addHeader("Access-Control-Allow-Origin","");
Access-Control-Allow-Origin:允许跨域访问的域名,如果是公共的则返回*即可
response.addHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS");
Access-Control-Allow-Methods:允许跨域访问的谓词(方法),如GET,POST,DELETE,PUT(REST)
.Net服务器一般处理程序代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace jQuery601_DotNet.Action { /// <summary> /// FindUserById 的摘要说明 /// </summary> public class FindUserById : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.Headers.Add("Access-Control-Allow-Origin","*"); context.Response.Headers.Add("Access-Control-Allow-Methods", "GET,POST"); String name = ""; int id = Convert.ToInt32(context.Request.Params["id"]); if (id == 1001) { name = "Mark"; } else if (id == 1002) { name = "Jack"; } context.Response.Write(name); } public bool IsReusable { get { return false; } } } }
客户端脚本:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>6.4.9、跨域AJAX请求</title> </head> <body> <h2>6.4.9、跨域AJAX请求</h2> <h2></h2> <button type="button">ajax请求</button> <script type="text/javascript" src="https://www.jb51.net/js/jQuery/jquery.min.js"></script> <script type="text/javascript"> $("#btnAjax").click(function() { $.get("https://localhost:12833/Action/FindUserById.ashx",{"id":1001},function(data){ log(data); },"text"); }); function log(msg) { $("#message")[0].innerHTML += msg + "<br/>"; } </script> </body> </html>
运行结果:
从上图可以看到实现跨域且为异步请求。
Java Servlet后台脚本:
package com.gomall.action; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.codehaus.jackson.map.ObjectMapper; import com.gomall.service.IProductService; import com.gomall.service.ProductService; @WebServlet("/Product") public class Product extends HttpServlet { private static final long serialVersionUID = 1L; public Product() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); String act = request.getParameter("act"); IProductService productService = new ProductService(); ObjectMapper mapper = new ObjectMapper(); PrintWriter out=response.getWriter(); if (act.equals("getAll")) { String json = mapper.writeValueAsString(productService.getAll()); out.append(json); } else if (act.equals("area")) { String callback=request.getParameter("callback"); out.append(callback+"('"+new Date()+"')"); } else if (act.equals("getJSONP")) { String callback=request.getParameter("callback"); String json = mapper.writeValueAsString(productService.getAll()); out.append(callback+"("+json+")"); } else if (act.equals("getAllCORS")) { /**向响应的头部中添加内容*/ response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET,POST"); String json = mapper.writeValueAsString(productService.getAll()); out.append(json); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
客户端代码: