springmvc与ajax交互

在实际开发中我们经常需要前后台交互,那么springmvc与ajax之间交互这里记录下在实际开发中遇到的细节问题。

jsp页面:

[html]  view plain  copy
  1. <fieldset id="login" style="width:600px; border:1px solid #000;border-left:none;border-right:none">     
  2.     <legend style="">用户登录</legend>     
  3.     <p align="center">账号:<input type="text" name="username" /></p>     
  4.     <p align="center">密码:<input type="password" name="password" /></p>     
  5.     <p align="center"><input type="submit" id="submit1" value="登录" /></p>    
  6. </fieldset>  

ajax请求如下:

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.     $(function() {  
  3.     $("#submit1").click(function() {  
  4.         var json = {  
  5.             'username':$(':input[name=username]').val(),  
  6.         'password':$(':input[name=password]').val()  
  7.         };  
  8.         //json字符串 {"username":"admin","password":"123456"}  
  9.         var postdata = JSON.stringify(json);//json对象转换json字符串  
  10.         alert(postdata);  
  11.         $.ajax({  
  12.         type : 'POST',  
  13.         contentType : 'application/json',//注意类型  
  14.         /** 
  15.                   *(默认: true) 默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串), 
  16.                   * 都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。 
  17.                   * 如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。 
  18.                  */  
  19.         processData : false,  
  20.         url : '<%=path%>/databind/requestbodybind',  
  21.         dataType : 'json',  
  22.         data : postdata,  
  23.         success : function(data) {  
  24.             alert('username : '+data.username+'\npassword : '+data.password);  
  25.         },  
  26.         error : function() {  
  27.             alert('error...');  
  28.         }  
  29.       });  
  30.        });            
  31.     });  
  32. </script>   
tip:我们可以看到在用contentType : ‘application/json’发起请求,data我们传的是一个json字符串,而不是json对象,一开始我也认为是可以的,结果不行,直接传对象报错,不妨亲自试试。

SpringMVC需要提供的方法如下:

[java]  view plain  copy
  1. @RequestMapping(value="requestbodybind", method = {RequestMethod.POST})  
  2. @ResponseBody  
  3. public Account requestBodyBind(@RequestBody Account account){  
  4.       System.out.println("requestbodybind:" + account);  
  5.       return account;  
  6. }  

那还是 contentType : ‘application/json’ 发起的请求,我们能不能用如下的方式接收值呢

[java]  view plain  copy
  1. @RequestMapping(value="json", method = {RequestMethod.POST})  
  2. @ResponseBody  
  3. public Account json(String username, String password){  
  4. Account account = new Account();  
  5. account.setUsername(username);  
  6. account.setPassword(password);  
  7. return account;  
  8. }  

答案是不可以的,会抛异常, 400 Bad Request

究其原因是:contentType : ‘application/json’数据发送后台接收必须是Modle,不能是单个属性,且必须加上@RequestBody注解。
如果我们把contentType换成默认的contentType : ‘application/x-www-form-urlencoded’呢,前后台又该怎么写?

ajax写法如下:

[javascript]  view plain  copy
  1. $(function(){  
  2.     $("#submit").click(function(){  
  3.            $.ajax({  
  4.                type: "POST",  
  5.                /* contentType : 'application/x-www-form-urlencoded',*/  
  6.                url:  '<%=path%>/databind/json',  
  7.                dataType: "json",  
  8.                data: {username:$('#username').val(),  
  9.                       password:$('#password').val()},  
  10.                success: function(data){  
  11.                     alert('username : '+data.username+'\npassword : '+data.password);  
  12.                }  
  13.            });   
  14.     });  
  15. });  

