基於註解的SpringMVC簡單介紹

SpringMVC是一個基於DispatcherServlet的MVC框架,每一個請求最先訪問的都是DispatcherServlet,DispatcherServlet負責轉發每一個Request請求給相應的Handler,Handler處理以後再返回相應的視圖(View)和模型(Model),返回的視圖和模型都可以不指定,即可以只返回Model或只返回View或都不返回。在使用註解的SpringMVC中,處理器Handler是基於@Controller和@RequestMapping這兩個註解的,@Controller聲明一個處理器類,@RequestMapping聲明對應請求的映射關係,這樣就可以提供一個非常靈活的匹配和處理方式。

 

DispatcherServlet是繼承自HttpServlet的,既然SpringMVC是基於DispatcherServlet的,那麼我們先來配置一下DispatcherServlet,好讓它能夠管理我們希望它管理的內容。HttpServlet是在web.xml文件中聲明的。

 

Xml代碼  收藏代碼
  1. <servlet>  
  2.     <servlet-name>blog</servlet-name>  
  3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.     <load-on-startup>1</load-on-startup>  
  5. </servlet>  
  6. <servlet-mapping>  
  7.     <servlet-name>blog</servlet-name>  
  8.     <url-pattern>*.do</url-pattern>  
  9. </servlet-mapping>  

 

 上面聲明瞭一個名爲blog的DispatcherServlet,該Servlet將處理所有以“.do”結尾的請求。在初始化DispatcherServlet的時候,SpringMVC默認會到/WEB-INF目錄下尋找一個叫[servlet-name]-servlet.xml的配置文件,來初始化裏面的bean對象,該文件中對應的bean對象會覆蓋spring配置文件中聲明的同名的bean對象。如上面的就會在/WEB-INF目錄下尋找一個叫blog-servlet.xml的文件;當然也可以在Servlet中聲明配置文件的位置,那就是通過Servlet的初始化參數來設置contextConfigLocation參數的值。

 

Xml代碼  收藏代碼
  1. <servlet>  
  2.     <servlet-name>blog</servlet-name>  
  3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.     <init-param>  
  5.         <param-name>contextConfigLocation</param-name>  
  6.         <param-value>/WEB-INF/blog-servlet.xml</param-value>  
  7.     </init-param>  
  8.     <load-on-startup>1</load-on-startup>  
  9. </servlet>  
  10. <servlet-mapping>  
  11.     <servlet-name>blog</servlet-name>  
  12.     <url-pattern>*.do</url-pattern>  
  13. </servlet-mapping>  

 

 DispatcherServlet會利用一些特殊的bean來處理Request請求和生成相應的視圖返回。

 

關於視圖的返回,Controller只負責傳回來一個值,然後到底返回的是什麼視圖,是由視圖解析器控制的,在jsp中常用的視圖解析器是InternalResourceViewResovler,它會要求一個前綴和一個後綴

 

Xml代碼  收藏代碼
  1. <bean  
  2.     class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
  3.     <property name="prefix" value="/WEB-INF/" />  
  4.     <property name="suffix" value=".jsp" />  
  5. </bean>  

 

在上述視圖解析器中,如果Controller返回的是blog/index,那麼通過視圖解析器解析之後的視圖就是/WEB-INF/blog/index.jsp。

 

要使用註解的SpringMVC需要在SpringMVC的配置文件中進行聲明,具體方式爲先引入mvc命名空間,然後利用<mvc:annotation-driven />進行聲明。

 

Xml代碼  收藏代碼
  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  3.     <span style="background-color: #00ff00;"><span style="color: #ff0000;">xmlns:mvc="http://www.springframework.org/schema/mvc"</span>  
  4. </span>  
  5.   
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  7.      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  8.      http://www.springframework.org/schema/context  
  9.      http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  10.     <span style="background-color: #00ff00; color: #ff0000;"> http://www.springframework.org/schema/mvc  
  11.      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"</span>  
  12.   
  13. >  
  14. <mvc:annotation-driven />  
  15.   
  16. </beans>  

 

 

 

主要是說說Controller.

在SpringMVC中Controller不需要繼承什麼類,也不需要實現什麼接口,一切使用了@Controller進行標記的類都是Controller

 

Java代碼  收藏代碼
  1. @Controller  
  2. public class BlogController {  
  3.   
  4. }  

 有了Controller之後,那麼到底是怎樣請求一個Controller具體的方法的呢,那是通過@RequestMapping來標記的,@RequestMapping可以標記在類上面,也可以標記在方法上,當方法上和類上都標記了@RequestMapping的時候,那麼對應的方法對應的Url就是類上的加方法上的,如下面的index方法,其對應的URL應爲類上的/blog加上index方法上的/index,所以應爲/blog/index,所以當請求/blog/index.do的時候就會訪問BlogController的index方法。加在類上的@RequestMapping不是必須的,當Controller類上加上了@RequestMapping的時候,那麼Controller方法上的@RequestMapping就是相對於類上的@RequestMapping而言的,也就是前面說的請求映射的時候是類上的地址加方法上的地址,而當Controller類上沒有加@RequestMapping的時候,方法上的@RequestMapping就是絕對路徑了。

 

 

