在线咨询

深入剖析Spring Web源码(十四) - 处理器映射,处理器适配器以及处理器的实现 - 处理器的实现架构 - 注解控制器


4.2.2.3.2 注解控制器

上一小结中,我们剖析了简单控制器的实现体系结构。事实上,自从Spring 2.5引进了注解方法控制器, 已经不推荐使用简单控制器的实现体系结构中的基于Form的实现类。

注解控制器是通过在一个简单的Java对象上声明具有元信息的注解来实现的。所以,注解控制器并没有接口,抽象类或者实体类的实现体系结构。然而,声明在简单的Java对象上的注解则扮演着至关重要的角色。

下面我们根据不同类型的注解进行剖析,

1.         标识控制器和控制器方法的注解

@Controller

一个注解控制器是通过注解@Controller标识的。注解@Controller比注解@Component具有更具体的语义,代表它不仅是应用程序环境中的一个Bean,而且还是一个注解控制器类型。注解@Component还有两个其他具有更具体语义的注解,@Repository和@Service。

注解@Componet和它具有更具体语义的注解都是通过XML环境中的标记<context:component-scan/>加载进入应用程序环境的。

@RequestMapping

注解控制器的处理器方法是通过注解@RequestMapping映射到一个适当的HTTP请求的。在注解@RequestMapping中,可以声明HTTP方法,HTTP参数,HTTP头信息以及更加重要的URL Pattern信息。这些信息全部是用来匹配一个HTTP请求的,如果匹配成功,则用当前声明注解@RequestMapping的处理器方法来处理当前HTTP请求。

注解@RequestMapping既能够声明在注解控制器类级别也能生命在注解控制器的处理器方法中。如果存在类级别的注解@RequestMapping,它将会结合方法级别的注解@RequestMapping一起参与匹配HTTP请求。

2.         声明初始化数据绑定方法的注解

@InitBinder

注解@InitBinder用于声明一个初始化数据绑定对象的方法,数据绑定对象用于对一个业务逻辑对象进行赋值的辅助对象。在一个处理器方法参数没有任何注解声明的时候,它就是一个需要绑定的业务逻辑对象,在调用处理器方法之前,需要使用Web数据绑定对象对此业务逻辑对象进行绑定,注解@InitBinder就是用来给Web数据绑定进行初始化的。

3.         声明模型属性相关注解

@SessionAttribute

注解@SessionAttribute可以声明保存某些模型对象到Session范围内。这些Session范围内的对象可以在接下来的请求中继续可得。

@ModelAttribute

注解@ModelAttribute有两个用途,它可以用来声明一个方法的返回值作为模型属性。它也能用来声明某个处理器方法参数能够从某个模型属性中得到期望的值。

4.         注解控制器处理器方法参数和返回值注解

前面我们已经在基于流程的剖析的章节中,对注解控制器的处理器方法的参数和返回值的注解进行了详细的分析和代码注释。这里将不再重复分析。

最后我们对一个典型的注解控制器进行分析,如下代码注释,

//  声明作为注解控制器组件

@Controller

 

//  映射带有模板参数的 URL 到所有的当前控制器的处理器方法中

@RequestMapping("/owners/{ownerId}/pets/new")

 

//  pet 对象存储到 Session 范围内

@SessionAttributes("pet")

public   class  AddPetForm {

     //  引用持久层业务逻辑服务对象,注解控制器推荐使用控制器对持久层业务逻辑的直接调用,在不复杂的情况下,不再需要服务层和 DAO 层次

     private   final  Clinic clinic;

 

     //  自动注入持久层业务逻辑服务对象

    @Autowired

     public  AddPetForm(Clinic clinic) {

         this .clinic = clinic;

    }

 

     //  声明模型属性,这些模型属性会在视图显示中使用

    @ModelAttribute("types")

     public  Collection<PetType> populatePetTypes() {

         return   this .clinic.getPetTypes();

    }

 

     //  用来初始化绑定 Pet 对象

    @InitBinder

     public   void  setAllowedFields(WebDataBinder dataBinder) {

        dataBinder.setDisallowedFields("id");

    }

 

     // HTTP GET 请求用来显示 Form

    @RequestMapping(method = RequestMethod.GET)

     //  从路径变量中提取 OWNER ID

     public  String setupForm(@PathVariable("ownerId")  int  ownerId, Model model) {

         //  取得 Owner 信息

        Owner owner =  this .clinic.loadOwner(ownerId);

       

         //  创建一个 Pet 对象加入到 Owner

        Pet pet =  new  Pet();

        owner.addPet(pet);

       

         //  Pet 对象到模型中,并且 Pet 对象是 Session 属性,所以,它也会保存在 Session

        model.addAttribute("pet", pet);

         return  "pets/form";

    }

 

     // HTTP POST 请求用来创建 Pet 对象

    @RequestMapping(method = RequestMethod.POST)

     // Pet 对象在显示 Form 的请求中存储在 Session 中,所以,它在模型中也是可得

     public  String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {

         //  Pet 对象绑定和校验

         new  PetValidator().validate(pet, result);

       

         //  如果出错继续显示 Form 视图

         if  (result.hasErrors()) {

             return  "pets/form";

        }

         //  如果成功则创建 Pet 对象

         else  {

             this .clinic.storePet(pet);

           

             //  结束一个 Session 周期,清楚 Session 中保存的属性

            status.setComplete();

           

             //  成功后显示 Owner 视图

             return  "redirect:/owners/" + pet.getOwner().getId();

        }

    }

 

}

转载请注明出处【 http://sishuok.com/article-detail.html?t=article-119&n=5374 】