在實際開發中我們經常需要前后台交互,那么springmvc與ajax之間交互這里記錄下在實際開發中遇到的細節問題。
jsp頁面:
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請求如下:
<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>
tip:我們可以看到在用contentType : ‘application/json’發起請求,data我們傳的是一個json字符串,而不是json對象,一開始我也認為是可以的,結果不行,直接傳對象報錯,不妨親自試試。
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>
以上$.ajax()中 contentType : 'application/json',則data必須轉換為json對象且后台方法參數必須用model接受,否則報400錯誤,則后台接受參數為:
@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默認值。
博客原文:https://blog.csdn.net/u014079773/article/details/52984747