<p>跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题。</p><p><strong>跨域问题怎么解决?</strong></p><p>1、响应头添加Header允许访问</p><p>2、jsonp 只支持get请求不支持post请求</p><p>3、httpClient内部转发</p><p>4、使用接口网关——nginx、springcloud zuul (互联网公司常规解决方案)</p><p><strong>解决方式一:响应头添加Header允许访问</strong></p><p>跨域资源共享(CORS)Cross-Origin Resource Sharing这个跨域访问的解决方案的安全基础是基于"JavaScript无法控制该HTTP头"它需要通过目标域返回的HTTP头来授权是否允许跨域访问。</p><pre class="brush:js;toolbar:false">response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问 response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式</pre><p><strong>解决方式二:jsonp 只支持get请求不支持post请求</strong></p><p>用法:</p><p>①dataType改为jsonp </p><p>②jsonp : "jsonpCallback"————发送到后端实际为https://panxu.net/?a/FromServlet?userName=644064&jsonpCallback=jQueryxxx </p><p>③后端获取get请求中的jsonpCallback </p><p>④构造回调结构</p><pre class="brush:js;toolbar:false">$.ajax({ type : "GET", async : false, url : "https://panxu.net?a/FromServlet?userName=644064", dataType : "jsonp",//数据类型为jsonp jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数 success : function(data) { alert(data["userName"]); }, error : function() { alert('fail'); } }); String jsonpCallback = request.getParameter("jsonpCallback"); //构造回调函数格式jsonpCallback(数据) resp.getWriter().println(jsonpCallback+"("+jsonObject.toJSONString()+")");</pre><p><strong>解决方式三:httpClient内部转发</strong></p><p>实现原理很简单,若想在B站点中通过Ajax访问A站点获取结果,固然有ajax跨域问题,但在B站点中访问B站点获取结果,不存在跨域问题,这种方式实际上是在B站点中ajax请求访问B站点的HttpClient,再通过HttpClient转发请求获取A站点的数据结果。但这种方式产生了两次请求,效率低,但内部请求,抓包工具无法分析,安全。</p><pre class="brush:java;toolbar:false;">$.ajax({ type : "GET", async : false, url : "https://panxu.net:8080/B/FromAjaxservlet?userName=644064", dataType : "json", success : function(data) { alert(data["userName"]); }, error : function() { alert('fail'); } }); @WebServlet("/FromAjaxservlet") public class FromAjaxservlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { //创建默认连接 CloseableHttpClient httpClient = HttpClients.createDefault(); //创建HttpGet对象,处理get请求,转发到A站点 HttpGet httpGet = new HttpGet("https://panxu.net:8080/A/FromServlet?userName="+req.getParameter("userName")); //执行 CloseableHttpResponse response = httpClient.execute(httpGet); int code = response.getStatusLine().getStatusCode(); //获取状态 System.out.println("http请求结果为:"+code); if(code == 200){ //获取A站点返回的结果 String result = EntityUtils.toString(response.getEntity()); System.out.println(result); //把结果返回给B站点 resp.getWriter().print(result); } response.close(); httpClient.close(); } catch (Exception e) { } } }</pre><p><strong>解决方式四:使用nginx搭建企业级接口网关方式</strong></p><p>www.a.a.com不能直接请求www.b.b.com的内容,可以通过nginx,根据同域名,但项目名不同进行区分。什么意思呢?这么说可能有点抽象。假设我们公司域名叫panxu.net</p><p>当我们需要访问www.a.a.com通过panxu.net/A访问,并通过nginx转发到www.a.a.com</p><p>当我们需要访问www.b.b.com通过panxu.net/B访问,并通过nginx转发到www.a.a.com</p><p>我们访问公司的域名时,是"同源"的,只是项目名不同,此时项目名的作用只是为了区分,方便转发。如果你还不理解的话,先看看我是怎么进行配置的:</p><pre class="brush:bash;toolbar:false">server { listen 80; server_name www.nginxtest.com; location /A { proxy_pass http://a.a.com:81; index index.html index.htm; } location /B { proxy_pass http://b.b.com:81; index index.html index.htm; } }</pre><p>我们访问以panxu.net开头且端口为80的网址,nginx将会进行拦截匹配,若项目名为A,则分发到a.a.com:81。实际上就是通过"同源"的域名,不同的项目名进行区分,通过nginx拦截匹配,转发到对应的网址。整个过程,两次请求,第一次请求nginx服务器,第二次nginx服务器通过拦截匹配分发到对应的网址。</p><p>以上就是关于“Ajax跨域的解决方案”的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流。</p>