SpringMVC系列之參數傳遞【前後端參數傳遞的方式詳解】

· spring mvc參數傳遞的方式有哪些?

一、前端向後臺傳遞參數的方式:

  1. 通過 Servlet api 中的 HttpServletRequest對象
  2. 基本數據類型 + String類型
  3. Array 數組
  4. Java Bean 對象
  5. List 集合
  6. Map 集合
  7. JSON 格式

二、後臺向前端通過request域傳遞值的方式:

  1. Servlet api 中的 HttpServletRequest對象
  2. ModelAndView 對象
  3. ModelMap 對象
  4. Model 對象
  5. Map 集合

· spring mvc參數傳遞方式的具體代碼實現?

以下代碼,只給出前端頁面和後端SpringMVC中Controller的具體代碼實現。基本的SpringMVC配置可以另外查看專門講解 SpringMVC配置文件 書寫的文章。

一、前端向後臺傳遞參數的方式

1.通過 Servlet api 中的 HttpServletRequest對象

這種方式想必是學習了Java Web之後,最熟悉的一種獲取前端頁面傳遞參數的方式。直接在服務器端,使用對HttpServletRequest對象進行操作即可。我們曾幾何時,都是這樣乾的String name = request.getParameter("name");通過request對象的getParameter()方法直接獲取指定的key屬性名,即可獲取到對應的value屬性值,然後賦值給了name變量。

在SpringMVC的Controller中,這種傳統方式也是存在的。具體代碼如下:

	import org.springframework.stereotype.Controller;
	import javax.servlet.http.HttpServletRequest;
	
	@Controller
	@RequestMapping("/param")
	public class ParamController{
	
		@RequestMapping("/servlet")
	    public String servlet(HttpServletRequest request){
	        String name = request.getParameter("name");
	        System.out.println("name:" + name);
	        request.setAttribute("result", "hello " + name);
	        return "hello";
	    }
	  
    }

這種方式需要注意的點,無非就是在Controller具體的請求處理方法中,需要傳入一個HttpServletRequest對象,來作爲當前方法的形參,然後就可以在此方法中,使用這個request對象了,這個對象跟之前傳統的方法中的request對象是一致的。通過它,可以獲取到很多的內容,getSession(),getHeader(),getAttribute()等等。

在前端頁面中,訪問的時候,只需要指定url的路徑,然後利用key=value的形式訪問即可。無需書寫其他的代碼,例如:

http://localhost:8080/param/servlet?name=golden3young

這樣,後端接收到name參數的之後,使用System.out.println("name:" + name);即可將值打印到控制檯上。至於最後兩行的代碼,是解析視圖的內容,後續進行講解,這裏不做展開。

2. 基本數據類型 + String類型

所謂基本數據類型和String類型傳值,是什麼意思呢?其實就是,我們可以在SpringMVC的Controller中具體請求處理方法中,直接使用基本數據類型或者String類型的參數進行對映,只要前端頁面和方法中指定的參數名稱是完全一致的,這裏包括大小寫,那麼前端這個參數名稱所賦有的值,就會傳遞到後臺的請求處理方法中。其實這其中,是SpringMVC底層的攔截器幫我們實現的,它會將請求中傳來的所有參數,跟我們所定義的請求處理方法中的參數進行對比,如果發現是一模一樣的,它就會從請求中把那個參數的值拿出來賦給我們處理方法中的那個變量,於是,我們就可以直接使用了。當然,這個轉換的過程比較複雜,也同樣存在一些問題,稍後會告訴大家。

SpringMVC的Controller中,具體的請求處理方法:

	@RequestMapping("/simple")
    public String simple(int id, String name, ModelMap modelMap){
        System.out.println("id:" + id);
        System.out.println("name:" + name);
        modelMap.addAttribute("result", "Hello " + name + "," + id);
        return "hello";
    }

爲了講解的清晰,我將Controller類聲明和導包的代碼都省略了,只給出核心的請求處理方法的代碼。
這裏,我們可以看出,Controller中定義了,請求路徑爲/simple的請求,將直接執行simple()這個方法,而這個方法,我們給了3個形參,id,name,modelMap,這裏,我們只關注int id, String name 即可,這兩個參數的類型一個是int,屬於基本數據類型之一;另一個是String字符串類型。那麼這麼寫的意義是什麼呢?其實就是前端頁面在傳遞值的時候,如果有參數名爲id或者name的屬性,則會直接將屬性的值賦給這兩個變量。

