基于注解的SpringMVC

基于注解的SpringMVC

一、概述

SpringMVC在2.5版本后新增了注解功能,2.5版本以前的基本通过继承Controller体系来开发业务控制器,2.5版本后Controller体系中
BaseCommandController及其子类AbstractCommandController、AbstractFormController、AbstractWizardFormController、
SimpleFormController、CancellableFormController等都已经被标示为@Deprecated,建议不再使用。

相比传统的继承Controller体系中某些类的方式,SpringMVC的注解具有以下优点:
1、Controller不再需要继承某个特定类,只是简单的POJO。
2、请求映射的配置非常方便灵活。
3、参数绑定机制非常方便丰富。
4、可以根据不同的http方法或者参数,细粒度处理不同的http请求

二、示例

下面通过对SpringMVC注解的详细介绍来看一下上述优点。

首先需要在应用的dispatcher-servlet.xml 启动注解机制
< 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包中。
1、@Controller注解
简单示例
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层的数据访问。

2、使用@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  {};

}
注:如果在类层次指定了映射,则方法层次上都将继承类层次的映射

3、获取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 " ;
    }
4、使用@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的继承体系。


常用的有如下几个:
StringHttpMessageConverter ---字符串
MappingJacksonHttpMessageConverter ----json
ByteArrayHttpMessageConverter ----字节数组
MarshallingHttpMessageConverter -----xml
5、使用模板技术生成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对象。
6、数据验证
@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()){
            
// ……
        }
    }
需要注意以下限制:
1、BindingResult参数必须跟在一个JavaBean参数后面
2、错误会被自动的绑定到model中,便于渲染模板时使用
3、不支持@RequestBody等类型的参数形式
7、异常处理
@ExceptionHandler
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值