这里不得不提下,虽然data这里看起来传的是一个json对象,但由于使用了application/x-www-form-urlencoded,最终可以通过firebug可以看到,其实最终传过去的还是username=admin&password=123456,当然你也可以直接传字符串过去,但是有一点要注意,真实项目中字段还是特别多的,这样拼接会相当繁琐,然而我们知道还有个方法供我们使用, jQuery给我们提供的$(“#login”).serialize()序列化表单。

[javascript]  view plain  copy
  1. $(function(){  
  2.     $("#submit").click(function(){  
  3.            var params = $("#login").serialize();//序列化表单  
  4.            alert(params);  
  5.            $.ajax({  
  6.                type: "POST",  
  7.                url:  '<%=path%>/databind/json',  
  8.                dataType: "json",  
  9.                data: params,  
  10.                success: function(data){  
  11.                     alert('username : '+data.username+'\npassword : '+data.password);  
  12.                }  
  13.            });   
  14.     });  
  15. });  

后台接收方式如下:

[java]  view plain  copy
  1. @RequestMapping(value="json", method = {RequestMethod.POST})  
  2. @ResponseBody  
  3. public Account json(String username,String password){  
  4.     Account account = new Account();  
  5.     account.setUsername(username);  
  6.     account.setPassword(password);  
  7.     return account;  
  8. }  

那这里要提出一个疑问,如果我需要接受的字段特别多呢,难道我在方法中也需要一个一个参数的去写嘛,比如有20个,还不得累死。

答案是当然啦

[java]  view plain  copy
  1. @RequestMapping(value="/json", method = {RequestMethod.POST})  
  2. @ResponseBody  
  3. public Account json(Account account){  
  4.     System.out.println(account);  
  5.     return account;  
  6. }  

此外,这里不得不提一件事情,很多人一看到要拿model接收传参,就想着应该是不是应该加上@RequestBody注解,springmvc才会帮你把相关值封装到model里面去,我在这里告诉你,千万不要这样想,这个注解不是随便就用的,它的用途是帮你转换json->model、 xml->model,你好好的表单提交,用的contentType:application/x-www-form-urlencoded,何必画蛇添足加上这个注解呢。

总结:

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.     $(function() {  
  3.     $("#submit1").click(function() {  
  4.         var json = {  
  5.         'username':$(':input[name=username]').val(),  
  6.          'password':$(':input[name=password]').val()  
  7.         };  
  8.         //json字符串 {"username":"admin","password":"123456"}  
  9.         var postdata = JSON.stringify(json);//json对象转换json字符串  
  10.         alert(postdata);  
  11.         $.ajax({  
  12.         type : 'POST',  
  13.         contentType : 'application/json',  
  14.         /** 
  15.                   *(默认: true) 默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串), 
  16.                   * 都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。 
  17.                   * 如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。 
  18.                  */  
  19.         processData : false,  
  20.         url : '<%=path%>/databind/requestbodybind',  
  21.         dataType : 'json',  
  22.         data : postdata,  
  23.         success : function(data) {  
  24.             alert('username : '+data.username+'\npassword : '+data.password);  
  25.         },  
  26.         error : function() {  
  27.             alert('error...');  
  28.         }  
  29.          });  
  30.     });                   
  31.     });  
  32. </script>   
以上$.ajax()中 contentType : 'application/json',则data必须转换为json对象且后台方法参数必须用model接受,否则报400错误,则后台接受参数为:

[java]  view plain  copy
  1. @RequestMapping(value="requestbodybind", method = {RequestMethod.POST})  
  2. @ResponseBody  
  3. public Account requestBodyBind(@RequestBody Account account){  
  4.      System.out.println("requestbodybind:" + account);  
  5.      return account;  
  6. }  

默认$.ajax()中的contentType:'application/x-www-form-urlencoded'发送的数据格式为“xx=yy&uu=ii”data数据不是json对象,它是发送信息至服务器时内容编码类型。
如下$.ajax()没有写contentType则默认类型为'application/x-www-form-urlencoded',则data传递的参数类型为单个属性.

[javascript]  view plain  copy
  1. function initArrivePerson(divId) {  
  2.     var jqids = $("#jqid").val();//获得警情id  
  3.     $.ajax({  
  4.          type:"post",     
  5.          url:basePath + "kscj/findArrivePerson.do",  
  6.          data:{"jqid":jqids},  
  7.          dataType:"json",  
  8.          async: false,  
  9.          cache:false,  
  10.          success : function(data) {  
  11.              $("#"+divId).html("");  
  12.              var arrivePerson="";  
  13.              for (var i=0;i<data.length;i++) {  
  14.                  arrivePerson+="<span>";  
  15.                  arrivePerson+="<input type=\"checkbox\"  name=\"cjrxm\"  value=\'"+data[i].sjybh+"\'/><span>"+data[i].sjyxm+"</span>";  
  16.                  arrivePerson+="<input type=\"hidden\"  name=\"cjdbh\"  value=\'"+data[i].cjdbh+"\'/>";  
  17.                  arrivePerson+="</span>";  
  18.              }  
  19.              $("#"+divId).append(arrivePerson);   
  20.          }  
  21.     });  
  22. }  
则后台接受参数为:

[java]  view plain  copy
  1. @RequestMapping(value = "/findArrivePerson", produces = {"application/json;charset=UTF-8"})  
  2. @ResponseBody  
  3. public List<TItmpTcsDisposal> findArrivePerson(HttpServletRequest req, HttpServletResponse resp, String jqid){  
  4.     List<TItmpTcsDisposal> arriveList = titmpGpsLocateinfoService.findNoRepeat(jqid);  
  5.     return arriveList;  
  6. }  

补充:

什么时候该用@RequestParam注解,什么时候不该用

前面我们已经看到了,接受单个基本类型值的参数,只要在方法中分别写下,并且并不需要使用什么注解就能拿到传过来的值,那为什么还有@RequestParam这个注解呢,并且看到很多地方都在用。
其实呢这个注解,有它的用处,并不是一无是处,首先作为基本类型的参数,如果不使用注解,是可传可不传的如果为null并不会报错,但当你使用了@RequestParam注解,那么此时该参数就是必传的了,如果不传就会报错,然而还是可以通过配置来让其可不必传,如@RequestParam(value=”username”, required=false),此外,该注解还可以设置如果前台没有传值过来,会给一个默认值,如@RequestParam(value=”username”, defaultValue=”ruo”)。
我对该注解做的总结是:如果你某个参数不是必传的,就别用它了,如果是必传的,请一定用上它,如果必传参数可以有默认值的话,还请加上defaultValue默认值。

猜你喜欢

转载自blog.csdn.net/l18848956739/article/details/79867341