網站跨域解決方案
什麼是跨域問題
是兩個專案之間使用ajax(前端類似與後端技術httpclient)實現通訊,如果瀏覽器訪問的域名地址與ajax訪問的地址不一致的情況下,預設情況下瀏覽器會有安全機制,這個機制跨域問題,會無法獲取到返回結果
瀏覽器跨域問題產生的原因
使用ajax請求呼叫第三方介面,如果ajax訪問的介面域名或者埠號與瀏覽器訪問的域名或者埠號不一致的情況下,就會產生跨域問題。(屬於瀏覽器安全策略)跨域不屬於前端問題
一定要域名和埠號都保持一致才能訪問到
跨域時,請求可以訪問到後臺介面,但是獲取不到資料
環境搭建
新建兩個專案
maven依賴
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> </parent> <dependencies> <!-- SpringBoot 對lombok 支援 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- SpringBoot web 核心元件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <!-- SpringBoot 外部tomcat支援 --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!-- springboot-log4j --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.8.RELEASE</version> </dependency> <!-- springboot-aop 技術 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> </dependencies>
專案一:itmayiedu-web-a
配置檔案
server:
port: 9000
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
後臺
@SpringBootApplication @Controller public class AIndexController { @RequestMapping("/getAInfo") public String getBInfo() { return "aIndex"; } public static void main(String[] args) { SpringApplication.run(AIndexController.class, args); } }
頁面
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "GET",
async : false,
url : "http://b.itmayiedu.com:9001/getBInfo",
dataType : "json",
success : function(data) {
alert(data["respCode"]);
},
error : function() {
alert('fail');
}
});
});
</script>
專案二:itmayiedu-web-b
配置檔案
server:
port: 9001
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
後臺
@SpringBootApplication
@RestController
public class BIndexController {
@RequestMapping("/getBInfo")
public Map<String, Object> getBInfo(HttpServletResponse response) {
// 告訴瀏覽器允許跨域訪問,*表示所有的域名都允許的
response.setHeader("Access-Control-Allow-Origin", "*");
Map<String, Object> result = new HashMap<>();
System.out.println("這是B專案");
result.put("respCode", "200");
result.put("respMsg", "操作成功");
return result;
}
public static void main(String[] args) {
SpringApplication.run(BIndexController.class, args);
}
}
跨域問題解決方案
訪問:http://a.itmayiedu.com:9000/getAInfo
host檔案修改
127.0.0.1 a.itmayiedu.com
127.0.0.1 b.itmayiedu.com
1、使用jsonp解決跨域問題(不推薦,因為只能支援get請求,不支援post請求)
頁面程式碼修改
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://b.itmayiedu.com:9001/getBInfo",
dataType : "jsonp",
jsonp : "jsonpCallback",//服務端用於接收callback呼叫的function名的引數
success : function(data) {
alert(data["respCode"]);
},
error : function() {
alert('fail');
}
});});
</script>
後臺程式碼修改
@RequestMapping("/getBInfo")
public void getBInfo(HttpServletResponse response, String jsonpCallback) throws IOException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("respCode", "200");
jsonObject.put("respMsg", "操作成功");
PrintWriter printWriter = response.getWriter();
printWriter.write(jsonpCallback + "(" + jsonObject.toJSONString() + ")");
printWriter.close();
}
2、使用HttpClient進行轉發(不推薦,因為使用效率非常低,會發送兩次請求)
相當於傳送兩次請求,但是注意保證域名和埠號一致問題,
好處:安全,隱藏了真實呼叫地址,與Nginx反向代理非常相似
前端程式碼修改
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://a.itmayiedu.com:9000/forwardB",
dataType : "json",
success : function(data) {
alert(data["respCode"]);
},
error : function() {
alert('fail');
}
});});
</script>
後端新增
@RequestMapping("/forwardB")
@ResponseBody
public JSONObject forwardB() {
JSONObject result = HttpClientUtils.httpGet("http://b.itmayiedu.com:9001/getBInfo");
return result;
}
3、設定瀏覽器響應頭允許跨域(可以推薦)
// 告訴瀏覽器允許跨域訪問,*表示所有的域名都允許的,在公司正常程式碼放在過濾器中
response.setHeader("Access-Control-Allow-Origin", "*");
4、使用Nginx搭建API介面閘道器(強烈推薦)因為保證域名和埠都一致,使用專案區分反向代理到真實專案地址
原理:保證域名和埠號永遠是相同的,根據專案不同名稱使用Nginx進行反向代理到真實伺服器
host新增:
127.0.0.1 api.itmayiedu.com
nginx核心配置
server {
listen 80;
server_name api.itmayiedu.com;location /a {
proxy_pass http://a.itmayiedu.com:9000/;
index index.html index.htm;
}
location /b {
proxy_pass http://a.itmayiedu.com:9001/;
index index.html index.htm;
}error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
前端程式碼
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://api.itmayiedu.com/b/getBInfo",
dataType : "json",
success : function(data) {
alert(data["respCode"]);
},
error : function() {
alert('fail');
}
});});
</script>
訪問:http://api.itmayiedu.com/a/getAInfo
5、使用Zuul微服務搭建API介面閘道器(強烈推薦)SpringCloud