第17章基于注解的控制器0117.1SpringMVC常用注解02030417.2在SpringMVC中处理模型数据17.3基于注解的控制器示例117.4基于注解的控制器示例2本章导读从Spring2.5开始引入注解,使用注解的方式可以减少XML的配置,也提供了自动装配的功能,使得开发工作变得更为轻松,这实际上是“约定优于配置”的开发原则。0117.1SpringMVC常用注解使用基于注解的控制器有以下两个优点:(1)一个使用基于注解的控制器可以处理多个动作,而一个实现了Controller接口的控制器只能处理一个动作。这就允许将相关的操作写在同一个控制器类中,从而减少应用程序中类的数量。(2)基于注解的控制器的请求映射不需要存储在配置文件中。使用RequestMapping注解类型,可以对一个方法进行请求处理。0117.1SpringMVC常用注解org.springframework.stereotype.Controller注解类型用于指示Spring类的实例是一个控制器,其注解形式是@Controller,SpringMVC使用扫描机制查找应用程序中所有基于注解的控制器类(使用@Controller标记的类)。分发处理器会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解,而使用@RequestMapping注解的方法才是真正处理请求的处理器。为了保证Spring能找到你的控制器,需要在SpringMVC的配置文件中添加相应的扫描配置信息。17.1.1@Controller和@RequestMapping0117.1SpringMVC常用注解@RequestMapping注解可以在控制器类的级别和(或)控制器类中的方法的级别上使用。在类的级别上的注解会将一个特定请求或者请求模式映射到一个控制器之上。之后还可以另外添加方法级别的注解来进一步指定到处理方法的映射关系。17.1.1@Controller和@RequestMapping0117.1SpringMVC常用注解SpringMVC还定义了处理器的拦截器,当启动SpringMVC的时候,SpringMVC就会解析@Controller中的@RequestMapping的配置,再结合所配置的拦截器,这样它就会组成多个拦截器和一个控制器的形式,存放到一个HandlerMapping中去。当请求来到服务器,首先是通过请求信息找到对应的HandlerMapping,进而可以找到对应的拦截器和处理器,这样就能够运行对应的控制器和拦截器。17.1.1@Controller和@RequestMapping0117.1SpringMVC常用注解将依赖注入到SpringMVC控制器的最简单方法是通过注解@Autowired到字段(属性)或方法。Autowired注解类型属于org.springframework.beans.factory.annotation包。被定位于实现业务逻辑功能的Service,为了能被作为依赖注入,类必须要声明为@Service,该类型是org.springframework.stereotype的成员。Service注解类型指示类是一个服务。此外,在SpringMVC配置文件中,还需要添加自动扫描控制器(Contoller)所在的包以及服务(Service)所在的包的代码。17.1.2@Autowired和@Service0117.1SpringMVC常用注解@RequestParam用于将请求参数区数据映射到功能处理方法的参数上。例如下面的示例代码:17.1.3@RequestParam和@PathVariable这里@RequestParam注解可以用来提取请求参数区数据名为“num”的String类型的参数,并将之作为输入参数传给number。0117.1SpringMVC常用注解这里请求参数区数据可以是URL请求中的参数,也可以是提交表单中的参数。例如针对前一种可假设URL请求如下:=168针对后一种可假设提交表单如下:17.1.3@RequestParam和@PathVariable0117.1SpringMVC常用注解@PathVariable可以用来映射URL中的占位符到目标方法的参数中。例如有以下的代码:17.1.3@RequestParam和@PathVariable如请求的URL为“控制器URL/users/123/topics/456”,则自动将URL中模板变量{userId}和{topicId}绑定到通过@PathVariable注解的同名参数上,即入参后userId=123、topicId=456。0117.1SpringMVC常用注解考虑浏览器和服务器之间的交互。当用户第1次访问服务器时,服务器会在响应消息中增加Set-Cookie头字段,将用户信息以Cookie的形式发送给浏览器。一旦用户浏览器接受了服务器发送的Cookie信息,就会将它保存在浏览器的缓冲区中。这样,当浏览器后续访问该服务器时,都会在请求信息中将用户信息以Cookie的形式发送给Web服务器,从而使服务器端分辨出当前请求是由哪个用户发出的。使用@Cookie注解可以将请求的Cookie数据映射到功能处理方法的参数上。17.1.4@CookieValue和@RequestHeader0117.1SpringMVC常用注解org.springframework.web.bind.annotation.RequestHeader注解类型用于将请求的头信息区数据映射到功能处理方法的参数上。在控制器的方法参数中使用@RequestHeader注解,能够从Http请求头中提取指定的某个请求头,可以说等价于HttpServletRequest.getHeader(String)。17.1.4@CookieValue和@RequestHeader0217.2在SpringMVC中处理模型数据ModelAndView有一个类型为ModelMap的属性model,而ModelMap继承了LinkedHashMapString,Object,因此可以存放各种键值对。为了进一步定义数据模型功能,Spring还创建了类ExtendedModelMap,这个类实现了数据模型定义的Model接口,如图17-1所示,并且还在此基础上派生了关于数据绑定的类BindingAwareModelMap。17.2.1数据模型0217.2在SpringMVC中处理模型数据在控制器的方法中,可以把ModelAndView、Model、ModelMap作为参数。在SpringMVC运行的时候,会自动初始化它们,因此可以选择ModelMap或者Model作为数据模型。事实上SpringMVC创建的是一个BindingAwareModelMap实例。ModelAndView初始化后,model属性为空,当调用它增加数据模型的方法后,会自动创建一个ModelMap实例,用以保存数据模型。17.2.1数据模型0217.2在SpringMVC中处理模型数据SpringMVC提供了以下几种途径输出模型数据:17.2.1数据模型0217.2在SpringMVC中处理模型数据可将控制器处理方法的返回值设为ModelAndView,ModelAndView中既可存放视图信息,也可存放模型数据信息。SpringMVC会把ModelAndView的model中数据放入到request域对象中。17.2.2ModelAndView0217.2在SpringMVC中处理模型数据SpringMVC在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器(事实上这个隐含的模型对象是一个BindingAwareModelMap类型的对象,通过后面的例子我们可以验证),如果方法的入参为Map、Model或者ModelMap类型,SpringMVC会将隐含模型的引用传递给这些入参(因为BindingAwareModelMap继承或实现了Map、Model或者ModelMap)。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据,SpringMVC也会把Map中数据放入到request域对象中。17.2.3Map及Model0217.2在SpringMVC中处理模型数据上面介绍的两种方式,SpringMVC都是将数据存放在request域对象中,若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个@SessionAttributes注解(该注解只能放在类的上面,而不能修饰放方法),SpringMVC将把模型中对应的属性暂存到HttpSession中。@SessionAttributes除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中。17.2.4@SessionAttributes0217.2在SpringMVC中处理模型数据SpringMVC在每次调用请求处理方法时,都会创建Model类型的一个实例。若打算使用该实例,则可以在方法中添加一个Model类型的参数。除此之外,我们还可以使用在方法中添加org.springframework.web.bind.annotation.ModelAttribute注解类型将请求参数绑定到Model对象。17.2.5@ModelAttribute0217.2在SpringMVC中处理模型数据@ModelAttribute注解只支持一个属性value,类型为String,表示绑定的属性名称。可以用@ModelAttribute来注解方法参数或方法。带@ModelAttribute注解的方法(请求方法),会将其输入的或创建的参数对象添加到Model对象中(若方法中没有显式地增加)。17.2.5@ModelAttribute0217.2在SpringMVC中处理模型数据@ModelAttribute还可以标注一个非请求的处理方法。被@ModelAttribute注解的方法,会在每次调用该控制器类的请求处理方法时被调用。SpringMVC会在调用请求处理方法之前调用带有@ModelAttribute注解的方法。带@ModelAttribute注解的方法可以返回一个对象或一个void类型。如果返回一个对象,则返回对象会自动添加到Model中;若方法返回void,则还必须添加一个Model类型的参数,并自行将实例添加到Model中。17.2.5@ModelAttribute0317.3基于注解的控制器示例1本示例着是对前面章节中SpringMVC_Basic_Demo2工程的改写。由于使用注解类型来开发,一个控制器类可以包含多个请求处理方法。原本在SpringMVC_Basic_Demo2工程中的两个控制器AddBookController和SaveBookController,这里用一个控制器替代就可以了,这个控制器是BookController。而控制器BookController包含了两个请求方法,其请求映射分别是/book_add和/book_save。0417.4基于注解的控制器示例2本示例着重说明:①如何使用@Autowired和@Service进行依赖注入;②Spring如何通过Flash属性进行重定向传值;③@PathVariable使用;④Spring组件自动扫描机制。本章小结本章主要介绍了SpringMVC中的一些常用注解的使用,这里包括@Controller和@RequestMapping、@Autowired和@Service、@RequestParam和@PathVariable、@CookieValue和@RequestHeader、@SessionAttributes和@ModelAttribute、@Resource和@Qu