一、什麼是跨域
我們先回顧一下域名地址的組成:
http:// www . google : 8080 / script/jquery.js
http:// (協議號)
www (子域名)
google (主域名)
8080 (端口號)
script/jquery.js (請求的地址)
* 當協議、子域名、主域名、端口號中任意一各不相同時,都算不同的“域”。
* 不同的域之間相互請求資源,就叫“跨域”。
比如:http://www.abc.com/index.html 請求 http://www.def.com/sever.php
二、出現跨域問題的情況
由於在工作中需要使用AJAX請求其他域名下的請求,但是會出現拒絕訪問的情況,這是因爲基於安全的考慮,AJAX只能訪問本地的資源,而不能跨域訪問。
比如說你的網站域名是aaa.com,想要通過AJAX請求bbb.com域名中的內容,瀏覽器就會認爲是不安全的,所以拒絕訪問。
會出現跨域問題的幾種情況:
三、處理跨域的方法1 -- 代理
這種方式是通過後臺(ASP、PHP、JAVA、ASP.NET)獲取其他域名下的內容,然後再把獲得內容返回到前端,這樣因爲在同一個域名下,所以就不會出現跨域的問題。
比如在北京(www.beijing.com/sever.php)和上海(www.shanghai.com/sever.php)各有一個服務器,北京的後端(www.beijing.com/sever.php)直接訪問上海的服務,然後把獲取的響應值返回給前端。也就是北京的服務在後臺做了一個代理,前端只需要訪問北京的服務器也就相當與訪問了上海的服務器。這種代理屬於後臺的技術,所以不展開敘述。
四、處理跨域的方法2 -- JSONP
假設在http://www.aaa.com/index.php這個頁面中向http://www.bbb.com/getinfo.php提交GET請求,那麼我們在www.aaa.com頁面中添加如下代碼:
1
2
3
4
5
6
7
|
var eleScript=
document.createElement( "script" ); //創建一個script元素 eleScript.type
= "text/javascript" ; //聲明類型、 eleScript.src
= "http://www.bbb.com/getinfo.php" ;
//添加src屬性 引入跨域訪問的url document.getElementsByTagName( "HEAD" )[0].appendChild(eleScript); //在頁面中添加新創建的script元素 |
當GET請求從http://www.bbb.com/getinfo.php返回時,可以返回一段JavaScript代碼,這段代碼會自動執行,可以用來負責調用http://www.aaa.com/index.php頁面中的一個callback函數。看下面一個列子:
在www.aaa.com頁面中:
1
2
3
4
5
6
7
8
9
10
11
|
<script> function jsonp(
json ){ document.write(
json.name ); //輸出周星馳 } <script> <script
src= "http://www.bbb.com/getinfo.php" ></script> |
在www.bbb.com頁面中:
jsonp({ "name":"周星馳","age":45 });
也就是在www.aaa.com頁面中聲明,在www.bbb.com頁面中調用。但是JSONP只支持 “GET” 請求,但不支持 “POST” 請求。
五、處理跨域的方法3 -- XHR2(推薦方法)
“XHR2” 全稱 “XMLHttpRequest Level2” 是HTML5提供的方法,對跨域訪問提供了很好的支持,並且還有一些新的功能。
* IE10一下的版本都不支持
* 只需要在服務器端頭部加上下面兩句代碼:
header( "Access-Control-Allow-Origin:*" );
header( "Access-Control-Allow-Methods:POST,GET" );
最近開發的項目有個功能的需求如下:根據用戶提供的外部鏈接(outter_url),在頁面填寫好查詢條件(param)並向該url發起查詢請求,查詢返回的數據來動態生成html的table來顯示數據,同時要求請求的方法是post請求。
在開發過程中用的是jquery的異步請求。問題出現了,網上搜了半天沒有發現實現jquery跨域進行post請求的解決方案(貌似不支持),所以自己用java代碼來發起post跨域請求
關於實現思路的幾點說明:
1) 項目中用的是spring,所以這個請求是在spring某個controller的方法中實現的,爲了方便說明問題該方法假設爲(ajaxProxy)
2) 在jsp頁面中通過jquery的ajax方法,發起一個請求,該請求的url映射到1)中所說的那個ajaxProxy方法,並把查詢條件(param)一起傳遞到ajaxProxy方法.部分代碼如下
- $.ajax({
- type : "GET",
- //映射到controller對應方法的url
- url : "<c:url value='/user/put/queryItems'/>",
- //查詢條件數據
- data : param,
- dataType : 'json',
- success : function(data) {//動態生成table,代碼略}
3) 在ajaxProxy方法中,用HttpURLConnection鏈接outter_url,並設置connection的請求方法爲Post,併發送查詢條件(param),該部分的代碼實現如下:
- URL connect = new URL(outer_url);
- HttpURLConnection connection =(HttpURLConnection)connect.openConnection();
- Connection.setRequestMethod(“Post”);
- //發送查詢條件
- OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
- out.wirte(param);
- out.flush();
4) 接收數據並返回數據,jsp頁面中ajax的success方法處理接收到的數據data,並把data返回就可以了,接收數據的代碼如下
- StringBuffer data = new StringBuffer();
- BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "gb2312"));
- String line;
- while ((line = reader.readLine()) != null) {
- data.append(line);
- }
- return data;
綜上所述,實現跨域post請求的java實現代碼如下
- @RequestMapping("queryItems")
- public @ResponseBody
- String ajaxProxy(String name, String startTime, String endTime,
- String tag, Model m, HttpServletRequest req) throws UnsupportedEncodingException {
- //拼接查詢條件,組成json格式的數據發送
- JSONObject node = new JSONObject();
- try {
- JSONObject param = new JSONObject();
- param.put("type", "");
- param.put("typevalue", "");
- //param.put("key", name);
- param.put("key", new String(name.toString().getBytes("utf-8"), "gbk"));
- param.put("start_time", startTime);
- param.put("end_time", endTime);
- param.put("tags", tag);
- node.put("param", param);
- JSONObject user = new JSONObject();
- user.put("userid", "123");
- node.put("user", user);
- JSONObject device = new JSONObject();
- device.put("dnum", "123");
- node.put("device", device);
- JSONObject developer = new JSONObject();
- developer.put("apikey", "******");
- developer.put("secretkey", "*****");
- node.put("developer", developer);
- node.put("action", action);
- } catch (JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- // 使用POST方式向目的服務器發送請求
- URL connect;
- StringBuffer data = new StringBuffer();
- try {
- connect = new URL("outter_url");
- HttpURLConnection connection = (HttpURLConnection)connect.openConnection();
- connection.setRequestMethod("POST");
- connection.setDoOutput(true);
- OutputStreamWriter paramout = new OutputStreamWriter(
- connection.getOutputStream(),"UTF-8");
- paramout.write(json);
- paramout.flush();
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- connection.getInputStream(), "gb2312"));
- String line;
- while ((line = reader.readLine()) != null) {
- data.append(line);
- }
- paramout.close();
- reader.close();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return data.toString();
- }