1. 程式人生 > >Spring MVC使用篇(六)—— 請求對映

Spring MVC使用篇(六)—— 請求對映

文章目錄

1、綜述

  Handler處理器在Spring MVC中佔據著重要位置,它主要負責請求的處理和結果的返回。在MVC架構中,Handler扮演了控制層(Controller)的角色。

2、Controller

  在日常開發中最常用的處理器對映器和介面卡是基於註解的處理器對映器和介面卡配置,即annotation-driven標籤。它會自動註冊處理器對映器和處理器介面卡,並且除此之外還提供了資料繫結支援。利用Spring MVC提供的預設的註解配置,可以省去許多的開發配置,因此提高了開發效率。具體配置如下:

<!--配置基於註解的處理器介面卡與處理器對映器-->
<mvc:annotation-driven/>

  在使用annotation-driven標籤時,處理器Handler的型別要符合annotation-driven標籤指定的處理器對映器和介面卡型別。annotation-driven標籤指定的預設處理器對映器和介面卡在Spring 3.1之前為DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter,在Spring 3.1之後為RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

  在配置了註解的處理器對映器的情況下,當使用@Controller註解去標識一個類時,其實就是告訴Spring MVC該類是一個Handler控制器類。在配置了component-scan標籤後,當Spring初始化Bean資訊時,會掃描到所有標註了@Controller註解的類,並將其作為Handler來載入。

提示:可以在@Controller註解上指定一個請求域,表示整個Controller的服務請求路徑在該域下訪問。

3、RequestMapping

  基於註解的Handler必須在類中實現處理請求邏輯的方法,並且使用註解標註它們處理的URL路徑。在@Controller中編寫的方法需要標註@RequestMapping註解,表明該方法是一個處理前端請求的方法。

  @RequestMapping註解的作用是為控制器指定可以處理哪些URL請求,該註解可以放置在類上或者方法上。當放置在類上時,提供初步的URL請求對映資訊,即一個前置請求路徑(相對於Web應用的根目錄),當放置在方法上時,提供進一步的細分URL對映資訊,相對於類定義處的URL。若類定義處未標註@RequestMapping,則方法處標記的URL相對於Web應用的根目錄。

  使用@RequestMapping註解時,如果為其指定一個URL對映名,則指定其value屬性即可。而一般不在@RequestMapping中配置其他屬性時,可以省去value引數名,直接編寫一個代表URL對映資訊的字串即可,@RequestMapping會預設匹配該字串為value屬性的值。但需要注意的是,如果@RequestMapping中配置了value屬性之外的其他屬性時,則必須宣告value屬性,不可省略。

  下面是一個@RequestMapping註解的例子,這裡只為其中的方法設定了RequestMapping註解,程式碼如下:

package com.ccff.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {
    @RequestMapping("/test")
    public String test(){
        return "success";
    }
}

  假設工程名為“SpringMVC”,預設字尾名為“.action”。那麼這裡test()處理的URL請求路徑為:http://localhost:8080/SpringMVC/test.action。

  如果在類上也新增@RequestMapping註解,就會為整個Handler類的@RequestMapping的URL新增一個字首路徑,程式碼如下:

package com.ccff.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class MyController {
    @RequestMapping("/userTest")
    public String userTest(){
        return "success";
    }
}

  假設工程名為“SpringMVC”,預設字尾名為“.action”。那麼這裡test()處理的URL請求路徑為:http://localhost:8080/SpringMVC/test/userTest.action。

  除此之外,註解@RequestMapping還可以限定請求方法、請求引數和請求頭。

  對於請求方法,@RequestMapping的method屬性可以指定“GET”或“POST”請求型別,表明該URL只能以某種請求方式請求才能獲得響應,程式碼如下:

package com.ccff.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/test")
public class MyController {
    @RequestMapping(value = "/userTest", method = RequestMethod.GET)
    public String userTest(){
        return "success";
    }
}

  這裡訪問“/test/userTest.action”時,只能接受GET請求型別。可以看到,指定的“GET”或“POST”請求型別需要由RequestMethod列舉類來表示,以達到一種規範。

  對於請求引數,@RequestMapping的param屬性可以指定某一種引數名型別,當請求資料中含有該名稱的請求引數時,才能進行響應,具體程式碼如下:

package com.ccff.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class MyController {
    @RequestMapping(value = "/userTest", params = "username")
    public String userTest(){
        System.out.println("只接受username引數");
        return "success";
    }
}

  該配置表示,當一個URL請求中不含有名稱為“username”的引數時,該方法就拒絕此次請求。

  對於請求頭,@RequestMapping的headers屬性可以指定某一種請求頭型別,當請求資料頭的型別符合指定的值時,才能進行響應,具體程式碼如下:

package com.ccff.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class MyController {
    @RequestMapping(value = "/userTest", headers = "Content-Type:text/html;charset=UTF-8")
    public String userTest(){
        System.out.println("只接受請求頭中Content-Type為text/html;charset=UTF-8的請求");
        return "success";
    }
}

  該配置表示,當一個請求頭中的Content-Type為“text/html;charset=UTF-8”的引數時,該方法才會處理此次請求。

  還有兩個屬性,分別是consumes和produces。其中consumes表示處理請求的提交內容型別(Content-Type),例如“application/json,text/html”。而produces表示返回的內容型別,僅當request請求頭中的(Accept)型別中包含該指定型別時才返回。

  下面是一個consumes的例子,具體程式碼如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MyController {
    @RequestMapping(value = "/fruits", method = RequestMethod.POST, consumes = "application/json")
    public void addFruit(Fruits fruit, Model model){
        //implements omitted
    }
}

  該配置表示方法僅處理request的Content-Type為“application/json”型別的請求。

  下面是一個produces的例子,具體程式碼如下:

package com.ccff.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {
    @RequestMapping(value = "/getFruits", method = RequestMethod.GET, produces = "application/json")
    @ResponseBody
    public void addFruit(int id, Model model){
        //implements omitted
    }
}

  該配置表示方法僅處理request請求中Accept頭中包含“application/json”的請求,同時暗示了返回的內容型別為application/json。

小貼士:指定consumes和produces可以規範請求的Content-Type內容型別。