$http({ method: 'POST', //withCredentials: true, //這個用來將cookie傳回服務器,可是post請求設置這個將致使error headers: { 'Content-Type': 'application/x-www-form-urlencoded',//跨站必須,不然瀏覽器自動將method改成options }, url: 'http://192.168.14.136:8888/api/v1.0/login/', data: data1, /*transformRequest: function(obj) {//這個用來把json變爲p1=v1&p2=v2這種形式 var str = []; for (var p in obj) { str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); } return str.join("&"); }*/ }).success(function(data) { alert(data); }).error(function(data) { alert(data); }); //服務器端必須返回頭以下才會success response.setHeader("Access-Control-Allow-Origin", "*");//若是要傳遞cookie這裏不能使用通配符,而是要用下面的方式 response.addHeader("Access-Control-Allow-Credentials", "true"); //接受cookie傳遞 response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); //匹配客戶端發來的Origin並返回去,這樣ajax才能success。 response.setHeader("Access-Control-Allow-Methods","POST"); response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type"); python: self.set_header("Content-Type","application/json") self.set_header("Access-Control-Allow-Origin",self.request.headers.get("Origin", "*")) self.set_header("Access-Control-Allow-Credentials","true") self.set_header("Access-Control-Allow-Methods","POST,GET,OPTIONS") self.set_header("Access-Control-Allow-Headers","x-requested-with,content-type") 注意:返回json的格式必須嚴謹,不然會ajax err
從網上下載了一個AngularJS項目,配置啓動後發現數據發送不到本身的後臺中去,老是提示跨域問題。javascript
下面是AngularJS的部分代碼:html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html ng-app=""> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Access-Control-Allow-Origin" content="*"> <title>AngularJSTest</title> </head> <body ng-controller="MyController"> <p>User</p> <p>ID</p> <input id="id" name="id" ng-model="saveUser.id"> <br> <p>Name</p> <input id="id" name="name" ng-model="saveUser.name"> <br> <p>age</p> <input id="id" name="age" ng-model="saveUser.age"> <br> <ul> <li ng-repeat="x in infos"> {{ x.ID + x.name + x.age }} </li> </ul> <button ng-click="getUser()">提交</button> <script> function MyController($scope, $http){ $scope.saveUser = { id:1, name:"John", age:"16" }; $scope.getUser = function(){ $http({ method: "POST", url: "http://localhost:8080/Spring-MVC/AngularJS/getUser.do", data: $scope.saveUser }).success(function (data){ $scope.infos = data; }) }; } </script> <script src="lib/angular/angular.js"></script> </body> </html>
注意:在$http中URL前部分爲後臺項目的路徑。前端
後臺須要本身寫一個過濾器,並配置到web.xml中去java
package com.jxq.util; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; public class RequestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse pResponse, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub HttpServletResponse response = (HttpServletResponse) pResponse; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type"); chain.doFilter(request, response); } public void destroy() { // TODO Auto-generated method stub } }
web.xml中的配置python
<filter> <filter-name>requestFilter</filter-name> <filter-class>com.jxq.util.RequestFilter</filter-class> </filter> <filter-mapping> <filter-name>requestFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
Controller的寫法:web
package com.jxq.controller.user; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.jxq.entity.user.AngularUser; import com.jxq.service.user.UserOperate; @Controller @RequestMapping(value="/AngularJS") public class UserController { @Autowired private UserOperate userOperate; @RequestMapping(value="/getUser.do", method=RequestMethod.POST) @ResponseBody public List<AngularUser> save(@RequestBody AngularUser angularUser){ System.out.println("ID:" + angularUser.getId()); System.out.println("name:" + angularUser.getName()); System.out.println("age:" + angularUser.getAge()); List<AngularUser> lists = new ArrayList<AngularUser>(); AngularUser user1 = new AngularUser(); user1.setId("001"); user1.setAge("25"); user1.setName("zhangsan"); lists.add(user1); AngularUser user2 = new AngularUser(); user2.setId("002"); user2.setAge("26"); user2.setName("lisi"); lists.add(user2); AngularUser user3 = new AngularUser(); user3.setId("003"); user3.setAge("27"); user3.setName("wangwu"); lists.add(user3); return lists; } }
必需要加上@responseBody,不然沒法返回數據給前端,稍後的博客會詳細介紹@requestBody和@responseBodyajax
下面詳細說一下AngularJS的$http請求跨域,此部分爲網上查詢獲得。spring
跨域,前端開發會常常碰見,AngularJS實現跨域方式相似於Ajax,使用的是CORS機制。json
是一種容許當前域的資源被其餘域的腳本請求訪問的機制。整個請求都是瀏覽器自動完成,不須要用戶參與,會自動添加一些附加的頭信息,有時候會多發出一次附加的請求。api
分爲兩種:簡單請求和非簡單請求。
區別在於只要知足兩類條件,就是簡單請求。
(1):請求方法是一下三種方法之一:HEAD、GET和POST
(2):請求的頭信息不超過一下幾種字段:
Accept、Accept-Language、Content-Language、Last-Event-ID和Content-Type
其中Content-Type的值:application/x-www-form-urlencoded、multipart/form-data和text/plain
凡是不知足上述兩個條件的,都是非簡單請求。瀏覽器對於這兩種請求的處理方式是不同的。
對於簡單請求,瀏覽器直接發出CORS請求,就是在頭信息中會增長一個Origin字段.
Origin字段用來講明本次請求來自哪一個源(協議+域名+端口),服務器根據這個值,決定是否贊成此次請求。
若是是不在許可範圍內,服務器會返回一根正常的HTTP迴應,可是沒有包括Access-Control-Allow-Origin字段,就知道是出錯了,從而跑出錯誤,被XMLHttpRequest的onerror回調函數捕獲。
注意:這種錯誤是沒法經過狀態碼識別,由於HTTP迴應多是200。
若是Origin制定的域名在許可範圍內,服務器返回的響應,就會多幾個頭信息字段。
紅色框括起來的,是可CORS請求想看的字段,都是以Access-Control-開頭
(1):Access-Control-Allow-Origin
該字段是必須的。它的值要麼是請求時Origin字段的值,要麼是一個*,表示接受任何域名的請求。
(2):Access-Control-Allow-Credentials
可選,是一個布爾值,表示是否容許發送Cookie,默認狀況下,Cookie不包括在CORS請求之中,設爲true,即表示服務器明確許可,Cookie能夠包含在請求中,一塊兒發送給服務器。這個值也只能設爲true。若是不須要瀏覽器發送Cookie給服務器,刪除便可。
(3):Access-Control-Expose-Headers
可選,CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其餘字段,就必須在Access-Control-Expose-Headers裏面指定。上面的例子指定,getResponseHeader('FooBar')能夠返回FooBar字段的值。
是那種對服務器有特殊要求的請求,請求方法是PUT或DELETE,或者Content-Type類型爲application/json
首先是預檢測:在正式通信以前,發送一次查詢請求,詢問是否在許可名單中以及可使用那些HTTP動詞和頭信息。只有獲得答覆,纔會正式發起請求,不然報錯。
預檢測經過以後,瀏覽器就會發送一個正常的請求。
JSONP只支持GET請求,CORS支持全部的類型的HTTP請求。JSONP的優點在於支持老式瀏覽器,以及能夠向不支持CORS的網站請求數據。
AngularJS的$http請求方式:
$http.post(url, data, [config]).success(function(){ ... }); $http.get(url, [config]).success(function(){ ... });
指定callback和回調函數名,函數名爲JSON_CALLBACK時,會調用success回調函數,JSON_CALLBACK必須全爲大寫。
$http.jsonp("http://localhost/sitesettings/getBadgeInfo.pt?jsonp=JSON_CALLBACK&siteid=137bd406").success(function(data){ ... });
前端代碼:
function getAdustryController($scope,$http){ $http.get('http://localhost/ajax/getAllIndustryCategoty.pt?languageColumn=name_eu').success(function(data){ $scope.industries = data; }); }
在服務端設置容許在其餘域名下訪問、響應類型、響應頭
response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
在服務端設置:
response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");