前端頁面,在訪問時,只需要給出指定的url和傳遞指定名稱的參數即可,例如:

http://localhost:8080/param/simple?id=1&name=golden3young

通過上面的url,可以看出,請求直接奔向/param/simple,而對應的方法恰好就是simple()方法,同時前端請求通過key=value的格式傳遞了兩個參數,id 和 name, 而我們的simple()方法中,恰好就有同名的id 和 name,那麼我們simple()方法中的id和name將獲得前端請求傳來的值,1 和 golden3young。同時,它們的類型,也會被轉變成方法中定義的int和String類型。

有的同學可能發現了,前端請求在傳遞過程中,明明都是通過字符串格式傳遞的,而爲什麼到了Controller的simple()方法中,就變成了int和String類型?是怎麼轉換的?其實,這就是SpringMVC的過濾器爲我們做的事情。它不光接收映射同名的參數,而且還會將類型幫助我們轉換成功。但是,類型的轉換,存在着問題,比如:int類型是整數類型,剛纔傳來的參數id就是int類型,而值恰好是1,則不會出現問題,可是如果將值改成abc等非數字的內容呢?那肯定是會報錯的,因爲數字格式異常,無法進行轉換。同時,還有傳遞的時候忘記傳遞id屬性而只傳了name屬性,或者id屬性只給了key,而沒有value值,這些情況,都會導致錯誤的出現。

羅列一下幾種錯誤:

http://localhost:8080/param/simple?id=&name=golden3young

此時,id爲空字符串,那麼SpringMVC底層在爲我們轉換的時候,是將空串轉成int類型,那肯定是會報錯的。頁面報錯400.

http://localhost:8080/param/simple?name=golden3young

此時,我們沒有傳遞id這個屬性,那麼SpringMVC底層在匹配的時候,一旦沒有找到前端傳來的屬性,那麼就會直接給Controller的方法中的參數賦值成null,那麼把null轉成int類型,同樣也是會報錯的。頁面報錯500.

那像以上幾種情況,都需要大家在前端參數傳遞的時候,注意不要遺漏並且給出正確類型的數值。這裏加一個小的拓展。有些情況,我們可能無法斷定前端一定會傳過來某一個屬性,有可能不傳,那這種情況,我們可以進行規範。使用的註解是@RequestParam,後續會介紹。

3. Array 數組

這種方式,簡單來說,就是在前端頁面通過發送數組格式的數據,後臺Controller的處理方法中,在接收參數的時候,直接轉換成數組格式。跟 基本數據類型和String類型的 思想是一樣的,但是轉換的類型是不同的。
那這種方式,我們在前端頁面中,經常用到的地方,其實就是form表單中的多選框,因爲多選框的name都是一樣的,但是值有多個,傳遞到後端頁面後,傳統方式是進行截取,而現在SpringMVC可以幫助我們完成底層的工作,直接給我們一個array數組。

前端頁面代碼:

<form action="${pageContext.request.contextPath}/param/array" method="post">
     愛好:
     <input type="checkbox" name="hobby" value="唱歌" />唱歌
     <input type="checkbox" name="hobby" value="跳舞" />跳舞
     <input type="checkbox" name="hobby" value="書法" />書法
     <input type="checkbox" name="hobby" value="滑雪" />滑雪
     <br>
     <input type="submit" value="提交" />
</form>

Controller中的處理方法:

	@PostMapping("/array")
    public String array(String[] hobby, Map<String, String> map){
       for(String hobbyStr : hobby){
           System.out.println(hobbyStr);
       }

       //使用 java.util.Map 向request域傳值 【本例不必關注】
       map.put("result","測試數組傳參");
       return "hello";
    }

通過前後端代碼的比對,相信大家不難看出,前端參數的name爲hobby,value的值爲多個不同的值,而後端Controller中的方法中,指定了同名hobby的一個String數組類型的參數,於是乎,SpringMVC底層,就把從前端傳遞過來的多個hobby的值,以數組的格式存放到了hobby數組中。我們使用了for循環進行了遍歷打印。 後兩行的代碼同樣無需關注。

4. Java Bean對象

