DispatcherServlet处理器的适配和处理解析

 更新时间:2023年06月27日 11:14:32   作者:程序员札记  
这篇文章主要为大家介绍了DispatcherServlet的处理器的适配和处理流程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

处理大致流程图

获取处理器适配器

适配器模式

为什么要处理器适配器,我们前面不是获取处理器方法了么,直接调用就好啦。对没错,但是那可能只是一种处理器的方式,也就是HandlerMethod,以前还有另外的方式哦,比如实现Controller接口的:

还有实现HttpRequestHandler接口的:

他们的接口都不一样,总得兼容吧,处理接口不一致的办法不就是适配器模式嘛,你接口不同,我用不同的适配器来适配,对外都是统一接口,如果以后有新的实现,我只要添加适配器即可,这里就是适配器模式的应用啦。

DispatcherServlet的getHandlerAdapter

这里就是遍历所有的处理器适配器,看哪个是适配的就直接返回了。

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            for (HandlerAdapter adapter : this.handlerAdapters) {
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }
        throw new ServletException("No adapter for handler [" + handler +
                "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

如何适配

RequestMappingHandlerAdapter的supports

判断是否是HandlerMethod类型的。

    @Override
    public final boolean supports(Object handler) {
        return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    }
    @Override
    protected boolean supportsInternal(HandlerMethod handlerMethod) {
        return true;
    }

HttpRequestHandlerAdapter的supports

是不是实现了HttpRequestHandler接口。

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

SimpleControllerHandlerAdapter的supports

是不是实现了Controller接口。

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

至于这些是什么时候初始化的,我就不说了,前面已经把方法都演示过了,就是一些自动配置类里,自己可以去找啦,剩下的适配器自己可以也去看看。

处理器适配器处理

其实前面有拦截器,后面会说,还是说主要的,处理器适配器获得到之后,要进行适配器调用啦,不同的适配器调用方式不一样,但是核心还是调用处理器的方法啦:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

HttpRequestHandlerAdapter的handle

转换成接口类型,调用接口。

    @Override
    @Nullable
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
    }

SimpleControllerHandlerAdapter的handle

这个也一样。

    @Override
    @Nullable
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return ((Controller) handler).handleRequest(request, response);
    }

AbstractHandlerMethodAdapter的handle

这个是重点,我们要详细说。

    @Override
    @Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return handleInternal(request, response, (HandlerMethod) handler);
    }

RequestMappingHandlerAdapter的handleInternal

留出核心代码,就是处理器处理,然后准备response

@Override
    protected ModelAndView handleInternal(HttpServletRequest request,
            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        ModelAndView mav;
        ...
        mav = invokeHandlerMethod(request, response, handlerMethod);//      
        ...
        prepareResponse(response);
        ...
        return mav;
    }

invokeHandlerMethod

这里面的才是重点,每个都挺复杂的,没关系,我们一个个来看,新不追求太细节的东西,知道大致流程,大致的流程就是创建数据绑定工厂,这个东西就是做参数绑定用的,后面会介绍,然后是模型工厂,最终是要创建模型返回的,所以需要这个,而且数据绑定工厂也会封装在里面。

然后初始化模型,会根据方法的参数来找解析器解析,找到的话就可以解析出参数,最后封装到模型里去,最后再调用处理器的方法处理,然后获取模型和视图返回。看起来好像没多少东西,其实里面还是表深的。

@Nullable
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        //先封装一个
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        try {
            WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);//数据绑定工厂
            ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);//模型工厂
            //进行handlerMethod封装
            ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
            if (this.argumentResolvers != null) {//设置参数解析器
                invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            }
            if (this.returnValueHandlers != null) {//设置返回类型解析器
                invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            }
            invocableMethod.setDataBinderFactory(binderFactory);//绑定工厂
            invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);//参数名探测器
            //创建ModelAndView容器
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));//获取前面重定向来的属性
            modelFactory.initModel(webRequest, mavContainer, invocableMethod);//初始化模型
            mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
            ...
            //调用处理方法
            invocableMethod.invokeAndHandle(webRequest, mavContainer);
            ...
            return getModelAndView(mavContainer, modelFactory, webRequest);
        }
        finally {
            webRequest.requestCompleted();
        }

以上就是DispatcherServlet的处理器的适配和处理解析的详细内容,更多关于DispatcherServlet处理器适配的资料请关注脚本之家其它相关文章!

相关文章

  • Java 中的伪共享详解及解决方案

    Java 中的伪共享详解及解决方案

    这篇文章主要介绍了Java 中的伪共享详解及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 递归之斐波那契数列java的3种方法

    递归之斐波那契数列java的3种方法

    这篇文章主要为大家详细介绍了递归之斐波那契数列java的3种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • java开发环境的完整搭建过程

    java开发环境的完整搭建过程

    这篇文章主要给大家介绍了关于java开发环境的完整搭建过程,文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 浅析Java基于Socket的文件传输案例

    浅析Java基于Socket的文件传输案例

    这篇文章主要针对Java基于Socket的文件传输案例进行详细解析,具有一定的参考价值,感兴趣的朋友可以参考一下
    2016-02-02
  • Maven中两个命令clean 和 install的使用

    Maven中两个命令clean 和 install的使用

    Maven是一个项目管理和自动构建工具,clean命令用于删除项目中由先前构建生成的target目录,install命令用于将打包好的jar包安装到本地仓库中,供其他项目依赖使用,下面就来详细的介绍一下这两个命令
    2024-09-09
  • idea2020.2卡死在reading maven projects

    idea2020.2卡死在reading maven projects

    这篇文章主要介绍了idea2020.2卡死在reading maven projects,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java8 Optional常用方法使用场景分析

    Java8 Optional常用方法使用场景分析

    这篇文章主要介绍了Java8 Optional常用方法使用场景,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • JPA之使用JPQL语句进行增删改查

    JPA之使用JPQL语句进行增删改查

    这篇文章主要介绍了JPA之使用JPQL语句进行增删改查,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • 关于Java中的IO流总结(推荐)

    关于Java中的IO流总结(推荐)

    下面小编就为大家带来一篇关于Java中的IO流总结(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Maven打包的三种方式小结

    Maven打包的三种方式小结

    这篇文章给大家介绍了三种Maven打包的方式,使用maven-jar-plugin,使用maven-assembly-plugin和使用maven-shade-plugin这三种方式,通过代码介绍的非常详细,需要的朋友可以参考下
    2023-09-09

最新评论