Java代碼  收藏代碼
  1. @Controller  
  2. @RequestMapping("/blog")  
  3. public class BlogController {  
  4.       
  5.     @RequestMapping("/index")  
  6.     public String index(Map<String, Object> map) {  
  7.         return "blog/index";  
  8.     }  
  9. }  

 

 在上面的代碼中,如果index方法上沒有RequestMapping註解,而只有BlogController類上有,且該類只有一個方法的時候,直接請求類上的URL就會調用裏面的方法,即直接請求/blog.do的時候就會調用index方法。

在RequestMapping中還可以指定一個屬性method,其主要對應的值有RequestMethod.GET和RequestMethod.POST,利用該屬性可以嚴格的控制某一方法只能被標記的請求路徑對應的請求方法才能訪問,如指定method的值爲GET,則表示只有通過GET方式才能訪問該方法,默認是都可以訪問。RequestMapping中的URL映射還支持通配符*,如:

Java代碼  收藏代碼
  1. @Controller  
  2. @RequestMapping("/blog")  
  3. public class BlogController {  
  4.     @RequestMapping("/*/index")  
  5.     public String index(Map<String, Object> map) {  
  6.         return "blog/index";  
  7.     }  
  8. }  

 在@RequestMapping中還有一個屬性params,可以通過該屬性指定請求參數中必須包含某一參數,或必須不包含某一參數,或某參數的值必須是什麼,以此來縮小指定的映射範圍。

Java代碼  收藏代碼
  1. @Controller  
  2. @RequestMapping("/blog")  
  3. public class BlogController {  
  4.       
  5.     @RequestMapping(value="/index", params="param1=value1")  
  6.     public String index(Map<String, Object> map) {  
  7.         return "blog/index";  
  8.     }  
  9. }  

在上面示例中,只有當請求/blog/index.do並且請求參數param1的值爲value1的時候才能訪問到對應的index方法。如果params的值爲"param1",則表示請求參數只要包含param1就可以了,至於它的值是什麼無所謂;如果params的值爲"!param1",則表示請求參數必須不包含param1纔可以。@RequestMapping中還可以使用header來縮小映射範圍,如:

Java代碼  收藏代碼
  1. @Controller  
  2. @RequestMapping("/blog")  
  3. public class BlogController {  
  4.     @RequestMapping(value="/index",headers="content-type=text/html")  
  5.     public String index(Map<String, Object> map) {  
  6.         return "blog/index";  
  7.     }  
  8. }  

 

 

在SpringMVC中常用的註解還有@PathVariable,@RequestParam,@PathVariable標記在方法的參數上,利用它標記的參數可以利用請求路徑傳值,看下面一個例子

 

Java代碼  收藏代碼
  1. @RequestMapping(value="/comment/{blogId}", method=RequestMethod.POST)  
  2. public void comment(Comment comment,@PathVariable int blogId, HttpSession session, HttpServletResponse response) throws IOException {  
  3.       
  4. }  

 

在該例子中,blogId是被@PathVariable標記爲請求路徑變量的,如果請求的是/blog/comment/1.do的時候就表示blogId的值爲1,@PathVariable在進行賦值的時候如果像上面那樣沒有指定後面接的變量是對應URL中的哪個變量時默認是從URL中取跟後面接的變量名相同的變量,如上面示例中的@PathVariable int blogId,沒有指明要獲取URL中的哪個變量,這個時候就默認取URL中的blogId變量對應的值賦給方法參數中的blogId,那如果方法參數的名稱跟RequestMapping中定義的訪問路徑中的變量名不一樣,或者我要利用PathVariable明確指定後面接的方法參數是對應於URL中的哪個變量時,可以像下面這樣做,在PathVariable中給定一個value="blogId"(只有一個參數的時候value是可以省略的)值明確指定方法參數中的id變量是對應請求路徑定義中的blogId變量的。

