angularjs-$http.post请求传递参数,后台Controller接受不到原因
现象回显
js文件
app.controller('indexCtrl', function($scope, $state, $http) { $scope.login = function() { $http.post('authc/login', $scope.user). success(function(data) { $state.go('dashboard'); }). error(function(err) { $scope.authError = err; }); }; });
controller文件
@RequestMapping(value = "/login", method = RequestMethod.POST) public AccountPresenter login( @RequestParam(value = "account", required = true) String account, @RequestParam(value = "password", required = true) String password ) throws ApplicationRuntimeException { CxUserTable user = new CxUserTable(); try { user = loginService.login(account, password, false, false, 1); } catch (ApplicationRuntimeException e) { throw new ApplicationRuntimeException(e.getMessage()); } return user != null ? new AccountPresenter(user) : null; }
结果:
后台报错
08:32:36 [http-bio-8080-exec-10] ERROR c.c.c.u.s.ControllerExceptionHanler - 系统异常!
警告: Handler execution resulted in exception: Required String parameter 'account' is not present
分析:
原因是后台没有接收到account 参数。
jquery angularjs 请求头信息对比:
默认情况下,jQuery传输数据使用Content-Type: x-www-form-urlencodedand和类似于"foo=bar&baz=moe"的序列,
然而AngularJS,传输数据使用Content-Type: application/json和{ "foo": "bar", "baz": "moe" }这样的json序列。
AngularJS带有一些默认的请求头,Angular发出的所有请求上都会带有这些默认的请求头信息。默认请求头包括以下两个:
1.Accept:appliction/json,text/pain,/
2.X-Requested-With: XMLHttpRequest
请求头信息分析:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
B) PUT方式提交时,根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 必须;
multipart/form-data, 不能处理;
其他格式,必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;
AngularJS 转换请求和响应
对于所有通过$http服务发出的请求和收到的响应来说,AngularJS都会进行一些基本的转换,包括如下内容。
1.转换请求
如果请求的配置对象属性中包含JS对象,那么就把这个对象序列化成JSON格式。
2.转换响应
如果检测到了XSRF(Cross Site Request Forgery的缩写,意为跨站请求伪造,这是跨站脚本攻击的一种方式)前缀,则直接丢弃。如果检测到了JSON响应,则使用JSON解析器对它进行反序列化。
如果你不需要其中的某些转换,或者想自已进行转换,可以在配置项里面传入自已的函数。这些函数会获取HTTP的request/response体以及协议头信息,然后输出序列化、修改之后的版本。可以使用transformLRequest和transformResponse作为key来配置这些转换函数,而这两个函数在模块的config函数中是用$httpProvider服务来配置的。
我们什么时候需要使用这些东西呢?假设我们有一个服务,它更适合用jQuery的方式来操作。POST数据使用key1=val1&key2=val2(也就是字符串)形式来代替{key1:val1, key2:val2}JSON格式。我们可以在每个请求中来进行这种转换,也可以添加一个独立transformRequest调用,对于当前这个例子来说,我们打算添加一个通用的transformRequest,这样所有发出的请求都会进行这种从JSON到字符串的转换。下面就是实现方式:
module.config(function($httpProvider) { $httpProvider.defaults.transformRequest = function(data) { //使用jQuery的param方法把JSON数据转换成字符串形式 return $.param(data); }; });
解决方法:
第一种(推荐):
所以下把Content-Type设置成x-www-form-urlencodedand之后,还需要转换序列的格式,添加postCfg属性。
(此方法前提要引入jquery文件)
$scope.login = function() { var postCfg = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, transformRequest: function (data) { return $.param(data); } }; $http.post('authc/login', $scope.user, postCfg). success(function(data) { $state.go('dashboard'); }). error(function(err) { $scope.authError = err; }); };
第二种:
添加@ResponseBody 注解。通过body的形式解析json数据。
作用:
i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
参考:
http://blog.csdn.net/yy374864125/article/details/41113643
http://www.cfei.net/archives/24102