Ajax跨域问题
来源:互联网 发布:优酷淘宝搞笑视频 编辑:程序博客网 时间:2024/05/18 00:21
场景:我们想订阅新浪博客,如下图:
此时我们使用java代码,对订阅地址发出Ajax请求。
代码演示Ajax跨域请求:
rss.jsp
<%-- Created by IntelliJ IDEA. User: John Date: 2017/7/20 Time: 22:27 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><link><meta> <meta charset="utf-8"> <title>Ajax跨域</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"></head><body> <div class="container"> <div class="page-header"> <h3>RSS</h3> </div> <input type="text" id="url" class="col-xs-5"> <button id="loadBtn">Load</button> <ul class="list-unstyled" id="list"> </ul> </div> <script> (function(){ function createXmlHttp(){ var xmlHttp = null; if(window.ActiveXObject){ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); }else{ xmlHttp = new XMLHttpRequest(); } return xmlHttp; } document.querySelector("#loadBtn").onclick = function(){ //document.querySelector("list").innerHTML = ""; var url = document.querySelector("#url").value; var xmlHttp = createXmlHttp(); xmlHttp.open("get",url,true); xmlHttp.send(); } })(); </script></body></html>
JS同源策略,为了安全考虑,不能跨域名访问。
解决方案
一.使用代理模式
使用第三方组件Apache HttpComponenets
HttpClient的测试代码
package com.wh.test;import org.apache.commons.io.IOUtils;import org.apache.http.HttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.junit.Test;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;/** * Created by John on 2017/7/20. */public class HttpClientTest{ @Test public void testDownloadImage() throws IOException { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet("http://ww4.sinaimg.cn/mw690/6f055540gw1eqw4zp7hsgj21kw2dcqv5.jpg"); HttpResponse httpResponse = httpClient.execute(httpGet); //获取HTTP请求的相应码 int httpCode = httpResponse.getStatusLine().getStatusCode(); if(httpCode == 200) { //获取图片的字节流 InputStream inputStream = httpResponse.getEntity().getContent(); FileOutputStream outputStream = new FileOutputStream("D:/xiaoqingxin.jpg"); IOUtils.copy(inputStream,outputStream); outputStream.flush(); outputStream.close(); inputStream.close(); } else { System.out.println("请求异常:" + httpCode); } httpClient.close(); } @Test public void testGetRequest() throws IOException { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet("http://blog.sina.com.cn/rss/1220218113.xml"); HttpResponse httpResponse = httpClient.execute(httpGet); //获取HTTP请求的相应码 int httpCode = httpResponse.getStatusLine().getStatusCode(); if(httpCode == 200) { //获取网页的字符流 InputStream inputStream = httpResponse.getEntity().getContent(); String html = IOUtils.toString(inputStream); //将inputstream转换为字符串 System.out.println(html); } else { System.out.println("请求异常:" + httpCode); } httpClient.close(); } }
HttpClient操作工具类
package com.wh.util;import org.apache.commons.io.IOUtils;import org.apache.http.HttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;public class HttpUtil { public static String getRequestText(String url) { CloseableHttpClient httpClient = HttpClients.createDefault(); try { HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(httpGet); //获取HTTP请求的相应码 int httpCode = httpResponse.getStatusLine().getStatusCode(); if(httpCode == 200) { //获取网页的字符流 InputStream inputStream = httpResponse.getEntity().getContent(); String html = IOUtils.toString(inputStream); //将inputstream转换为字符串 return html; } else { throw new RuntimeException("请求服务器异常:" + httpCode); } } catch (IOException e) { throw new RuntimeException(e); } finally { try { httpClient.close(); } catch (IOException e) { throw new RuntimeException(e); } } } public static void getRequestStream(String url,String savePath) { CloseableHttpClient httpClient = HttpClients.createDefault(); try { HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(httpGet); //获取HTTP请求的相应码 int httpCode = httpResponse.getStatusLine().getStatusCode(); if(httpCode == 200) { //获取图片的字节流 InputStream inputStream = httpResponse.getEntity().getContent(); FileOutputStream outputStream = new FileOutputStream(savePath); IOUtils.copy(inputStream,outputStream); outputStream.flush(); outputStream.close(); inputStream.close(); } else { throw new RuntimeException("请求服务器异常:" + httpCode); } httpClient.close(); } catch (IOException e) { throw new RuntimeException(e); } finally { try { httpClient.close(); } catch (IOException e) { throw new RuntimeException(e); } } }}
使用代理模式后:
rss.jsp
<%-- Created by IntelliJ IDEA. User: John Date: 2017/7/20 Time: 22:27 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><link><meta> <meta charset="utf-8"> <title>Ajax跨域</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"></head><body> <div class="container"> <div class="page-header"> <h3>RSS</h3> </div> <input type="text" id="url" class="col-xs-5"> <button id="loadBtn">Load</button> <ul class="list-unstyled" id="list"> </ul> </div> <script> (function(){ function createXmlHttp(){ var xmlHttp = null; if(window.ActiveXObject){ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); }else{ xmlHttp = new XMLHttpRequest(); } return xmlHttp; } function createLi(link,title){ var li = document.createElement("li"); var a = document.createElement("a"); var text = document.createTextNode(title); a.setAttribute("href",link); a.setAttribute("target","_blank"); a.appendChild(text); li.appendChild(a); document.querySelector("#list").appendChild(li); } document.querySelector("#loadBtn").onclick = function(){ //document.querySelector("list").innerHTML = " "; var url = document.querySelector("#url").value; var xmlHttp = createXmlHttp(); xmlHttp.open("get","/load?url="+url,true); xmlHttp.onreadystatechange = function(){ if(xmlHttp.readyState == 4){ if(xmlHttp.status == 200){ var xmlDoc = xmlHttp.responseXML; var itemArray = xmlDoc.getElementsByTagName("item"); for(var i = 0;i < itemArray.length;i++){ var item = itemArray[i]; var title = item.getElementsByTagName("title")[0].childNodes[0].nodeValue; var link = item.getElementsByTagName("link")[0].childNodes[0].nodeValue; createLi(link,title); } } } }; xmlHttp.send(); } })(); </script></body></html>
后端servlet代理跨域访问
package com.wh.web;import com.wh.util.HttpUtil;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 java.io.IOException;import java.io.PrintWriter;/** * Created by John on 2017/7/20. * Ajax跨域请求代理Servlet */@WebServlet("/load")public class LoadServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String url = req.getParameter("url");//"http://blog.sina.com.cn/rss/1220218113.xml" String xml = HttpUtil.getRequestText(url); resp.setContentType("text/xml;charset=UTF-8"); PrintWriter writer = resp.getWriter(); writer.print(xml); writer.flush(); writer.close(); }}
场景2:电子词典(使用有道翻译API接口)
dict.jsp
<%-- Created by IntelliJ IDEA. User: John Date: 2017/7/21 Time: 22:11 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"></head><body> <div class="container"> <div class="page-header"> <h3>电子词典</h3> </div> <div class="form-group"> <input type="text" id="keyword" class="form-control" placeholder="请输入要查询的单词"> </div> </div> <p id="result"></p> <script> (function(){ function createXmlHttp() { var xmlHttp = null; if(window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else { xmlHttp = new XMLHttpRequest(); } return xmlHttp; } document.querySelector("#keyword").onkeyup = function(event){ if(13 == event.keyCode){ var keyword = this.value; var xmlHttp = createXmlHttp(); xmlHttp.open("get","/dict?q=" + encodeURIComponent(keyword),true); xmlHttp.onreadystatechange = function(){ if(xmlHttp.readyState == 4){ if(xmlHttp.status == 200){ var xmlDoc = xmlHttp.responseXML; var basic = xmlDoc.getElementsByTagName("basic")[0]; var explains = basic.getElementsByTagName("explains")[0]; var ex = explains.getElementsByTagName("ex")[0].childNodes[0].nodeValue; document.querySelector("#result").innerText = ex; } } }; xmlHttp.send(); } } })(); </script></body></html>
package com.wh.web;import com.wh.util.HttpUtil;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 java.io.IOException;import java.io.PrintWriter;/** * Created by John on 2017/7/21. */@WebServlet("/dict")public class DictServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String keyword = req.getParameter("q"); keyword = new String(keyword.getBytes("ISO8859-1"),"UTF-8"); String url = "http://fanyi.youdao.com/openapi.do?keyfrom=kaishengit&key=1587754017&type=data&doctype=xml&version=1.1&q=" + keyword; String xml = HttpUtil.getRequestText(url); resp.setContentType("text/xml;charset=UTF-8"); PrintWriter writer = resp.getWriter(); writer.print(xml); writer.flush(); writer.close(); }}
二.使用JSONP
JSONP(JSON with Padding),用来解决跨域问题的另一种解决方案,需要服务器端的支持。
JS中邪恶的eval()函数
jsonp.jsp
<%-- Created by IntelliJ IDEA. User: John Date: 2017/7/24 Time: 22:26 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <meta charset="UTF-8"> <title>Document</title></head><body><script src="/static/js/jquery-1.11.3.min.js"></script><button id="btn">翻译</button><script> $("#btn").click(function(){ $.get("/jsonp",{"callback":"handler"}, function (data) { eval(data);//此处,eval()会执行括号里的代表回调函数的参数字符串,即自动执行handler(data) }); }); function handler(data){ console.log("callback:" + data.id + "->" + data.name + "->" + data.address + "->" + data.score); }</script></body></html>
引申:JQuery对JSONP的支持
$("#btn").click(function(){$.getJSON("/jsonp?callback=?",function(data){alert(data.name);});});
JQuery会自动将callback后面的问号替换成生成的函数名称
服务端的支持
JsonpServlet.java
package com.wh.web;import com.google.gson.Gson;import com.wh.DTO.User;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 java.io.IOException;import java.io.PrintWriter;/** * Created by John on 2017/7/24. */@WebServlet("/jsonp")public class JsonpServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //String callback = req.getParameter("callback"); //服务端约定回调函数名为handler User user = new User(1,"lisi","China",77F); String data = new Gson().toJson(user); PrintWriter writer = resp.getWriter(); writer.print("handler(" + data + ")"); //writer.print(callback + "(" + data + ")"); writer.flush(); writer.close(); }}
使用JSONP直接在jsp中跨域访问有道翻译API
原理:JSONP(JSONWithPadding),就是打包在函数调用中的的JSON(或者包裹的JSON)。JSON是一种数据格式,JSONP是一种数据调用方式。//JSON{“name”:“sb”}//JSONPcallback({“name”:“sb”})出于安全考虑,脚本(AJAX)不能访问非本域的内容。但是,静态资源是不受域策略限制的,可以加载任意域的脚本、样式、图片等静态资源,JSOP就是利用这种原理来实现跨域获取数据的。
<%-- Created by IntelliJ IDEA. User: John Date: 2017/7/24 Time: 22:26 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <meta charset="UTF-8"> <title>Document</title></head><body><script src="/static/js/jquery-1.11.3.min.js"></script><input type="text" id="keyword"><button id="btn">翻译</button><p id="result"></p><script> $(function(){ //使用JSOP进行跨域访问(有道词典API接口) $("#btn").click(function(){ var url = "http://fanyi.youdao.com/openapi.do?keyfrom=kaishengit&key=1587754017&type=data&doctype=jsonp&callback=?&version=1.1"; var keyword = $("#keyword").val(); console.log(typeof keyword);//string keyword = keyword === undefined || keyword == ""? "undefined":keyword //jQuery中JSONP的两种实现方式 //第一种方式 /* $.ajax({ type:"get", url: url, dataType:"jsonp", jsonp:"callallback",//指定回调函数,名字可以随意取,但必须与下一行的Get参数一致 data:"q="+ keyword, success: function (json) { var array = json.basic.explains; var str = ""; for(var i = 0;i < array.length;i++){ str += array[i] + "</br>"; } $("#result").html(str); } });*/ //第二种方式 $.getJSON(url,{"q":keyword},function(json){ var array = json.basic.explains; var str = ""; for(var i = 0;i < array.length;i++){ str += array[i] + "</br>"; } $("#result").html(str); }); }); /* $.getJSON("/jsonp?callback=?",function(result){ console.log("name:" + result.name); }); $("#btn").click(function(){ $.get("/jsonp",{"callback":"handler"}, function (data) { eval(data);//此处,eval()会执行括号里的代表回调函数的参数字符串,即自动执行handler(data) }); }); function handler(data){ console.log("callback:" + data.id + "->" + data.name + "->" + data.address + "->" + data.score); }*/ });</script></body></html>
阅读全文
1 0
- ajax跨域问题
- AJAX跨域问题
- ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- ajax 跨域问题
- ajax跨域问题。
- ajax跨域问题
- Ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- Ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- ajax跨域问题
- dialog工具类 强大!!!
- python你想知道的都在这里 python资源大全中文版
- 【转载】别人是怎么破解你们家无线密码的
- linux 文件系统管理
- 青蛙跳台阶衍生之变态跳台阶(递归,思路分析及代码实现)
- Ajax跨域问题
- shell的$()与``
- 树分治总结
- 刷题——质数因子
- 有关jQueryEasyUI的form的submit()方法的小问题
- C++程序员学Java系列之二三:匿名对象
- 开篇
- Ubuntu16.04+Windows10双系统 显示正确时间
- Fidder抓包