通過上面3種方式的介紹,大家其實也能感覺出來,SpringMVC大大簡化了我們將請求中的參數進行轉換的這樣一個過程,我們只需要吃現成的即可。那麼同樣有這樣一個問題,如果前端頁面一次性要傳遞多個參數,比如十個以上,包括:id,age,name,birthday,gender,school,city,province,area,salary,married等等參數,如果按照上面學過的方法,我們需要把這所有的參數都寫在執行方法的形參位置處即可。如:

	@RequestMapping("/bean")
    public String testBean(int id, int age, String name, String birthday, String school,
    String city, String area, double salary, boolean married){
       .....
    }

放眼望去,可以說是非常長,寫起來同樣也是非常麻煩,如果執行方法不光這一個,還有多個,都需要接收這些參數,那我們寫起來就會浪費大量的無用功的時間。這時,我們就用到面向對象的編程思想,也就是創建一個對象,讓這些參數都成爲這個對象的屬性,然後,SpringMVC就會將前端傳來的這些參數的名稱與我們指定的對象(Java Bean)的屬性進行名稱的對比,如果一致,那麼就進行賦值,於是乎,我們先創建一個對象,用來存放所有的參數:

@Data
public class User{
	private int id;
	private int age;
	private String name;
	private String birthday;
	private String school;
	private String city;
	private String area;
	private double salary
	private boolean married;
}

那麼這樣,Controller中處理方法的代碼就簡化成了這樣:

	@RequestMapping("/bean")
    public String testBean(User user){
       .....
    }

然後,我們只需要在方法中,調用user.getter方法,來獲取所有的屬性值或者說參數值。
當然,這裏有的同學可能會問,那底層是怎麼實現的呢?SpringMVC底層其實還是將請求中的參數剝離出來,然後調用我們指定的這個對象(Java Bean)的setter方法來爲同名的屬性進行賦值,當我們用的時候,直接使用getter方法來用。有同學會問,那你剛纔寫的User類中沒有寫getter和setter啊,其實這裏,我偷了個懶,使用的是lombok插件,它會自動爲我們生成getter和setter,有興趣的同學,可以自己學一下,非常簡單。

那前端頁面在傳參的時候,還是保證訪問指定的url,然後傳遞同名的參數即可,沒有其他的變化,例如:

http://localhost:8080/param/bean?id=1&name=golden3young&age=18&married=false

根據我上面的url請求來看,後端springMVC在接收值的時候,只能映射到id,name,age,married這4個參數的值給User對象的同名屬性,而其他的屬性由於我沒有傳值,所以都會保持初始默認值,那這個默認值,就是Java基礎部門的內容了,也就是所有Java類型的默認值。

5. List集合

以List集合參數類型接收前端傳來的參數,其實就是將前端傳來的參數在後端Controller中自動進行類型的轉換,轉換成Java中的List集合類型來存儲前端傳來的參數。想要springmvc自動將接收的參數轉換成List集合類型,有兩種方法:

  1. 將List集合定義在Java Bean中
  2. 接收JSON格式數組
-1- 將List集合定義在Java Bean中

這種方式比較簡單直接,需要先創建一個Bean對象,然後將我們需要接收的參數定義成這個Bean對象的一個屬性,這裏要求參數的name需要與屬性名完全一致,這樣springmvc底層就可以自動的將名稱相同的參數和bean中對象的屬性進行映射賦值,我們只需要使用即可。

這裏,我們看一下後端的代碼實現

  • 創建一個User對象(Java Bean)
public class User {
    private List<Integer> idList;
    // 必須有 getter 和 setter方法
    public void setIdList(List<Integer> idList){
		this.idList = idList;
	}
	public List<Integer> getIdList(){
		return this.idList;
	}
}

將想要接收的參數名稱定義成這個類對象的一個屬性,屬性的類型需要定義成List集合形式,至於泛型也是可以自動進行轉換的,可以根據自己的需求進行調整,不單單是String類型。例如這裏,我們讓它自動接收前端傳來名爲idList的多個參數,然後自動將其存儲在List集合中,並且所有的idList參數都由字符串自動轉成Integer類型。而我們只需要在Controller中,定義一下Bean對象參數即可,代碼如下:

@RequestMapping("/testList")    
    public String testList(User user, Map<String, Object> map){
        List<Integer> idList = user.getIdList();
        idList.forEach(id -> System.out.println(id));
		
		// 以下代碼與本例無關
        map.put("result","測試List傳參");
        return "hello";
    }

