Spring Framework--SpringMVC(2)--Controller(1)

  Controller (控制器)通过一个服务接口提供了对Web应用功能的调用;控制器解释用户的输入并把它转换成一个模型(model),通过视图(View)展现给用户。Spring实现的控制器采用的是一种抽象的方式,这样使得创建更多不同的控制器成为可能。Spring从2.5版本开始为Controller引入了基于注解的编程模型(比如:@Controller,@RequestMapping,@RequestParam,@ModelAttribute等等),这些注解支持在ServletMVC,PortletMVC框架下也是可用的。这种基于注解方式实现的控制器不需要继承特定的基类,也不需要实现特定的接口,甚至不需要依赖于Servlet和Portlet API,但是我们可以容易地配置它来访问Servlet和Portlet的功能。很多web应用都在使用这种基于注解的方式,比如:MvcShowcase, MvcAjax, MvcBasic, PetClinic, PetCare, and others.

1、使用@Controller注解定义一个控制器

  使用了@Controller注解的类,表示这个类充当的是一个控制器,DispatcherServlet会扫描含有这个注解的类,并且检测映射方法。你可以在DispatcherServlet的上下文中像配置普通的bean一样显示地配置这些Controller,也可以使用Spring通用的自动检测bean功能。要使用这种自动检测bean的功能,需要在配置文件中添加自动组件扫描功能,方式是使用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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="org.springframework.samples.petclinic.web"/>
<!-- ... -->
</beans>

2、使用@RequestMapping映射请求到一个处理器方法。

  我们一般使用@RequestMapping注解来把基于URLs的请求(如:/home)映射到整个类或者类中的一个处理方法上。特别地,类级别的注解是把一个请求路径(或者路径模式)映射到一个表单控制器,然后方法级别的注解把这个主映射限制到某一个具体的http请求方法(“GET”,“POST”,etc)或者http请求参数条件。如:

@Controller
@RequestMapping("/appointments")
public class AppointmentsController {
private final AppointmentBook appointmentBook;
@Autowired
public AppointmentsController(AppointmentBook appointmentBook) {
this.appointmentBook = appointmentBook;
}
@RequestMapping(method = RequestMethod.GET)
public Map<String, Appointment> get() {
return appointmentBook.getAppointmentsForToday();
}
@RequestMapping(value="/{day}", method = RequestMethod.GET)
public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE)
Date day, Model model) {
return appointmentBook.getAppointmentsForDay(day);
}
@RequestMapping(value="/new", method = RequestMethod.GET)
public AppointmentForm getNewForm() {
return new AppointmentForm();
}
@RequestMapping(method = RequestMethod.POST)
public String add(@Valid AppointmentForm appointment, BindingResult result) {
if (result.hasErrors()) {
return "appointments/new";
}
appointmentBook.addAppointment(appointment);
return "redirect:/appointments";
}
}

  使用类级别注解,表示在这个控制器里的所有方法注解的映射URL路径都是相对于类上面的路径,如果类上没有url路径,则方法上的url路径都是绝对路径。

  在有些情况下,@RequestMapping注解需要放到接口方法上,比如在使用基于接口的JDK代理时。但是方法参数的注解(如:RequestParam)是必须要放在控制器类的方法里的。

  (1)URL模版模式,如:

@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {...}

如果方法的参数名称和路径中变量名一致,那么@PathVariable里的参数可以省略,上面方法也可以写成:public String findOwner(@PathVariable String ownerId, Model model) {...}

  (2)URL模版中使用正则表达式,语法是:{varName:regex},如:

@RequestMapping("/spring-web/{symbolicName:[a-z-]}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]}")
public void handle(@PathVariable String version, @PathVariable String extension) {...}

  (3)URL路径可以采用ant风格,?表示任意一个字符,*表示任意字符串,**表示任意路径,如:/owners/*/pets/{petId}

  (4)URL中可以包含占位符,语法是${...},...表示一个本地属性,系统属性或者环境变量的值,参考:PropertyPlaceholderConfigurer

  (5)URL可以包含用分号(;)分隔的键值对参数,我们称之为矩阵变量,为了映射这种路径,使用注解@MatrixVariable,如:

//一个请求: GET /owners/42;q=11/pets/21;q=22    
@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
public void findPet(@MatrixVariable(value="q", pathVar="ownerId") int q1,@MatrixVariable(value="q", pathVar="petId") int q2) {
// q1 == 11
// q2 == 22
}

  (6)通过一个请求的请求头Content-Type的值来限制请求映射到特定的方法,如下,只有当请求头的Content-Type为application/json时,才会使用这个方法处理请求。

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {...}

consumes的值还可以使用取反表达式!expression,如!text/plain表示所有Content-Type不是text/plain,如果在类级别和方法级别都定义了consumes,那么以方法为准。

  (7)通过一个请求的请求头Accept的值来限制请求映射到特定的方法,如下,只有当请求头的Accept为application/json时,才会使用这个方法处理请求。

@RequestMapping(value = "/pets/{petId}", method =RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {...}

 produces的值还可以使用取反表达式!expression,如!text/plain表示所有Accept不是text/plain,如果在类级别和方法级别都定义了produces,那么以方法为准。

  (8)通过URL中的参数或者请求头中的参数来限制请求映射到一个处理方法,语法为:

  a. 使用URL参数:params={param condition},其中param condition为:myParam, !myParam, myParam=myValue,分别表示参数存在,不存在,或者等于某个具体的值,如:

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
  @RequestMapping(value = "/pets/{petId}", method =RequestMethod.GET, params="myParam=myValue")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {...}
}

  b. 使用请求头中的参数:headers={header condition},其中header condition为:myHeader, !myHeader, myHeader=myValue,分别表示参数存在,不存在,或者等于某个具体的值,如:

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
  @RequestMapping(value = "/pets", method =RequestMethod.GET, headers="myHeader=myValue")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {...}
}

 

 

posted on 2014-04-14 11:31  leungrs  阅读(290)  评论(0编辑  收藏  举报