Spring MVC使用篇(三)—— 处理器映射器和适配器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_36378917/article/details/83549803

1、重温请求流程

  在Spring MVC的架构环境下,用户在Web端触发了请求,请求会先通过前端控制器(DispatcherServlet),然后前端控制器(DispatcherServlet)会请求处理器映射器(HandlerMapping)寻找处理该请求的Handler(或带拦截器的Handler链),接着前端控制器(DispatcherServlet)会根据处理器映射器(HandlerMapping)传来的Handler(或带拦截器的Handler链)与配置的处理器适配器(HandlerAdapter)进行匹配,找到可以处理此Handler(或带拦截器的Handler链)类型的处理器适配器(HandlerAdapter),进而该处理器适配器(HandlerAdapter)调用自己的handler方法,利用Java的反射机制去执行具体的Controller方法并获得ModelAndView视图对象。

2、Spring MVC默认的注解配置

2.1 在Spring 3.1之前

  Spring MVC默认加载的注解的处理器映射器和处理器适配器分别为DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter。它们位于Spring MVC的核心jar包的org.springframework.web.servlet.mvc.annotation包下。

2.2 在Spring 3.1之后

  DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter已经被列为国企的映射器和适配器,Spring MVC增加了新的基于注解的处理器映射器和适配器,分别为RequestMappingHandlerMapping和RequestMappingHandlerAdapter,它们同样位于Spring MVC的核心jar包的org.springframework.web.servlet.mvc.method.annotation包下。

3、配置注解的处理器映射器和适配器方式

3.1 第一种配置方式

  第一种配置方式和费注解的处理器适配器和映射器的配置一样,声明相关的bean即实现即可,配置如下:

<!--注解映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
    <!--注解适配器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />

3.2 第二种配置方式

  第二种配置方式,使用“<mvc:annotation-driven />”标签来配置。annotation-driven标签是一种简写模式,使用默认配置代替了一般的手动配置。annotation-driven标签会自动注册处理器映射器和处理器适配器(Spring 3.1 至 Spring 4 皆使用RequestMappingHandlerMapping和RequestMappingHandlerAdapter)。并且除此之外还提供了数据绑定支持,例如@NumberFormatannotation支持、@DateTimeFormat支持、@Valid支持、读写XML的支持(JAXB)和读写JSON的支持(Jackson)。在实际开发中,为了提高开发效率,使用最多的就是基于annotation-driven标签的配置。annotation-driven标签的配置十分简单,如下所示。

<!--配置基于注解的处理器适配器与处理器映射器-->
    <mvc:annotation-driven/>

4、让注解的处理器映射器和适配器找到注解的Handler

  为了让注解的处理器映射器和适配器找到注解的Handler,有两种配置方式。

  • 在springmvc.xml中声明相关的bean信息即可;
    <bean class="com.ccff.controller.FruitsController" />
  • 使用扫描配置,对某一个包下的所有类进行扫描,找出所有使用@Controller注解的Handler控制类;
    <!--使用扫描配置,对某一个包下面的所有类进行扫描,
    找出所有使用@Controller注解的Handler控制器类-->
    <context:component-scan base-package="com.ccff.controller"/>

注意:如果不使用annotation-driven标签配置注解的处理器映射器和适配器,而采用手动配置,那么必须保证基于注解的处理器映射器和适配器要成对配置,不然会没有效果。还有一点需要注意,如果在测试过程中出现“java.lang.IllegalArgumentException”,则说明使用了JDK 8.0的环境,由于Spring 3.x版本不支持JDK 8.0,因此需要更换编译环境。

5、非注解的处理器映射器

  • BeanNameUrlHandlerMapping类
    • 映射规则:将bean的name作为url进行查找,需要在配置Handler时指定beanname(就是url)。
    • 先在springmvc.xml配置文件中添加处理器映射器;
    • 在配置Handler时需要指定beanname(就是url);
<!-- 先在springmvc.xml配置文件中添加处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!--  在配置Handler时需要指定beanname(就是url) -->
<bean name="/query/queryAllFruits.action" class="com.ccff.controller.FruitsController" />
  • SimpleUrlHandlerMapping类
      SimpleUrlHandlerMapping可以通过内部参数配置请求的url和handler的映射关系。样例配置如下:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="someCheckInterceptors1"/>
                <ref bean="someCheckInterceptors2"/>
            </list>
        </property>
        <property name="mappings">
            <props>
                <prop key="user.action">userController</prop>
                <prop key="product.action">productController</prop>
                <prop key="other.action">otherController</prop>
            </props>
        </property>
    </bean>

  在SimpleUrlHandlerMapping的bean标签对中,可以通过property属性配置拦截器和相关的Handler处理器的URL的映射关系。在上面的样例中添加了两个拦截器配置,和三个Handler处理器的URL映射。
  以水果商城案例为例,使用SimpleUrlHandlerMapping处理器映射器配置如下:

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/queryFruits_test1.action">fruitsController</prop>
                <prop key="/queryFruits_test2.action">fruitsController</prop>
            </props>
        </property>
    </bean>
    <bean id="fruitsController" class="com.ccff.controller.FruitsController" />

  这里配置了两个不同的URL,但是对应的都是同一个Controller配置。也就是说,在浏览器上发出两个不同的URL请求,会得到相同的处理结果。

  • ControllerClassNameHandlerMapping类
      ControllerClassNameHandlerMapping可以使用CoC管理有限原则(conventionover configuration)的方式来处理请求,对于普通的Controller,会把其类名“xxxController”映射到“/xxx*”的请求URL。对于MultiActionController类型的Controller,ControllerClassNameHandlerMapping会把其类名“xxxController”以及其中的方法“yyy”映射到“/xxx/yyy.action”(.action对应设置的dispatcher-servlet的url-pattern)的请求URL。样例配置如下:
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />

6、非注解的处理器适配器

  • SimpleControllerHandlerAdapter
      SimpleControllerHandlerAdapter适配器支持所有实现了Controller接口的Handler控制器,开发者如果编写了实现Controller接口的控制器,那么SimpleControllerHandlerAdapter适配器会执行Controller的具体方法。
      以水果商城案例为例,配置处理器适配器SimpleControllerHandlerAdapter如下:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
  • HttpRequestHandlerAdapter
      HttpRequestHandlerAdapter要求编写的Handler实现HttpRequestHandler接口。因此在非注解的Handler编写中,Controller需要实现HttpRequestHandler接口,重写handleRequest方法。配置如下:
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
  • AnnotationMethodHandlerAdapter

小贴士
  通过上面的整理,我们可以知道,处理器映射器就是根据URL来查找Handler,处理器适配器就是按照它要求的规则(handler instanceof XXX接口)去执行Handler。但是这种开发模式有一个缺点,一个Handler类中只能编写一个方法,这对于大量请求处理逻辑真是勉为其难了,这种问题就可以通过注解的处理器映射器和适配器就可以很好的解决了。

猜你喜欢

转载自blog.csdn.net/weixin_36378917/article/details/83549803