在Controller的處理方法中,我們只需要在方法參數列表中,聲明一個User user對象,將我們剛纔寫有idList屬性的類對象引入即可,不需要直接引入idList屬性,而是引用包含它的Bean 對象,這樣,我們就可以直接在方法中,使用user這個對象了,通過getIdList()屬性,拿到轉換後的List類型的參數。

前端頁面在傳遞List類型參數的時候,可以直接用form表單傳遞,代碼:

<h2>測試List傳參</h2>
   <form action="${pageContext.request.contextPath}/param/testList" method="post">
       ID:
       <input type="checkbox" name="idList" value="1" />1
       <input type="checkbox" name="idList" value="2" />2
       <input type="checkbox" name="idList" value="3" />3
       <input type="checkbox" name="idList" value="4" />4
       <br>
       <input type="submit" value="提交" />
   </form>

這裏的代碼是典型的發送List集合類型參數的前端代碼,使用的是form表單中的checkbox多選框,由於多選框的值有多個,並且name屬性相同,那麼後端在接收起來時,就不再是一對一的關係,而是一個屬性(字段)有多個值,那麼正好可以使用List集合來存放。

如果前端頁面不想使用form表單提交,那麼還有第二種方式,可以通過js代碼來發送JSON格式的數組信息來進行數據的提交,更加的靈活。

-2- 接收JSON格式數組

後端接收前端多個參數時,不僅是通過Bean對象的屬性來進行轉換存儲,還可以直接接收,無需藉助任何的變量類型。但是,這裏就對前端傳遞參數的格式有了要求,也就是說,如果想在後端Controller中接收到前端傳遞的多個參數,並轉換成List集合形式,那麼就需要前端按照規範來進行傳遞,那到底是什麼規範呢?那就是JSON格式。

先來看一下後端對於請求的處理方法:

	@RequestMapping(value = "/jsonToList", method = RequestMethod.POST)
    @ResponseBody	// 此註解與本例無關
    public String jsonToList(@RequestBody List<String> hobby){
        for(String hob: hobby){
            System.out.println(hob);
        }

		// 以下代碼與本例無關
        // Spring MVC 可以將json格式的字符串轉換成json
        return "{\"code\":200,\"msg\":\"SUCCESS\"}";    //JSON格式的字符串
    }

詳細剖析一下這個方法,首先@RequestMapping註解定義value屬性來指定攔截的路徑,爲/jsonToList,method屬性來指定攔截請求的類型爲POST類型,其他的類型不作攔截。緊接着定義了一個名爲jsonToList的處理方法,參數列表中定義了一個List< String>類型的變量名爲hobby,這其實就是前端一會傳來的參數,名字就是hobby,並且有多個,統一存放在List< String>類型的hobby變量中,但是這裏非常重要的一點就是,這裏使用了 @RequestBody 註解,只有加上這個註解,才能告訴springmvc底層,它需要自動爲我們完成參數的轉換映射賦值,否則,我們定義的List類型的hobby變量,是沒有辦法將前端傳來的參數裝到自己肚子裏的,這個工作是springmvc底層幫我們做的,需要的就是 @RequestBody 這個註解, 將它加載參數聲明前面即可。

那這樣,後端就可以直接在方法中使用變量了。我們看一下前端發送參數時的代碼:

const path = '${pageContext.request.contextPath}';
// 將Json數據轉換成List
   function testJsonToList(){
       //定義一個json數組  new  Array()
       let hobby = ['唱歌','跳舞','喝酒','燙頭']
       $.ajax({
           url: path + '/param/jsonToList',
           type: 'post',
           data: JSON.stringify(hobby), //數組也是js對象
           dataType: 'json',   //簡寫 application/json
           contentType: 'application/json',
           success: res=>{
               alert('code:' + res.code + ', msg:' + res.msg)
           }
       })
   }

以上代碼片段是寫在前端< script>標籤中的,即腳本代碼。這裏進行一下剖析,以便大家理解。

