SpringMVC(3)之处理器映射器和适配器

一、处理器映射器和适配器

非注解的处理映射器2种:

(处理器映射器HandlerMapping,负责根据request请求,找到对应的Handler处理器和拦截器,然后封装在HandlerExecutionChain对象中,最后返回给中央调度器,常用的实现类见以下俩种)

1.BeanNameUrlHandlerMapping: 会根据请求的url与spring中定义的处理器bean的name属性值进行匹配,从而在spring中找到处理器bean(这种方式bean id必须以“/”开头,否则无法加到url数组中)

//注册处理器映射器BeanNameUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
//注册处理器Handel
<bean name="/queryItems.action" class="com.dmz.ssm.controller.ItemsController"></bean>

PS:为什么必须以“/”方式开头,详情见源码如下图

public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
    public BeanNameUrlHandlerMapping() {
    }

    protected String[] determineUrlsForHandler(String beanName) {
        List<String> urls = new ArrayList();
        if (beanName.startsWith("/")) {
            urls.add(beanName);
        }

        String[] aliases = this.getApplicationContext().getAliases(beanName);
        String[] var4 = aliases;
        int var5 = aliases.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String alias = var4[var6];
            if (alias.startsWith("/")) {
                urls.add(alias);
            }
        }

        return StringUtils.toStringArray(urls);
    }
}

BeanNameUrlHandlerMapping不足之处:

1.处理器的id名称是一个url,并不是bean的名称,有些不伦不类

2.处理器的定义与请求的url绑在一起,若出现多个url请求同一个处理器的情况,就需要在spring容器中配置多个处理器类的bean

2.SimpleUrlHandlerMapping

SimpleUrlHandlerMapping处理映射器,可以将url与处理器的定义分离,还可以对url进行统一管理,该映射器会根据请求的url与spring容器中定义的处理器映射器,子标签的key属性进行匹配,匹配上后,在根据key的value值与处理器bean的id进行匹配,从而在spring中找到处理器bean

//注册处理器映射器SimpleUrlHandlerMapping
 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
            <!--第一种
                <prop key="/queryItemsone.action">myController</prop>
                <prop key="/queryItemstwo.action">myController</prop>
               --> 
               <!--第二种
                <prop key="/queryItemsone.action" value="myController"/>
                <prop key="/queryItemstwo.action" value="myController"/>
               --> 
               //以上俩种方式都可以根据key,访问到myController
            </props>
        </property>
    </bean>
    //注册处理器
    <bean id="myController" class="com.dmz.ssm.controller.ItemsController"></bean>

 非注解的处理适配器2种:

(处理器适配器HandlerAdapter)

1.SimpleControllerHandlerAdapter底层调用Controller.handlerRequest(request,response);看源码如下:

//代码实现
public class ItemsControllerone implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        //相当于request的setAttribute方法
        modelAndView.addObject("msg",hello);
        modelAndView.setViewName("/WEB-INF/jsp/itemsList.jsp");
        return modelAndView;
    }
}
//源码
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    public SimpleControllerHandlerAdapter() {
    }

    public boolean supports(Object handler) {
        return handler instanceof Controller;
    }

    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //这里调用Controller.handleRequest
        return ((Controller)handler).handleRequest(request, response);
    }

    public long getLastModified(HttpServletRequest request, Object handler) {
        return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
    }
}

2.HttpRequestHandlerAdapter底层调用HttpRequestHandler.handlerRequest(request,response);看源码如下:

//代码实现
public class ItemsControllerone implements HttpServletRequest {

    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置模型数据
        request.setAttribute("msg",hello);
        //设置转发的视图
        request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
        //使用此方法可以通过修改response,设置响应的数据格式,比如响应json格式
        /*response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("json串");*/
    }
}
//源码
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    public HttpRequestHandlerAdapter() {
    }

    public boolean supports(Object handler) {
        return handler instanceof HttpRequestHandler;
    }

    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //这里调用的是HttpRequestHandler.handleRequest
        ((HttpRequestHandler)handler).handleRequest(request, response);
        return null;
    }

    public long getLastModified(HttpServletRequest request, Object handler) {
        return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
    }
}

 

下面说一下具体自定义的controller 里面的handleRequest方法是怎么被调用的,见源码DispatcherServlet类的doDispatch方法

如果实现的是Controller接口,则需要使用SimpleControllerHandlerAdapter适配器来执行自定义Controller,若使用HttpRequestHandlerAdapter无法把Controller转换为HttpRequestHandler,执行时会报错,反之如果是HttpRequestHandler接口需要使用HttpRequestHandlerAdapter适配器

spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器。

spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。

<!--================注解的处理器映射器==============================-->

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

 

spring3.1之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter 注解适配器。

spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter 注解适配器

<!--================注解的适配器==============================-->

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

Handler 单个配置

<!-- 配置Handler -->

    <bean    class="spring.ssm.controller.ItemsController3"/>

Handler 使用组件扫描配置

<context:component-scan base-package="com.iot.ssm.controller"></context:component-scan>

注意: 使用mvc:annotation-driven代替上面两个注解映射器和注解适配的配置 mvc:annotation-driven默认加载很多的参数绑定方法, 比如json转换解析器默认加载了 如果使用mvc:annotation-driven则不用配置上面的RequestMappingHandlerMapping和RequestMappingHandlerAdapter实际开发时使用mvc:annotation-driven

原文地址:https://www.cnblogs.com/minet/p/12296394.html