出自:http://www.javashuo.com/article/p-mdkqrtyw-k.htmljavascript
协议://+[用户名/密码@]+主机+公司名+机构名+:端口+/路径html
主机+公司名+机构名java
协议://+主机+公司名+机构名+:端口jquery
由于JavaScript同源策略的限制,A域名下的JavaScript没法操做B或是C域名下的对象,因此就出现跨域一词;web
同源策略:ajax
请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同。apache
因此跨域就是: 域名,端口,协议三者其一不一样;json
JSONP跨域是利用script脚本容许引用不一样域下的js实现的,将回调方法带入服务器,返回结果时回调。跨域
@WebServlet(name = "JSONPServlet", urlPatterns = "/callback") public class JSONPServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String callback = request.getParameter("callback"); System.out.println(callback); response.getWriter().write(callback+"('"+new Date().toLocaleString()+"')"); } }
<body> <h1>JSONP跨域</h1> <h2>JSONP跨域是利用script脚本容许引用不一样域下的js实现的,将回调方法带入服务器,返回结果时回调。</h2> <script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> var show = function ( data){ window.alert(data); } </script> <script type="text/javascript" src="http://localhost:8080/callback?callback=show" charset="utf-8"></script> </body>
结果:浏览器
服务器返回一段javascript,经过指定的方法名调用。从图中能够看出,使用JSONP的形式调用已经再也不是经过XMLHTTPRequest对象,而是同步调用。
@WebServlet(name = "JSONPServlet", urlPatterns = "/callback") public class JSONPServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String callback = request.getParameter("callback"); System.out.println(callback); response.getWriter().write(callback+"('"+new Date().toLocaleString()+"')"); } }
<script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> $("#cross_domain--button").click( function (){ $.get("http://localhost:8080/callback?callback=?",function(data){ alert(data) }, "jsonp") }); </script>
在jQuery中若是使用JSONP只须要将返回数据类型设置为jsonp就能够了。
总结:
一、只支持get请求,不支持post请求;
二、请求是同步的;服务器返回数据要处理,要添加回调函数。
同源策略(same origin policy)的限制下非同源的网站之间不能发送 ajax 请求的。
w3c 提出了跨源资源共享CORS即Cross Origin Resource Sharing(跨域源资源共享),就是咱们所熟知的跨域请求。
跨域资源共享(CORS)是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,容许网页从不一样的域访问其资源。
CORS与JSONP相比:
一、 JSONP只能实现GET请求,而CORS支持全部类型的HTTP请求。
二、 使用CORS,开发者可使用普通的XMLHttpRequest发起请求和得到数据,比起JSONP有更好的错误处理。
三、 JSONP主要被老的浏览器支持,它们每每不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
四、CORS 将请求分为两类:简单请求和非简单请求:
/** * 实现CORS简单跨域服务 */ @WebServlet(name = "SimpleServlet", urlPatterns = "/simple") public class SimpleServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置容许CORS的域名,若是是全部则使用* response.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8020"); response.getWriter().write("{\"name\":\"Book\"}"); } }
<html> <head> <meta charset="UTF-8"> <title>实现CORS简单跨域</title> </head> <body> <script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> $.get("http://localhost:8080/simple", function(data) { console.log(data) $("body").text(data.name) },"json"); //跨域Post请求 $.post("http://localhost:8080/simple", function(data) { console.log(data.name) }, "json"); </script> </body> </html>
结果:
简单请求的部分响应头及解释以下:
Access-Control-Allow-Origin(必含)- 不可省略,不然请求按失败处理。该项控制数据的可见范围,若是但愿数据对任何人均可见,能够填写"*"。
Access-Control-Allow-Credentials(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true(必为小写)。若是不包含cookies,请略去该项,而不是填写false。这一项与XmlHttpRequest2对象当中的withCredentials属性应保持一致,即withCredentials为true时该项也为true;withCredentials为false时,省略该项不写。反之则致使请求失败。
Access-Control-Expose-Headers(可选) – 该项肯定XmlHttpRequest2对象当中getResponseHeader()方法所能得到的额外信息。
如说你须要发送PUT、DELETE等HTTP动做,或者发送Content-Type: application/json的内容就须要使用复杂请求了。
最早发送的是一种"预请求",此时做为服务端,也须要返回"预回应"做为响应。预请求其实是对服务端的一种权限请求,只有当预请求成功返回,实际请求才开始执行。预请求以OPTIONS形式发送,当中一样包含域,而且还包含了两项CORS特有的内容。
5.2.2.一、Servlet支持CORS
@WebServlet(name = "ComplexServlet", urlPatterns = "/complex") public class ComplexServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置容许CORS的域名,若是是全部则使用* response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8020"); response.addHeader("Access-Control-Allow-Methods", "GET,HEAD,POST,TRACE,OPTIONS,PUT,DELETE"); response.addHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept"); response.addHeader("Access-Control-Allow-Credentials", "true"); response.getWriter().write("{\"name\":\"Book\"}"); } @Override protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<html> <head> <meta charset="UTF-8"> <title>实现CORS复杂跨域</title> </head> <body> <script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> $.ajax({ type:"post", url:"http://localhost:8080/complex", contentType:"application/json;charset=utf-8", dataType:"json", success:function(data){ $("body").text(data.name); } }); </script> </body> </html>
Access-Control-Allow-Origin(必含) – 和简单请求同样的,必须包含一个域,不能是*号。
Access-Control-Allow-Methods(必含) – 这是对预请求当中Access-Control-Request-Method的回复,这一回复将是一个以逗号分隔的列表。尽管客户端或许只请求某一方法,但服务端仍然能够返回全部容许的方法,以便客户端将其缓存。
Access-Control-Allow-Headers(当预请求中包含Access-Control-Request-Headers时必须包含) – 这是对预请求当中Access-Control-Request-Headers的回复,和上面同样是以逗号分隔的列表,能够返回全部支持的头部。
Access-Control-Allow-Credentials(可选) – 和简单请求当中做用相同。
Access-Control-Max-Age(可选) – 以秒为单位的缓存时间,容许时应当尽量缓存。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>CorsFilter</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> <init-param> <param-name>cors.allowed.origins</param-name> <param-value>http://127.0.0.1:8020</param-value> </init-param> <init-param> <param-name>cors.allowed.methods</param-name> <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value> </init-param> <init-param> <param-name>cors.allowed.headers</param-name> <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value> </init-param> <init-param> <param-name>cors.exposed.headers</param-name> <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value> </init-param> <init-param> <param-name>cors.support.credentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.preflight.maxage</param-name> <param-value>10</param-value> </init-param> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
@WebServlet(name = "FilterCORSServlet", urlPatterns = "/filtercors") public class FilterCORSServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet( request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("{\"name\":\"Book\"}"); } }
<script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> $.ajax({ type:"post", url:"http://localhost:8080/filtercors", contentType:"application/json;charset=utf-8", dataType:"json", success:function(data){ $("body").text(data.name); } }); </script>
结果:
方法1、若是想对一系列接口添加 CORS 配置,能够在类上添加注解,对该类声明全部接口都有效:
@Component @RequestMapping("/cors") @CrossOrigin( origins = {"http://127.0.0.1:8020"}, allowedHeaders = "*", methods = { RequestMethod.GET,RequestMethod.POST,RequestMethod.OPTIONS }, allowCredentials = "true", maxAge = 90 ) public class corsController { //跨域 CORS--复杂请求 @RequestMapping(value = "/cors01") @ResponseBody public String cors01() { return "{\"name\":\"Tom\",\"age\":999}"; } }
<script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> $.ajax({ type: "POST", url:"http://localhost:8080/cors/cors01", contentType:"application/json;charset=utf-8", dataType:"json", success:function(data){ $("body").text(data.name); } }); </script>
结果:
方法2、修改配置文件:
<!--跨域--> <mvc:cors> <mvc:mapping path="/cors/*" allowed-origins="http://127.0.0.1:8020" allowed-methods="POST,GET,OPTIONS,DELETE,PUT" allowed-headers="Content-Type,ContentType,Access-Control-Allow-Headers, Authorization, X-Requested-With" allow-credentials="true"/> </mvc:cors>
@Component @RequestMapping("/cors") public class corsController { //跨域 CORS--复杂请求 @RequestMapping(value = "/cors01") @ResponseBody public String cors01() { return "{\"name\":\"Tom\",\"age\":999}"; } }
<body> <script type="text/javascript" src="js/jquery-1.11.3.js" ></script> <script type="text/javascript"> $.ajax({ type: "POST", url:"http://localhost:8080/cors/cors01", contentType:"application/json;charset=utf-8", dataType:"json", success:function(data){ $("body").text(data.name); } }); </script> </body>