定義了一個名爲testJsonToList的方法,其中首先定義了一個名爲hobby的數組,這個數組有4個值,分別是唱歌、跳舞、喝酒、燙頭。數組名爲hobby,與後端controller中我們定義的List名稱完全一致(只有這樣才能完成自動映射);同時,需要注意的是,這裏我們將參數是封裝在一個數組對象中,格式是:用 [ ] 將內容包裹在內。思考一下:爲什麼要用數組進行存儲呢? 下面會給出解釋。
接下來發送ajax請求,指定 url 到實現約定的地址;
type 指定爲POST類型;
data 爲我們要傳遞的參數,這裏我們使用了 JSON.stringify() 方法,這個發送是JSON所持有的,作用是將一個js對象轉換成JSON格式,爲什麼要轉換成JSON格式?這是本例在開頭就說好的,後端想要直接接收多個同名參數並存放到List集合中,前端發送參數時就必須按規定發送,規定就是JSON格式,這裏的JSON.stringify() 其作用就是幫助我們完成格式的轉換,換句話說,就是我們可以直接在前端定義一個js支持的數組對象或者是Js對象都可以,然後通過這個方法讓它自動爲我們完成轉換;當然,我們也可以自己直接將內容寫成JSON格式,例如:{“hobby:”:“唱歌”,“hobby”:“跳舞”,“hobby”:“喝酒”,“hobby”:“燙頭”},但是這樣書寫如果字段比較多的時候,會比較的繁瑣,所以不如直接寫一個js中的數組對象,然後使用 JSON.stringify() 來幫助我們完成格式的轉換。
dataType 爲我們傳遞數據的格式,毋庸置疑是JSON格式,所以寫成’application/json’,當然簡寫就是’json‘.
contentType 爲指定編碼格式。服務端通常是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體是用何種方式編碼,再對主體進行解析。使用 POST 提交數據方案,包含了 Content-Type 和消息主體編碼方式兩部分。application/json 這個 Content-Type 作爲響應頭大家肯定不陌生。實際上,現在越來越多的人把它作爲請求頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。由於 JSON 規範的流行,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數。
sucess 爲回調函數,此處代碼與本例無關,不作過多解釋。

>> 總結 > 發送JSON格式直接到後端Controller,無非需要注意兩點:

後端Controller的執行方法中,需要給參數列表加上@RequestBody註解,並確保存儲變量與前端發送參數的name保持一致。
前端發送的內容,必須是JSON格式,可以自己手寫JSON格式也可以使用JSON.stringify來轉換成JSON格式。ajax請求中,需要修改dataType和contentType,值都是’application/json’,可以不使用簡寫。

6. Map集合

以Map集合參數類型接收前端傳來的參數,其實就是將前端傳來的參數在後端Controller中自動進行類型的轉換,轉換成Java中的Map集合類型來存儲前端傳來的參數。想要springmvc自動將接收的參數轉換成Map集合類型,有兩種方法:

  1. 將Map集合定義在Java Bean中
  2. 接收JSON格式對象
-1- 將Map集合定義在Java Bean中

有了List集合的介紹,這裏直接上代碼,先看一下Bean對象:

public class User {

    private Map<String, String> userMap;
    
    public Map<String, String> getUserMap() {
        return userMap;
    }

    public void setUserMap(Map<String, String> userMap) {
        this.userMap = userMap;
    }
}

定義一個Map類型的結合,用於存儲前端出來名爲userMap的多個參數。

接下來,看一下Controller中的處理方法:

    @PostMapping("/testMap")
    public String testMap(User user){
        Map<String, String> userMap = user.getUserMap();
        System.out.println(userMap);
		...
    }

這裏剖析一下:@PostMapping註解爲指定只攔截POST請求,同時攔截的Url爲 /testMap,執行方法名成testMap,參數列表中直接定義User user對象,與List集合完全相同。於是,在方法中,就可以直接使用user對象,使用getUserMap()方法就可以拿取到userMap這個對象中的內容,我們使用System.out.println()將其遍歷打印出來。

接下來,看一下前端頁面的傳遞參數代碼:

const path = '${pageContext.request.contextPath}';

function testMap(){
    $.ajax({
        url: path + '/param/testMap',
        type: 'POST',
        data: "userMap['id']=100&userMap['name']=zs",    // Map<String, String> {id=1,name=zs}
        dataType: 'text',
        success: function(res){
            alert(res)
        },
        error: function (err) {
            alert(err)
        }
    })
}

這裏對上述代碼片段進行一下剖析,在前端< script >代碼中,定義名爲testMap的方法;
url: 發送ajax請求到指定的Url與後臺的controller中的testMap方法對應。
type: 指定請求類型爲POST
data: 指定參數傳遞的內容,這裏的格式需要大家記住,Map集合由於是鍵值對類型的格式,所以在發送中,需要採用 name[‘key’]=value的格式進行發送,name爲當前屬性的name值,在這裏也就是userMap,對應了後臺controller方法中的Map集合類型的userMap變量,[‘id’]爲第一個Key,對應的value就是100,而第二個key是’name’ 對應的值爲 zs,這裏需要注意的是,如果參數大於1個,那麼參數直接需要用&符號進行連接,最終將所有的內容,寫在雙引號中。
dataType: 此時的數據類型僅僅爲text文本格式

