• 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

  • 相关阅读:
    BUUCTF--[GUET-CTF2019]number_game
    36D杯CTF Re WP
    BUUCTF--[GWCTF 2019]re3
    虎符网络安全赛道 Re Game
    Python ZIP压缩文件破解
    合唱队, 华为
    字符串排序, 华为
    称砝码, 华为
    迷宫问题, 华为
    Sudoku , 华为
  • 原文地址:https://www.cnblogs.com/minet/p/12296394.html
Copyright © 2020-2023  润新知