Java代碼  收藏代碼
  1. @RequestMapping(value="/comment/{blogId}", method=RequestMethod.POST)  
  2. public void comment(Comment comment,@PathVariable("blogId"int id, HttpSession session, HttpServletResponse response) throws IOException {  
  3.       
  4. }  

 

同樣@RequestParam也是用來給參數傳值的,但是它是從頭request的參數裏面取值,相當於request.getParameter("參數名")方法。它的取值規則跟@PathVariable是一樣的,當沒有指定的時候,默認是從request中取名稱跟後面接的變量名同名的參數值,當要明確從request中取一個參數的時候使用@RequestParam("參數名"),如下所示:

Java代碼  收藏代碼
  1. @RequestMapping("/show")  
  2. public void showParam(@RequestParam int id, @RequestParam("name") String username) {  
  3.     //這樣做進行URL請求訪問這個方法的時候,就會先從request中獲取參數id的值賦給參數變量id,從request中獲取參數name的值賦給參數變量username  
  4. }  

 

 

在Controller的方法中,如果需要WEB元素HttpServletRequest,HttpServletResponse和HttpSession,只需要在給方法一個對應的參數,那麼在訪問的時候SpringMVC就會自動給其傳值,但是需要注意的是在傳入Session的時候如果是第一次訪問系統的時候就調用session會報錯,因爲這個時候session還沒有生成。

 

接下來討論一下方法的返回值,主要有以下情況:

 

  • 返回一個ModelAndView,其中Model是一個Map,裏面存放的是一對對的鍵值對,其可以直接在頁面上使用,View是一個字符串,表示的是某一個View的名稱
  • 返回一個字符串,這個時候如果需要給頁面傳值,可以給方法一個Map參數,該Map就相當於一個Model,往該Model裏面存入鍵值對就可以在頁面上進行訪問了
  • 返回一個View對象
  • 返回一個Model也就是一個Map,這個時候將解析默認生成的view name,默認情況view name就是方法名,這裏之前搞錯了,感謝網友的指正。默認的View Name是由RequestToViewNameTranslator來解析的,顧名思義就是把request翻譯成viewName,在沒有指定RequestToViewNameTranslator時,Spring將使用其自身的默認實現DefaultRequestToViewNameTranslator的默認配置,即取到當前請求的URI,去掉最前和最後的斜槓“/”,以及對應的後綴。所以當你請求“http://localhost/app/abc”的時候,對應的默認viewName就是請求URI——“/abc”去掉最前最後的斜槓和後綴之後的結果,即“abc”,請求“http://localhost/app/abc/efg”時對應的默認視圖名稱是“abc/efg”,“http://localhost/app/abc/efg/hi.html”——>“abc/efg/hi”。如果需要改變默認的視圖名稱的解析方式,可以在SpringMVC的配置文件中配置一個名稱爲viewNameTranslator,類型爲RequestToViewNameTranslator的bean。如果該bean是DefaultRequestToViewNameTranslator,那麼你可以通過prefix屬性指定視圖名稱的前綴,通過suffix指定後綴,通過stripLeadingSlash指定是否需要去掉最前面的斜槓,更多可指定的屬性請參考DefaultRequestToViewNameTranslator的實現。當然你也可以定義自己的RequestToViewNameTranslator實現類,實現RequestToViewNameTranslator接口的getViewName(HttpServletRequest request)方法,實現自己的獲取默認視圖名稱的邏輯。
  • 什麼也不返回,這個時候可以在方法體中直接往HttpServletResponse寫入返回內容,否則將會由RequestToViewNameTranslator來決定
  • 任何其他類型的對象。這個時候就會把該方法返回類型對象當做返回Model模型的一個屬性返回給視圖使用,這個屬性名稱可以通過在方法上給定@ModelAttribute註解來指定,否則將默認使用該返回類名稱作爲屬性名稱。
下面是一個簡單的實例
Java代碼  收藏代碼
  1.        @RequestMapping("/{owner}/index")  
  2. public String userIndex(Map<String, Object> map,@PathVariable String owner, HttpServletRequest request) throws ParserException {  
  3.     List<DefCategory> categories = categoryService.find(owner);  
  4.     int offset = Util.getOffset(request);  
  5.     Pager<Blog> pager = blogService.find(owner, 0, offset, maxResults);  
  6.     int totalRecords = pager.getTotalRecords();  
  7.     List<Blog> blogs = pager.getData();  
  8.     Util.shortBlog(blogs);  
  9.       
  10.     List<Message> messages = messageService.find(owner, 05).getData();  
  11.     Util.shortMessage(messages, 20);  
  12.     map.put("messages", messages);  
  13.     map.put("totalRecords", totalRecords);  
  14.     List<BlogStore> stores = storeService.find(owner, 05).getData();  
  15.     map.put("maxResults", maxResults);  
  16.     map.put("blogs", blogs);  
  17.     map.put("totalRecords", totalRecords);  
  18.     map.put("owner", userService.find(owner));  
  19.     map.put("defCategories", categories);  
  20.     map.put("stores", stores);  
  21.     return "blog/userIndex";  
  22. }  

  

給頁面傳值

    在Controller中把請求轉發給業務邏輯層進行處理之後需要把業務邏輯層的處理結果進行展現,在展現的過程中就需要我們把處理結果傳給展示層進行展示。那麼處理結果是怎麼進行傳遞的呢?前面已經說了Controller的返回結果可以是一個包含模型和視圖的ModelAndView,也可以僅僅是一個視圖View,當然也可以什麼都不返回,還可以是僅僅返回一個Model。我們知道模型Model是用來封裝數據給視圖View進行展示的,那麼,在SpringMVC中,如果要把我們後臺的信息傳遞給前臺進行展示的話應該怎麼做呢?這主要有兩種方式:
    1.返回包含模型Model的ModelAndView,或者是直接返回一個Model(這個時候就需要考慮默認的視圖),這種類型的返回結果是包含Model的,這個Model對象裏面的對應屬性列都可以直接在視圖裏面使用。
    2.如果是直接返回一個視圖View,這個時候SpringMVC提供了一種類似於在Controller方法中獲取HttpRequest對象的機制,這個時候我們只需要給定Controller方法一個Map參數,然後在方法體裏面給這個Map加上需要傳遞到視圖的鍵值對,這樣在視圖中就可以直接訪問對應的鍵值對

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章