基於註解的SpringMVC

相比傳統的繼承Controller體系中某些類的方式,SpringMVC的註解具備如下優勢: 一、Controller再也不須要繼承某個特定類,只是簡單的POJO。 二、請求映射的配置很是方便靈活。 三、參數綁定機制很是方便豐富。 四、能夠根據不一樣的http方法或者參數,細粒度處理不一樣的http請求java

1、概述

SpringMVC在2.5版本後新增了註解功能,2.5版本之前的基本經過繼承Controller體系來開發業務控制器,2.5版本後Controller體系中
BaseCommandController及其子類AbstractCommandController、AbstractFormController、AbstractWizardFormController、web

SimpleFormController、CancellableFormController等都已經被標示爲@Deprecated,建議再也不使用。ajax


相比傳統的繼承Controller體系中某些類的方式,SpringMVC的註解具備如下優勢:
一、Controller再也不須要繼承某個特定類,只是簡單的POJO。
二、請求映射的配置很是方便靈活。
三、參數綁定機制很是方便豐富。
四、能夠根據不一樣的http方法或者參數,細粒度處理不一樣的http請求spring

2、示例

下面經過對SpringMVC註解的詳細介紹來看一下上述優勢。

首先須要在應用的dispatcher-servlet.xml 啓動註解機制json

<context:annotation-config />
<!-- 設置註解驅動 -->
<mvc:annotation-driven />
 
<!-- 設置掃描的包 -->
<context:component-scan base-package="com.demo.web.controller" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
數組


注:雖然咱們的Controller不須要再繼承任何類,但出於規範,咱們仍然命名爲***Controller.java,並統一放在com.demo.web.controller包中。
mvc

一、@Controller註解

簡單示例
app

package com.demo.controller;

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

@Controller
class IndexController {
    @RequestMapping(
"/index")
    String index() {
        
return "index";
    }
}
異步


