在实际开发中我们经常需要前后台交互,那么springmvc与ajax之间交互这里记录下在实际开发中遇到的细节问题。
jsp页面:
- <fieldset id="login" style="width:600px; border:1px solid #000;border-left:none;border-right:none">
- <legend style="">用户登录</legend>
- <p align="center">账号:<input type="text" name="username" /></p>
- <p align="center">密码:<input type="password" name="password" /></p>
- <p align="center"><input type="submit" id="submit1" value="登录" /></p>
- </fieldset>
ajax请求如下:
- <script type="text/javascript">
- $(function() {
- $("#submit1").click(function() {
- var json = {
- 'username':$(':input[name=username]').val(),
- 'password':$(':input[name=password]').val()
- };
- //json字符串 {"username":"admin","password":"123456"}
- var postdata = JSON.stringify(json);//json对象转换json字符串
- alert(postdata);
- $.ajax({
- type : 'POST',
- contentType : 'application/json',//注意类型
- /**
- *(默认: true) 默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),
- * 都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。
- * 如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
- */
- processData : false,
- url : '<%=path%>/databind/requestbodybind',
- dataType : 'json',
- data : postdata,
- success : function(data) {
- alert('username : '+data.username+'\npassword : '+data.password);
- },
- error : function() {
- alert('error...');
- }
- });
- });
- });
- </script>
SpringMVC需要提供的方法如下:
- @RequestMapping(value="requestbodybind", method = {RequestMethod.POST})
- @ResponseBody
- public Account requestBodyBind(@RequestBody Account account){
- System.out.println("requestbodybind:" + account);
- return account;
- }
那还是 contentType : ‘application/json’ 发起的请求,我们能不能用如下的方式接收值呢
- @RequestMapping(value="json", method = {RequestMethod.POST})
- @ResponseBody
- public Account json(String username, String password){
- Account account = new Account();
- account.setUsername(username);
- account.setPassword(password);
- return account;
- }
答案是不可以的,会抛异常, 400 Bad Request
究其原因是:contentType : ‘application/json’数据发送后台接收必须是Modle,不能是单个属性,且必须加上@RequestBody注解。
如果我们把contentType换成默认的contentType : ‘application/x-www-form-urlencoded’呢,前后台又该怎么写?
ajax写法如下:
- $(function(){
- $("#submit").click(function(){
- $.ajax({
- type: "POST",
- /* contentType : 'application/x-www-form-urlencoded',*/
- url: '<%=path%>/databind/json',
- dataType: "json",
- data: {username:$('#username').val(),
- password:$('#password').val()},
- success: function(data){
- alert('username : '+data.username+'\npassword : '+data.password);
- }
- });
- });
- });
这里不得不提下,虽然data这里看起来传的是一个json对象,但由于使用了application/x-www-form-urlencoded,最终可以通过firebug可以看到,其实最终传过去的还是username=admin&password=123456,当然你也可以直接传字符串过去,但是有一点要注意,真实项目中字段还是特别多的,这样拼接会相当繁琐,然而我们知道还有个方法供我们使用, jQuery给我们提供的$(“#login”).serialize()序列化表单。
- $(function(){
- $("#submit").click(function(){
- var params = $("#login").serialize();//序列化表单
- alert(params);
- $.ajax({
- type: "POST",
- url: '<%=path%>/databind/json',
- dataType: "json",
- data: params,
- success: function(data){
- alert('username : '+data.username+'\npassword : '+data.password);
- }
- });
- });
- });
后台接收方式如下:
- @RequestMapping(value="json", method = {RequestMethod.POST})
- @ResponseBody
- public Account json(String username,String password){
- Account account = new Account();
- account.setUsername(username);
- account.setPassword(password);
- return account;
- }
那这里要提出一个疑问,如果我需要接受的字段特别多呢,难道我在方法中也需要一个一个参数的去写嘛,比如有20个,还不得累死。
答案是当然啦
- @RequestMapping(value="/json", method = {RequestMethod.POST})
- @ResponseBody
- public Account json(Account account){
- System.out.println(account);
- return account;
- }
此外,这里不得不提一件事情,很多人一看到要拿model接收传参,就想着应该是不是应该加上@RequestBody注解,springmvc才会帮你把相关值封装到model里面去,我在这里告诉你,千万不要这样想,这个注解不是随便就用的,它的用途是帮你转换json->model、 xml->model,你好好的表单提交,用的contentType:application/x-www-form-urlencoded,何必画蛇添足加上这个注解呢。
总结:
- <script type="text/javascript">
- $(function() {
- $("#submit1").click(function() {
- var json = {
- 'username':$(':input[name=username]').val(),
- 'password':$(':input[name=password]').val()
- };
- //json字符串 {"username":"admin","password":"123456"}
- var postdata = JSON.stringify(json);//json对象转换json字符串
- alert(postdata);
- $.ajax({
- type : 'POST',
- contentType : 'application/json',
- /**
- *(默认: true) 默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),
- * 都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。
- * 如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
- */
- processData : false,
- url : '<%=path%>/databind/requestbodybind',
- dataType : 'json',
- data : postdata,
- success : function(data) {
- alert('username : '+data.username+'\npassword : '+data.password);
- },
- error : function() {
- alert('error...');
- }
- });
- });
- });
- </script>
- @RequestMapping(value="requestbodybind", method = {RequestMethod.POST})
- @ResponseBody
- public Account requestBodyBind(@RequestBody Account account){
- System.out.println("requestbodybind:" + account);
- return account;
- }
默认$.ajax()中的contentType:'application/x-www-form-urlencoded'发送的数据格式为“xx=yy&uu=ii”data数据不是json对象,它是发送信息至服务器时内容编码类型。
如下$.ajax()没有写contentType则默认类型为'application/x-www-form-urlencoded',则data传递的参数类型为单个属性.
- function initArrivePerson(divId) {
- var jqids = $("#jqid").val();//获得警情id
- $.ajax({
- type:"post",
- url:basePath + "kscj/findArrivePerson.do",
- data:{"jqid":jqids},
- dataType:"json",
- async: false,
- cache:false,
- success : function(data) {
- $("#"+divId).html("");
- var arrivePerson="";
- for (var i=0;i<data.length;i++) {
- arrivePerson+="<span>";
- arrivePerson+="<input type=\"checkbox\" name=\"cjrxm\" value=\'"+data[i].sjybh+"\'/><span>"+data[i].sjyxm+"</span>";
- arrivePerson+="<input type=\"hidden\" name=\"cjdbh\" value=\'"+data[i].cjdbh+"\'/>";
- arrivePerson+="</span>";
- }
- $("#"+divId).append(arrivePerson);
- }
- });
- }
- @RequestMapping(value = "/findArrivePerson", produces = {"application/json;charset=UTF-8"})
- @ResponseBody
- public List<TItmpTcsDisposal> findArrivePerson(HttpServletRequest req, HttpServletResponse resp, String jqid){
- List<TItmpTcsDisposal> arriveList = titmpGpsLocateinfoService.findNoRepeat(jqid);
- return arriveList;
- }
补充:
什么时候该用@RequestParam注解,什么时候不该用
前面我们已经看到了,接受单个基本类型值的参数,只要在方法中分别写下,并且并不需要使用什么注解就能拿到传过来的值,那为什么还有@RequestParam这个注解呢,并且看到很多地方都在用。
其实呢这个注解,有它的用处,并不是一无是处,首先作为基本类型的参数,如果不使用注解,是可传可不传的,如果为null并不会报错,但当你使用了@RequestParam注解,那么此时该参数就是必传的了,如果不传就会报错,然而还是可以通过配置来让其可不必传,如@RequestParam(value=”username”, required=false),此外,该注解还可以设置如果前台没有传值过来,会给一个默认值,如@RequestParam(value=”username”, defaultValue=”ruo”)。
我对该注解做的总结是:如果你某个参数不是必传的,就别用它了,如果是必传的,请一定用上它,如果必传参数可以有默认值的话,还请加上defaultValue默认值。