-2- 接收JSON格式對象

除了上述通過規範傳遞內容的格式,來發送傳遞內容外,還可以將發送內容的格式定義爲JSON格式。JSON格式就不需要我們手動的規範傳遞的參數格式了,也就不再需要自己去寫 這種:data: "userMap['id']=100&userMap['name']=zs",代碼,因爲一旦字段多的時候,寫起來非常的麻煩。

接下來,看一下後臺Controller的代碼:

	@PostMapping("/jsonToMap")
    public User jsonToMap(@RequestBody Map<String, Object> map){
        // {id: 1, hobby: ['踢球','跳舞'], user: {id:1, name:'zs'}}  -- json格式
        System.out.println(map);
        ...
    }

此時,我們在參數列表中定義了 一個Map集合名爲map,key的泛型爲String,value的泛型爲Object,也就是說,value的類型可以是任意類型。(其實這裏的變量名稱map,可以是任意的名稱,不需要再與前端保持一致了,因爲這裏的映射規則是key和value的鍵值對了)

接下來,看一下前端頁面的代碼:

const path = '${pageContext.request.contextPath}';

//將json數據轉換成Map
 function testJsonToMap(){
     let obj = {id: 1, hobby: ['唱歌', '跳舞', '打遊戲'], user: {id: 1, name:'四哥'}}

     $.ajax({
         url: path + '/param/jsonToMap',
         type: 'POST',
         data: JSON.stringify(obj),
         dataType: 'json',
         contentType: 'application/json',
         success: res=>{
             alert(res.id + res.name + res.age)
         }
     })
 }

可以看出,由於此時後端接收參數的類型變成了Map集合類型,也就是鍵值對類型,需要有一個key和一個value來組合對應。那麼前端擁有這種格式的類型,數組已經無法滿足了,因爲數組的值是一個整體,沒有辦法體現出一個個鍵值對(Key=value),此時!前端唯一能有這種格式的,就剩下Js對象了!使用js對象,就可以模擬出key=value的格式,如上代碼中所寫:let obj = {id: 1, hobby: ['唱歌', '跳舞', '打遊戲'], user: {id: 1, name:'四哥'}} ,定義了一個js對象名爲obj,這個js對象的鍵值對之間都用逗號(,)隔開,第一對爲id:1,key爲id,value爲1;第二對,key爲hobby,value爲數組對象 [‘唱歌’, ‘跳舞’, ‘打遊戲’];第三對,key爲user,value爲js對象{id: 1, name:‘四哥’}。

最終整個對象被{ }包裹,由此可以看出,此時參數傳遞對應的關鍵所在已經變成了key和value的對應,此時的key在後端會被自動映射成String類型,而value則被映射成Object類型,如果我們需要將Value的Object類型進行進一步的轉換,可以在後端使用強制類型轉換,非常的方便。

同時,此時我們也不需要自己手寫key=value的格式數據了,直接使用js對象即可。

接下來就是發送ajax請求,
url: 指定到規定的請求地址
type: 必須修改成post
data: 傳遞的參數,這裏使用JSON.stringify()來幫助我們將js對象轉換成json格式的數據
dataType: 數據的類型,當然是’json’,這是簡寫。
contentType: 請求頭中規定的編譯格式,爲’application/json’
success: 回調函數

>> 總結 > 發送JSON格式直接到後端Controller,無非需要注意兩點:

後端Controller的執行方法中,需要給參數列表加上@RequestBody註解,並確保存儲變量與前端發送參數的name保持一致。
前端發送的內容,必須是JSON格式,可以自己手寫JSON格式也可以使用JSON.stringify來轉換成JSON格式。ajax請求中,需要修改dataType和contentType,值都是’application/json’,可以不使用簡寫。

7. JSON 格式