在一個POJO上面使用 @Controller 就能夠標註該POJO是一個Controller,就這麼簡單。 @Controller註解定義在org.springframework.steretype包中。
使用方式: @Controller 或者 @Controller("indexController)。 org.springframework.steretype包中還包含 @Componenet @Service @Respository
三個註解。@Component是通用標註,@Controller標註web控制器,@Service標註Servicec層的服務,@Respository標註DAO層的數據訪問。

ui

二、使用@RequestMapping註解處理請求映射

    SpringMVC中註解基本都包含在 org.springframework.web.bind.annotation 包中。先看一下@RequestMapping 註解的源碼。

@Target( { ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {

    
/**
     * 指定映射的URL.能夠在類層次和方法層次使用。方式以下:
     * @RequestMapping("/add_")或 @RequestMapping(value = "/add")
     * 支持Ant風格的URL映射,如 @RequestMapping("/myPath/*.htm")
     * 在類層次指定了映射後,能夠在方法層次再指定相對路徑
     
*/
    String[] value() 
default {};

    
/**
     * 指定HttpRequest的方法, 如:GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE.
     * 使用舉例: @RequestMapping(value = "/add_activity", method = RequestMethod.GET)
     
*/
    RequestMethod[] method() 
default {};

    
/**
     * 指定HttpRequest中包含的參數,使用方式以下:
     * @RequestMapping(value = "/something",params="myParam") 請求包含myParam參數
     * @RequestMapping(value = "/something",params="myParam=myValue")請求包含myParam參數,而且該參數值爲myValue
     * @RequestMapping(value = "/something",params="!myParam") 請求不包含myParam參數
     
*/
    String[] params() 
default {};

    
/**
     * 指定HttpRequest中包含的頭部信息,使用方式以下:
     * @RequestMapping(value = "/something", headers="content-type")請求包含該頭部
     * @RequestMapping(value = "/something", headers="content-type=text/*")請求包含特定值的頭部
     * @RequestMapping(value = "/something", headers="!content-type")請求不包含該頭部
     
*/
    String[] headers() 
default {};

}

注:若是在類層次指定了映射,則方法層次上都將繼承類層次的映射

三、獲取HttpRequest中得參數

@RequestMapping("active")
public @ResponseBody boolean active(Long accountId) {
    return accountService.activeAccount(accountId);
}

@RequestMapping("active")
public @ResponseBody boolean active(Account account) {
    return accountService.activeAccount(accountId);
}

@RequestMapping("inactive")
public @ResponseBody boolean inactive(@RequestParam("accountId") Long accountId,
            @RequestHeader(
"User-Agent") String userAgent,
            @CookieValue(
"loginId") String loginId) {
    
return accountService.inactiveAccount(accountId);
}

@RequestMapping(value 
= "list/{pageNo}", method = RequestMethod.GET)
public String list(@PathVariable int pageNo) {
     
return "/account/list";
}

@RequestMapping(value = "add", method = RequestMethod.GET)
public String add(@RequestBody String body) {
     return "/account/add";
}



active方法的入參 accountId,若是請求中有名爲 accountId的參數,則會進行默認綁定,不只基本類型,javabean的屬性也能夠默認進行綁定;
若是須要明確綁定,使用@RequestParam。 通常建議進行明確指定。

3.1 @RequestParam 綁定httpRequest中參數,@RequestParam("accountId") 完整形式爲  @RequestParam(value="accountId",required=true,defaultValue=null)
3.2 @RequestHeader 綁定httpRequest頭部信息,@RequestHeader("User-Agent") 完整形式爲 @RequestHeader(value="User-Agebt",required=true, defaultValue=null)
3.3 @CookieValue 綁定一個Cookie值,@CookieValue("loginId") 完整形式爲 @CookieValue(value="loginId",required=true,defaultValue=null)
3.4 @RequestBody 將httpRequest的body綁定到方法參數上
3.5 @ModelAttribute 有兩種使用方式: 1)在方法級別,指定方法的返回值綁定到model中; 2)方法參數級別,指定model中的值綁定到方法的入參上 示例以下:

 @ModelAttribute("countryList")
    
public List<String> getCountries() {
        
return new ArrayList<String>();
    }

@RequestMapping(value 
= "search", method = RequestMethod.POST)
    
public String searchAccount(@ModelAttribute("accountId") Long accountId) {
        
return "/search";
    }

四、使用@ResponseBody 生成response

    適用於webservice的數據交換,或ajax異步請求,text、json或者xml格式的數據交換。
    例如訪問: http://localhost:8080/accounts/info.htm
 

@RequestMapping(value = "info")
public @ResponseBody Account getAccount() {
        Account a 
= new Account();
        a.setId(
123L);
        a.setName(
"zhangsan");
        
return a;
 }


返回數據以下:

{"name":"zhangsan","id":123}

從上面例子能夠看出,使用@ResponseBody後,返回的javabean默認被序列化成json格式的數據並被寫入到response body中。

@Request 和 @ReponseBody 使用了HttpMessageConverter機制。下面是HttpMessageConverter的繼承體系。

基於註解的SpringMVC
經常使用的有以下幾個:

StringHttpMessageConverter ---字符串

MappingJacksonHttpMessageConverter ----json

ByteArrayHttpMessageConverter ----字節數組

MarshallingHttpMessageConverter -----xml

五、使用模板技術生成response

    適用於通常頁面請求。可使用velocity freemarker等模板技術,在dispatcher-servlet.xml中須要設置viewResolver。
   

@RequestMapping("/index")
public String index(ModelMap modelMap) {
        modelMap.put(
"name""liucs");
        
return "index";
}

@RequestMapping(
"/index")
public String index2(Model model) {
        model.addAttribute(
"name","liucs");
        
return "index";
}

@RequestMapping("/index")
public ModelAndView index3() throws Exception {
      ModelAndView mav = new ModelAndView("index");
      mav.addObject("name", "liucs");
      return mav;
}


如上面代碼index1和index2所示,不使用@ResponseBody註解。 返回一個String類型,這個String是viewname, 若是是重定向,return "redirect:/index.htm".
入參能夠包含ModelMap或者Model,其實這二者是一個東西,做用同樣。也能夠採用index3式的傳統寫法,返回一個ModelAndView對象。

六、數據驗證

@InitBinder標註

@InitBinder
    
public void myInitBinder(WebDataBinder binder){
      binder.setDisallowedFields(
new String[]{"id"});
    }

經過在方法中聲明一個BindingResult參數來啓動綁定和驗證

@RequestMapping("update")
    
public void update(@ModelAttribute("account") Account account,BindingResult bindResult) {
        
if(bindResult.hasErrors()){
            
//……
        }
    }

須要注意如下限制:
一、BindingResult參數必須跟在一個JavaBean參數後面
二、錯誤會被自動的綁定到model中,便於渲染模板時使用
三、不支持@RequestBody等類型的參數形式

七、異常處理

@ExceptionHandler


獲取【下載地址】   

相關文章
相關標籤/搜索