`

spring 基于注解的控制器配置

阅读更多

13.12. 基 于注解的控制器配置

现时对于一些类型的配置数据有一个趋势,就是偏爱注解方式而不是XML文件。为了方便实现,Spring现在(从2.5开始)提供了使用注解配置 MVC框架下的组件的支持。

Spring 2.5为MVC控制器引入了一种基于注解的编程模型,在其中使用诸如@RequestMapping@RequestParam@ModelAttribute , 等等。 这种注解支持在Servlet MVC和Portlet MVC中均可使用。通过这种方式实现的控制器不必由特定的基类继承而来,或者实现特定的接口。 更进一步的,它们通常并不直接依赖于Servlet或Portlet API,虽然如果需要,它们可以方便的访问Servlet或Portlet的功能。

提示

Spring发行版本附带了PetClinic 示例,它是一个在 简单的表单处理的上下文中, 利用了本节中说明的注解支持的Web应用程序。 可以在“samples/petclinic ”目录中找到PetClinic 应用程序。

另外一个建立在基于注解的Web MVC上的示例应用程序,请见imagedb 。 这个示例集中在无状态的multi-action控制器,包括多段文件上传的处理。 可以在“samples/imagedb ”目录找到imagedb 应用程序。

下面的章节记录了这些注解以及通常如何使用它们。

13.12.1. 建立dispatcher实现注解支持

只有对应的HandlerMapping (为了实现类型级别的注解)和/ 或HandlerAdapter (为了实现方法级别的注解)出现在 dispatcher中时, @RequestMapping 才 会被处理。 这在DispatcherServletDispatcherPortlet 中都是缺省的行为。

然而,如果是在定义自己的HandlerMappingsHandlerAdapters , 就需要确保一个对应的自定义的DefaultAnnotationHandlerMapping 和 /或AnnotationMethodHandlerAdapter 同样被定义——假设 想要使用@RequestMapping

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean class="org.springframework.web.servlet.mvc.DefaultAnnotationHandlerMapping"/>

    <bean class="org.springframework.web.servlet.mvc.AnnotationMethodHandlerAdapter"/>

    ... (controller bean definitions) ...

</beans>

如果你想要自定义映射策略,显式的定义一个DefaultAnnotationHandlerMapping 和 /或AnnotationMethodHandlerAdapter 也有实际意义。 例如,指定一个自定义的PathMatcher 或者WebBindingInitializer (见下面)。

13.12.2. 使用@Controller 定 义一个控制器

注解@Controller 指明一个特定的类承担控制器 的职责, 而没有扩展任何控制器基类或者引用Servlet API的必要。当然,如果需要还是可以引用特定Servlet功能。

注解@Controller 的基本目标是担任所注解的类的原型的角色,指 明它的职责。 Dispatcher将会在这样被注解的类中扫描映射的方法,探测注解@RequestMapping (见 下一节)。

所注解的控制器bean可以被显式定义,这个过程是在dispatcher的上下文中使用一个标准的Spring bean定义完成的。 然而,@Controller 原型也允许自动探测,就像 Spring 2.5对探测组件的类以及为它们自动注册bean定义的普遍支持一样。

要实现对这样的所注解的控制器的自动探测,必须要向配置中加入组件扫描的部分。 通过使用在下面的XML片段中所展示出的spring-context schema,这很容易实现:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:component-scan base-package="org.springframework.samples.petclinic.web"/>

    ...

</beans>

13.12.3. 使用@RequestMapping 映射请求

注解@RequestMapping 被用于映射如 “/editPet.do”这样的URL到一个完整的类或者一个特定的处理方法。 典型的,顶层的注解映射一个特定的请求路径(或者路径模式)到一个表单控制器,另外的方法一级的注解可以缩小这个主要映射的范围,包括对于一个特定的 HTTP请求方法(“GET/POST”)或者特定的HTTP请求参数。

提示

@RequestMapping 在类型一级也可以被用于Controller 接口的普通实现。 在这种情况下,请求处理的代码会遵循传统的handleRequest 模 样,而控制器的映射将会通过一个@RequestMapping 注解体现。 这对于预先构建的Controller 基类,诸如SimpleFormController ,也一样有效。

在下面的讨论中,我们将会关注基于通过注解实现的处理方法的控制器。

下面是一个使用了这种注解的表单控制器的例子,它选自PetClinic:

@Controller
@RequestMapping("/editPet.do")


@SessionAttributes("pet")
public class EditPetForm {

	private final Clinic clinic;

	@Autowired
	public EditPetForm(Clinic clinic) {
		this.clinic = clinic;
	}

	@ModelAttribute("types")
	public Collection<PetType> populatePetTypes() {
		return this.clinic.getPetTypes();
	}

	@RequestMapping(method = RequestMethod.GET)


	public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
		Pet pet = this.clinic.loadPet(petId);
		model.addAttribute("pet", pet);
		return "petForm";
	}

	@RequestMapping(method = RequestMethod.POST)


	public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, 
			SessionStatus status) {
		new PetValidator().validate(pet, result);
		if (result.hasErrors()) {
			return "petForm";
		}
		else {
			this.clinic.storePet(pet);
			status.setComplete();
			return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
		}
	}

}

对于一个传统的multi-action控制器,由于控制器会响应多个URL,URL就通常被直接映射到方法上。 下面是一个使用了@RequestMapping 的multi- action控制器的例子,它选自PetClinic:

@Controller
public class ClinicController {

	private final Clinic clinic;

	@Autowired
	public ClinicController(Clinic clinic) {
		this.clinic = clinic;
	}

	/**
	 * Custom handler for the welcome view.
	 * Note that this handler relies on the RequestToViewNameTranslator to
	 * determine the logical view name based on the request URL: "/welcome.do"
	 * -> "welcome".
	 */
	@RequestMapping("/welcome.do")


	public void welcomeHandler() {
	}

	/**
	 * Custom handler for displaying vets.
	 * Note that this handler returns a plain {@link ModelMap} object instead of
	 * a ModelAndView, thus leveraging convention-based model attribute names.
	 * It relies on the RequestToViewNameTranslator to determine the logical
	 * view name based on the request URL: "/vets.do" -> "vets".
	 *
	 * @return a ModelMap with the model attributes for the view
	 */
	@RequestMapping("/vets.do")


	public ModelMap vetsHandler() {
		return new ModelMap(this.clinic.getVets());
	}

	/**
	 * Custom handler for displaying an owner.
	 * Note that this handler returns a plain {@link ModelMap} object instead of
	 * a ModelAndView, thus leveraging convention-based model attribute names.
	 * It relies on the RequestToViewNameTranslator to determine the logical
	 * view name based on the request URL: "/owner.do" -> "owner".
	 *
	 * @param ownerId the ID of the owner to display
	 * @return a ModelMap with the model attributes for the view
	 */
	@RequestMapping("/owner.do")


	public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) {
		return new ModelMap(this.clinic.loadOwner(ownerId));
	}

}

使用@RequestMapping 注解的处理器方法允许具有非常灵活的外 观。 它们可以拥有下面类型的参数,在任意的顺序下(除非是对于验证结果,它需要紧跟在对应的命令对象后面,如果需要):

  • 请求和/或响应对象(Servlet API或者Portlet API)。 可以选择任何特定的请求/响应类型,例如,ServletRequest/HttpServletRequest或者PortletRequest /ActionRequest/RenderRequest。 注意那个Portlet的例子里,一个被显式声明了的action/render参数被用于映射特定的请求类型到一个处理方法(在没有提供其他信息来区分 action和render requests的情况下)。

  • 会话对象(Servlet API或者Portlet API):不管是HttpSession还是PortletSession。 一个此种类型的参数将会保证出现一个对应的会话。这样就造成,这样一个参数永远也不可以是null注意会话访问可以并不是线程安全的,特别是在Servlet环境中:如果允 许多个请求同时访问一个会话,就考虑把AnnotationMethodHandlerAdapter 的 “synchronizeOnSession”旗标置为“true”

  • org.springframework.web.context.request.WebRequestorg.springframework.web.context.request.NativeWebRequest 。 允许像访问请求/会话属性一样的访问一般的请求参数,而不是锁定在原生的Servlet/Portlet API上。

  • java.util.Locale 用于当前请求区域属性(由可用的最接近 的区域属性解析器决定,也就是, 在Servlet环境中配置好的LocaleResolver 以 及在Portlet环境中的portal locale)。

  • java.io.InputStream /java.io.Reader 用于访问请求的内容。 这将是Servlet/Portlet API暴露出的天然的InputStream/Reader。

  • java.io.OutputStream /java.io.Writer 用于生成响应的内容。 这将是Servlet/Portlet API暴露出的天然的OutputStream/Writer。

  • @RequestParam 注解的参数用于访问特定的 Servlet/Portlet请求参数。 参数的值将被转换为声明的方法参数类型。

  • java.util.Map /org.springframework.ui.Model /org.springframework.ui.ModelMap 用于充实将被暴露到Web视图的隐 含模型。

  • 绑定参数到的命令/表单对象:带有自定义的类型转换的bean属性或者域,依赖于@InitBinder 方 法和/或HandlerAdapter配置——参见AnnotationMethodHandlerAdapter 的“webBindingInitializer ”属性。 这样的命令对象,包括它们的验证结果,将会暴露为模型属性,默认的会在属性注解中使用非限定的命令类名(例如,对于类型 “mypackage.OrderAddress”使用“orderAddress”)。 为声明一个特定的模型属性名称指定一个参数级别的ModelAttribute 注 解。

  • org.springframework.validation.Errors /org.springframework.validation.BindingResult 验证 结果用于前面的一个命令/表单对象(前面紧接的参数)。

  • org.springframework.web.bind.support.SessionStatus 状 态处理用于把表单处理过程标记为已完成(触发会话属性的清理,这些会话属性是在句柄类型级别由@SessionAttributes 注 解指示出的)。

13.12.4. 使用@RequestParam 绑 定请求参数到方法参数

@RequestParam 注解是用于在控制器中绑定请求参数到方法参数。

下面取自PetClinic实例程序的代码片段说明了这种用法:

@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
public class EditPetForm {

    // ...



	@RequestMapping(method = RequestMethod.GET)
	public String setupForm(@RequestParam("petId") int petId

, ModelMap model) {
		Pet pet = this.clinic.loadPet(petId);
		model.addAttribute("pet", pet);
		return "petForm";
	}

    // ...


使用这个注解的参数默认是必需的,但是可以把@RequestParamrequired 属性置为false 从而 让这个参数可选(例如,@RequestParam(value="id", required="false") )。

13.12.5. 使用@ModelAttribute 提 供一个从模型到数据的链接

@ModelAttribute 在控制器中有两种使用场景。 当作为一个方法参数时,@ModelAttribute 用于映射一个模型属 性到特定的注解的方法参数(见下面的processSubmit() 方法)。 这是控制器获得持有表单数据的对象引用的方法。另外,这个参数也可以被声明为特定类型的表单支持对象,而不是一般的java.lang.Object ,这就增加了类型安全性。

@ModelAttribute 也用于在方法级别为模型提供引用数据 (见下面的populatePetTypes() 方 法)。 在这种用法中,方法编写可以包含与上面描述的@RequestMapping 注 解相同的类型。

注意: 使用@ModelAttribute 注 解的方法将会在选定的使用@RequestMapping 注解的方法之前 执行。 它们有效的使用特定的属性预先填充隐含的模型,这些属性常常来自一个数据库。 这样一个属性也就可以通过在选定的方法中使用@ModelAttribute 注 解的句柄方法参数来访问了,潜在的可以应用绑定和验证。

下面的代码片段展示了此注解的这两种用法:

@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
public class EditPetForm {

	// ...



	@ModelAttribute("types")


	public Collection<PetType> populatePetTypes() {
		return this.clinic.getPetTypes();
	}

	@RequestMapping(method = RequestMethod.POST)
	public String processSubmit(@ModelAttribute("pet") Pet pet

, BindingResult result,
			SessionStatus status) {
		new PetValidator().validate(pet, result);
		if (result.hasErrors()) {
			return "petForm";
		}
		else {
			this.clinic.storePet(pet);
			status.setComplete();
			return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
		}
	}

}

13.12.6. 使用@SessionAttributes 指 定存储在会话中的属性

类型级别的@SessionAttributes 注解使用一个特定的句柄声明会话 属性。 这通常会列出模型属性的名称,这些属性应被透明的保存在会话或者对话存储中,用于在后续的请求之间作为表单支持beans。

下面的代码片段展示了此注解的这种用法:

@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")


public class EditPetForm {
    // ...


}

13.12.7. 自定义WebDataBinder 初 始化

为了通过Spring的WebDataBinder 使用 PropertyEditors等自定义请求参数绑定,可以或者使用@InitBinder —— 在控制器之内的注解的方法, 或者通过提供一个定制的WebBindingInitializer 把 配置具体化。

13.12.7.1. 使用@InitBinder 自定义数据绑定

使用@InitBinder 注解控制器方法,可以在控制器类内部直接配置 Web数据绑定。 @InitBinder 指定初始化WebDataBinder 的方法, 后者被用于填充注解的句柄方法的命令和表单对象参数。

这个init-binder方法支持@RequestMapping 支持 的全部参数,除了命令/表单对象和对应的验证结果对象。 Init-binder方法必须没有返回值。因此,它们常被声明为void 。 典型的参数,包括 WebDataBinder 以及WebRequest 或者java.util.Locale , 允许代码注册上下文特定的编辑器。

下面的例子说明了@InitBinder 的用法,为所有的java.util.Date 表单属性配置一个CustomDateEditor

@Controller
public class MyFormController {

    @InitBinder


    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
    }

    // ...


}

13.12.7.2. 配置一个定制的WebBindingInitializer

为了外化数据绑定初始化的过程,可以提供一个WebBindingInitializer 接 口的自定义实现。 通过为一个AnnotationMethodHandlerAdapter 提 供一个定制的bean配置可以使它启用,这样就覆盖了默认配置。

下面取自PetClinic应用的例子展示了一个使用WebBindingInitializer 接 口的自定义实现的配置——org.springframework.samples.petclinic.web.ClinicBindingInitializer , 完成多个PetClinic控制器都需要的PropertyEditors的配置。

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="cacheSeconds" value="0" />
    <property name="webBindingInitializer">
        <bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" />
    </property>
</bean>
分享到:
评论
2 楼 ttaale 2011-04-06  
muqingren 写道
文档拷贝啊


恩。做个记录方便用到的时候查!
1 楼 muqingren 2011-03-31  
文档拷贝啊

相关推荐

    Spring基于注解的缓存配置--web应用实例

    在本实例中,我们将深入探讨如何在Spring框架中利用注解来实现缓存配置,特别是在Web应用程序中的实际应用。Spring Cache是一个强大的功能,它允许我们高效地管理应用程序中的数据,减少不必要的数据库查询,提高...

    spring famework 基于注解配置示例

    然而,随着注解(Annotation)技术的发展,Spring框架引入了基于注解的配置,使得代码更加简洁、直观。本示例将详细介绍如何使用注解配置实现Spring框架的注入。 首先,我们需要了解几个关键的注解: 1. `@...

    Quartz2.2.1基于Spring注解方式配置Quartz

    总结,通过上述步骤,我们已经成功地使用Spring注解配置了Quartz2.2.1,实现了基于注解的任务调度。这种方式简化了配置,使得任务管理和扩展更加方便。在实际开发中,可以根据项目需求调整触发规则,实现复杂的定时...

    使用 Spring 2.5 基于注解驱动的 Spring.pdf

    Spring 2.5基于注解驱动的SpringMVC配置方式代表了现代Web应用开发的一个重要趋势——减少XML配置,增强代码的自描述性和可维护性。通过上述核心注解的使用,开发人员能够更快速、高效地构建响应式、可扩展的Web应用...

    基于注解和Spring的多数据源配置和使用

    本篇文章将深入探讨如何基于注解和Spring实现多数据源配置和使用。 首先,我们需要理解"注解"在Java中的作用。注解是一种元数据,它提供了一种安全的方法来关联信息和代码(类、方法、变量等)。Spring框架广泛使用...

    spring2.5基于注解例子程序

    综上所述,这个"spring2.5基于注解的例子程序"涵盖了Spring 2.5的核心特性,包括注解驱动的配置、自动扫描、基于注解的事务管理、AOP支持、MVC框架的使用,以及依赖注入等。通过学习和理解这个例子,开发者可以更好...

    使用 Spring 2_5 基于注解驱动的 Spring MVC

    在本主题中,我们将深入探讨Spring框架的2.5版本引入的一个重要特性——基于注解的Spring MVC配置。Spring MVC是Spring框架的一部分,专门用于构建Web应用程序,它提供了一个模型-视图-控制器(MVC)架构来组织和...

    spring基于注解的上传

    在Spring框架中,基于注解的文件上传是一种高效且便捷的方式,它允许开发者在控制器方法上使用注解来处理文件上传请求。这篇博客主要探讨了如何利用Spring的`@RequestParam`、`@RequestPart`以及自定义Multipart...

    基于注解Spring MVC环境搭建

    总的来说,基于注解的Spring MVC环境搭建涉及众多步骤,从设置项目结构、配置MVC组件、编写控制器到测试和部署。这个过程旨在减少配置工作,提高开发效率,同时利用Spring强大的功能来构建健壮的Web应用程序。通过...

    基于注解的Spring JdbcTemplate

    **基于注解的Spring JdbcTemplate** 在Java世界中,Spring框架是企业级应用开发的首选。Spring JDBC模絫提供了一种简洁的方式来处理数据库操作,而`Spring JdbcTemplate`是这个模絫的核心组件。本教程将深入探讨...

    Spring 2.5 基于注解驱动的Spring MVC

    Spring 2.5引入了一种基于注解的新方式来驱动Spring MVC框架,使得开发者能够更加简洁、直观地配置和管理控制器。这一变化显著提升了开发效率,减少了XML配置文件的复杂性,同时也使得代码更加模块化。 ### 1. 基于...

    Spring MVC 的注解使用实例

    Spring MVC通过注解可以实现控制器、方法映射、模型数据绑定、视图解析等关键功能。本实例将深入探讨Spring MVC中常见的注解及其应用。 1. `@Controller` 注解:这个注解用于标记一个类作为Spring MVC的控制器。当...

    spring3注解详解

    Spring 3.0 是一个重要的版本,它引入了大量的注解,极大地简化了Spring框架的配置,使得开发人员能够更加专注于业务逻辑,而不再是XML配置。本文将深入解析Spring 3.0中的主要注解,帮助你更好地理解和使用它们。 ...

    s2sh+springSecurity的注解配置例子

    这些注解可以用来标记控制器方法,决定哪些用户或角色可以访问它们。例如,`@Secured("ROLE_ADMIN")`表示只有拥有"ROLE_ADMIN"角色的用户才能执行该方法。 接下来,我们需要配置Spring Security的核心组件,如`...

    使用 Spring 2.5 基于注解驱动的 Spring MVC.doc

    在Spring 2.5版本中,Spring MVC引入了一种新的编程模型,即基于注解的配置,这使得开发者能够更加简洁、直观地构建Web应用程序。本文将深入探讨Spring MVC注解的功能及其在Spring 2.5中的应用。 首先,Spring 2.5...

    基于注解配置和使用spring AOP(spring mvc框架)

    本篇文章将深入探讨如何在Spring MVC中配置和使用基于注解的AOP。 一、Spring AOP基础知识 1. **切面(Aspect)**:切面是关注点的模块化,例如日志、事务管理等。在Spring AOP中,切面可以是Java类或@Aspect注解...

    IOC之基于注解的配置bean(上)

    基于注解的配置是Spring实现IOC的一种方式,它减少了XML配置文件的使用,提高了开发效率。本篇文章将深入探讨如何在Spring中使用注解来配置Bean。 首先,我们需要了解Spring中的核心注解。`@Component`是基础注解,...

    springmvc+mybatis+spring注解

    标题 "springmvc+mybatis+spring注解" 描述了一个集成框架,该框架结合了Spring MVC、MyBatis和Spring的注解...通过解压并导入IDE,开发者可以快速启动并运行这个基于注解的SSM(Spring、SpringMVC、MyBatis)项目。

    基于注解的Spring_3.0.x_MVC

    在基于注解的 Spring 3.0.x MVC 中,使用 @Controller 注解来标注控制器 Bean,@RequestMapping 注解来标注请求映射关系,@Service 注解来标注服务 Bean,@Repository 注解来标注数据访问对象等。这种方式可以简化 ...

Global site tag (gtag.js) - Google Analytics