這裏所謂的JSON格式傳遞參數,其實已經在5、6兩個模塊介紹過了,這裏做一下總結。
①JSON格式傳遞參數,我們可以手寫JSON格式,或者是將js中的數據、對象進行轉換,採用的是JSON.stringify()方法,可以節省我們手寫的繁瑣。
②htpp協議的請求方法使用post,http協議的請求頭的contentType是application/json
③springmvc底層在幫我們進行JSON格式的解析和與Java屬性之間的映射,springmvc 使用jackson作爲默認的json轉換器,所以,需要我們引入maven依賴。總共有3個jar包:jackson-core.jar ,jackson-databind.jar,jackson-annotation.jar。而jackson-databind.jar依賴於其他兩個jar,於是我們在引入的時候,只需要引入jackson-databind.jar這一個jar包即可,另外兩個自動引入。
④ @RequestBod註解可以將json格式數據轉換成java bean,list,map。@ResponseBody註解可以將Object類型返回值轉成json格式的數據

二、後臺向前端通過request域傳遞值的方式:

1. Servlet api 中的 HttpServletRequest對象

代碼:

	//servlet請求
    @RequestMapping("/servlet")
    public String servlet(HttpServletRequest request){
        String name = request.getParameter("name");
        System.out.println("name:" + name);
        // 以下爲本例代碼
        request.setAttribute("result", "hello " + name);
        return "hello";
    }

這種方式是最傳統的方式,直接向request域中進行參數的傳遞,通過setAttribute()方法,來指定key和value,即可在前端頁面hello.jsp中直接獲取到request域中的內容。如何獲取?代碼如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h2>${result}</h2>
    </body>
</html>

2. ModelAndView 對象

代碼片段:

 public ModelAndView modelAndView(){
		ModelAndView  mv = new ModelAndView();
        // 向request域傳值
        mv.addObject("result","Hello spring mvc");
        // 設置視圖名稱   prefix + viewName + suffix (/jsps/hello.jsp)
        mv.setViewName("hello");
        return mv;

這是SpringMVC獨有的ModelAndView對象,通過聲明一個ModelAndView類型的對象,就可以使用這個對象來傳值或者是指定跳轉的頁面路徑。採用addObject()方法,來規定key和value,即可在前端頁面中根據key拿取到對應value的值。通過採用setViewName()方法,來傳入一個頁面的名稱,springmvc底層的視圖解析器就會將ModelAndView中的view視圖進行前綴和後綴的拼接加工,並給最終的頁面跳轉路徑。當然,這裏執行方法的返回類型需要是ModelAndView類型,方法最終需要將mv對象return 。

參數列表中也可以提前聲明ModelAndView對象,可直接在方法中使用。如:

 public ModelAndView modelAndView(ModelAndView mv){
        // 向request域傳值
        mv.addObject("result","Hello spring mvc");
        // 設置視圖名稱   prefix + viewName + suffix (/jsps/hello.jsp)
        mv.setViewName("hello");
        return mv;

3. ModelMap 對象

@RequestMapping("/simple")
    public String simple(int id, String name, ModelMap modelMap){
        // modelMap 可以向request域傳值【ModelAndView,Request,ModelMap】
        System.out.println("id:" + id);
        System.out.println("name:" + name);
        // 以下爲本例的代碼 
        modelMap.addAttribute("result", "Hello " + name + "," + id);
        return "hello";
    }

這裏的ModelMap對象與request對象相似,可以採用addAttribute()方法來傳遞參數,向ModelMap對象中添加key和value,其實就是在向request域中添加key和value,只不過ModelMap是又將request進行了一層封裝,原因是徹底與Servlet的內容分離,僅用SpringMVC的對象,就可以完成對request域的賦值。

4. Model 對象

@RequestMapping("/bean")
    public String testBean(User user, Model model){
        System.out.println(user);
        // 使用Model對象向request域傳值
        model.addAttribute("result", "hello " + user.getName());
        return "hello";
    }

Model對象與ModelMap對象類型。

5. Map 集合

	@PostMapping("/array")
    public String array(String[] hobby, Map<String, String> map){
       for(String hobbyStr : hobby){
           System.out.println(hobbyStr);
       }

       //使用 java.util.Map 向request域傳值
        map.put("result","測試數組傳參");

       return "hello";
    }

在執行方法的參數列表中,聲明一個Map集合,並向其中put()僅key和value,就可以被springmvc解析成向request域中傳遞值。底層就是使用request.setAttribute()在賦值。而我們無需引入request對象,僅僅使用一個簡單的map集合,就可以完成對request對象的操作。徹底與Servlet解耦。

發佈了14 篇原創文章 · 獲贊 3 · 訪問量 2085
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章