AJAX 跨域訪問是用戶訪問A網站時所產生的對B網站的跨域訪問請求均提交到A網站的指定頁面javascript
因爲安全方面的緣由, 客戶端js使用xmlhttprequest只能用來向來源網站發送請求,好比在www.readlog.cn下去請求test.readlog.cn的數據,都是不行的。html
如圖:前端
一、新建一個SpringMVC的Maven工程,參考:【Maven】Eclipse 使用Maven建立SpringMVC Web項目,pom.xml文件以下:java
1 <project xmlns="http://maven.apache.org/POM/4.0.0" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <groupId>com.test</groupId> 6 <artifactId>test-ajax-cross</artifactId> 7 <packaging>war</packaging> 8 <version>0.0.1-SNAPSHOT</version> 9 <!-- 定義maven變量 --> 10 <properties> 11 <!-- spring --> 12 <spring.version>4.2.0.RELEASE</spring.version> 13 14 <!-- log --> 15 <commons-logging.version>1.1.3</commons-logging.version> 16 17 <!-- Servlet --> 18 <servlet.version>3.0.1</servlet.version> 19 <jsp-api.version>2.2</jsp-api.version> 20 21 <!-- jstl --> 22 <jstl.version>1.2</jstl.version> 23 <standard.version>1.1.2</standard.version> 24 25 <!-- Tool --> 26 <!-- jackson json包 --> 27 <jackson-databind.version>2.9.7</jackson-databind.version> 28 <jackson-core.version>2.9.7</jackson-core.version> 29 <jackson-annotations.version>2.9.7</jackson-annotations.version> 30 31 <!-- test --> 32 <junit.version>3.8.1</junit.version> 33 34 <!-- jdk --> 35 <jdk.version>1.8</jdk.version> 36 <maven.compiler.plugin.version>2.3.2</maven.compiler.plugin.version> 37 </properties> 38 39 40 <dependencies> 41 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-core</artifactId> 45 <version>${spring.version}</version> 46 </dependency> 47 48 <dependency> 49 <groupId>org.springframework</groupId> 50 <artifactId>spring-beans</artifactId> 51 <version>${spring.version}</version> 52 </dependency> 53 54 <dependency> 55 <groupId>org.springframework</groupId> 56 <artifactId>spring-context</artifactId> 57 <version>${spring.version}</version> 58 </dependency> 59 60 <dependency> 61 <groupId>org.springframework</groupId> 62 <artifactId>spring-jdbc</artifactId> 63 <version>${spring.version}</version> 64 </dependency> 65 66 67 <dependency> 68 <groupId>org.springframework</groupId> 69 <artifactId>spring-expression</artifactId> 70 <version>${spring.version}</version> 71 </dependency> 72 73 <dependency> 74 <groupId>org.springframework</groupId> 75 <artifactId>spring-web</artifactId> 76 <version>${spring.version}</version> 77 </dependency> 78 79 <dependency> 80 <groupId>org.springframework</groupId> 81 <artifactId>spring-webmvc</artifactId> 82 <version>${spring.version}</version> 83 </dependency> 84 85 <dependency> 86 <groupId>org.springframework</groupId> 87 <artifactId>spring-tx</artifactId> 88 <version>${spring.version}</version> 89 </dependency> 90 91 92 93 94 <!-- Servlet --> 95 <dependency> 96 <groupId>javax.servlet</groupId> 97 <artifactId>javax.servlet-api</artifactId> 98 <version>${servlet.version}</version> 99 <scope>provided</scope> 100 </dependency> 101 <dependency> 102 <groupId>javax.servlet.jsp</groupId> 103 <artifactId>jsp-api</artifactId> 104 <version>${jsp-api.version}</version> 105 <scope>provided</scope> 106 </dependency> 107 108 <!-- jstl --> 109 <dependency> 110 <groupId>javax.servlet</groupId> 111 <artifactId>jstl</artifactId> 112 <version>${jstl.version}</version> 113 </dependency> 114 115 <dependency> 116 <groupId>taglibs</groupId> 117 <artifactId>standard</artifactId> 118 <version>${standard.version}</version> 119 </dependency> 120 121 122 <!-- jackson json包 --> 123 <dependency> 124 <groupId>com.fasterxml.jackson.core</groupId> 125 <artifactId>jackson-databind</artifactId> 126 <version>${jackson-databind.version}</version> 127 </dependency> 128 129 <dependency> 130 <groupId>com.fasterxml.jackson.core</groupId> 131 <artifactId>jackson-core</artifactId> 132 <version>${jackson-core.version}</version> 133 </dependency> 134 135 <dependency> 136 <groupId>com.fasterxml.jackson.core</groupId> 137 <artifactId>jackson-annotations</artifactId> 138 <version>${jackson-annotations.version}</version> 139 </dependency> 140 141 <!-- test --> 142 <dependency> 143 <groupId>junit</groupId> 144 <artifactId>junit</artifactId> 145 <version>${junit.version}</version> 146 <scope>test</scope> 147 </dependency> 148 149 </dependencies> 150 151 152 <build> 153 <plugins> 154 <!-- define the project compile level --> 155 <plugin> 156 <groupId>org.apache.maven.plugins</groupId> 157 <artifactId>maven-compiler-plugin</artifactId> 158 <version>${maven.compiler.plugin.version}</version> 159 <configuration> 160 <source>${jdk.version}</source> 161 <target>${jdk.version}</target> 162 </configuration> 163 </plugin> 164 </plugins> 165 <finalName>test-ajax-cross</finalName> 166 </build> 167 168 </project>
二、新建一個測試controller,注意返回的是一個json對象,項目中須要加入json依賴jquery
1 package com.test.ajax.cross.controller; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import javax.servlet.http.HttpServletRequest; 7 8 import org.springframework.stereotype.Controller; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.ResponseBody; 11 import org.springframework.web.servlet.ModelAndView; 12 13 @Controller 14 @RequestMapping("/test") 15 public class TestController { 16 17 @RequestMapping(value="/get") 18 @ResponseBody 19 public Map getTest(HttpServletRequest request){ 20 Map<String, Object> map = new HashMap(); 21 map.put("data", "TestController getTest()"); 22 return map; 23 } 24 }
三、新建一個測試界面webapp/static/test.htmlweb
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Insert title here</title> 6 <script src="jquery-1.11.3.min.js" type="text/javascript"></script> 7 </head> 8 <body> 9 <h2>測試界面</h2> 10 <a href="#" onclick="get()">發送get請求</a> 11 </body> 12 <script type="text/javascript"> 13 function get(){ 14 $.getJSON("http://localhost:8080/test-ajax-cross/test/get").then(function(result){ 15 console.log(result); 16 $("body").append("<br>" + JSON.stringify(result)); 17 }); 18 } 19 </script> 20 </html>
四、將項目發佈到Tomcat中,並訪問測試界面,http://localhost:8080/test-ajax-cross/static/test.htmlajax
五、修改hosts文件(用來映射域名與IP),將a.com映射到127.0.0.1,在使用地址:http://a.com:8080/test-ajax-cross/static/test.html#,訪問,能夠看到沒法完成ajax請求了spring
禁止瀏覽器檢查,啓動瀏覽器時,添加參數禁止瀏覽器對ajax作檢查chrome
windows採用如下方式打開谷歌瀏覽器express
"C:\Users\UserName\AppData\Local\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir //不知道chrome.exe 地址的話 右鍵chrome圖標-->屬性-->以下圖-->圖中 目標 就是文件的位置了,直接複製出來便可
mac採用如下方式打開谷歌瀏覽器
//chrome 瀏覽器 open -a "Google Chrome" --args --disable-web-security --user-data-dir //safari 瀏覽器 open -a '/Applications/Safari.app' --args --disable-web-security --user-data-dir
輸入地址:http://localhost:8080/test-ajax-cross/static/test.html#,進行訪問,能夠看到能正常完成ajax請求了
Jsonp(JSON with Padding) 是 json 的一種"使用模式",可讓網頁從別的域名(網站)那獲取資料,即跨域讀取數據。
JSONP的基本思想是,網頁經過添加一個<script>元素,向服務器請求JSON數據,這種作法不受同源政策限制;服務器收到請求後,將數據放在一個指定名字的回調函數裏傳回來
當經過<script>元素調用數據時,響應內容必須用javascript函數名和圓括號包裹起來。而不是發送這樣一段JSON數據,這就是JSONP中P的意義所在
在實踐中,支持JSONP的服務不會強制指定客戶端必須實現的回調函數名稱,好比handleResponse。相反,它們使用査詢參數的值,容許客戶端指定一個函數名,而後使用函數名去填充響應。許多支持JSONP的服務都能分辨出這個參數名。另外一個常見的參數名稱是callback,爲了讓使用到的服務支持相似特殊的需求,就須要在代碼上作一些修改了
JSONP由兩部分組成:回調函數和數據。回調函數是當響應到來時應該在頁面中調用的函數。回調函數的名字通常是在請求中指定的。而數據就是傳入回調函數中的JSON數據
一、修改Java後臺TestController類,增長jsonp的響應返回
1 package com.test.ajax.cross.controller; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import javax.servlet.http.HttpServletRequest; 7 8 import org.springframework.stereotype.Controller; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.ResponseBody; 11 import org.springframework.web.servlet.ModelAndView; 12 13 import com.fasterxml.jackson.core.JsonProcessingException; 14 import com.fasterxml.jackson.databind.ObjectMapper; 15 16 @Controller 17 @RequestMapping("/test") 18 public class TestController { 19 20 private ObjectMapper objectMapper = new ObjectMapper(); 21 22 @RequestMapping(value="/get") 23 @ResponseBody 24 public Map getTest(HttpServletRequest request){ 25 Map<String, Object> map = new HashMap(); 26 map.put("data", "TestController getTest()"); 27 return map; 28 } 29 30 @RequestMapping(value="/getJsonp") 31 @ResponseBody 32 public String getJsonp(HttpServletRequest request) throws JsonProcessingException{ 33 // 與前端約定好回調方法名稱,默認是callback 34 String callback = request.getParameter("callback"); 35 Map<String, Object> map = new HashMap(); 36 map.put("data", "TestController getTest()"); 37 String ret = callback+"("+ objectMapper.writeValueAsString(map)+")"; 38 return ret; 39 } 40 }
二、新建一個測試界面webapp/static/test2.html,用於jsonp請求,
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Insert title here</title> 6 <script src="jquery-1.11.3.min.js" type="text/javascript"></script> 7 </head> 8 <body> 9 <h2>測試jsonp界面</h2> 10 <a href="#" onclick="get()">發送get請求</a> 11 </body> 12 <script type="text/javascript"> 13 function get(){ 14 15 $.ajax({ 16 url: "http://localhost:8080/test-ajax-cross/test/getJsonp", 17 dataType: "jsonp", 18 jsonp:"callback", // 默認值是callback,能夠修改 19 success: function (result) { 20 console.log(result); 21 $("body").append("<br>" + JSON.stringify(result)); 22 } 23 }); 24 } 25 </script> 26 </html>
三、瀏覽器中輸入地址:http://a.com:8080/test-ajax-cross/static/test2.html#,進行訪問
觀察:使用F12查看請求
參數callback對應的值是,請求響應後的回調方法
參數_做用,值是隨機數,爲了是請求不使用緩存
返回內容是:jQuery111306019926935268467_1567783875359({"data":"TestController getTest()"})
注意:JSONP的弊端