SSM-SpringMVC-17:SpringMVC中深度剖析HandlerAdapter处理器适配器底层
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------
先放一张图

很熟悉啊,之前就看过,我们之前已经把handlerMapping剖了个底朝天,顺着上次的进度,继续跟,把HandlerAdapter处理器适配器剖一下
它同样是由中央调度器DispatcherServlet调度到的,所以,还是这个类中找doDispatch(request,response)这个方法,我把有用的代码,扒下来
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        try {
            try {
                ModelAndView err = null;
                Exception dispatchException = null;
                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    mappedHandler = this.getHandler(processedRequest);
                    if(mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
//上面的是我说的HandleMapping的执行 流程
//所以从后面的第一行开始看
                    HandlerAdapter ex = this.getHandlerAdapter(mappedHandler.getHandler());
HandlerExecutionChain mappedHandler这个变量,是处理器执行链,它的getHandler方法,就是获取它里面的处理器
它外面的this.getHandlerAdpter
点过去追踪
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
//迭代器
        Iterator var2 = this.handlerAdapters.iterator();
//一会要返回去的适配器对象
        HandlerAdapter ha;
        do {
//如果没有下一个的话。就抛异常
            if(!var2.hasNext()) {
                throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
            }
//将此强转成为处理器适配器
            ha = (HandlerAdapter)var2.next();
            if(this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler adapter [" + ha + "]");
            }
        } while(!ha.supports(handler));
//这儿有个适配器模式
        return ha;
    }
这是下载源码后的最直观的源码
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        for (HandlerAdapter ha : this.handlerAdapters) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing handler adapter [" + ha + "]");
            }
            if (ha.supports(handler)) {
                return ha;
            }
        }
        throw new ServletException("No adapter for handler [" + handler +
                "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }
看ha.sipports(handler)这个方法
找到HandlerAdapter接口
public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    long getLastModified(HttpServletRequest request, Object handler);
}
再来看一下自己写的控制器实现了Controller。这样就看DispatcherServlet属性中的HandlerApater谁支持Controller类型的处理器了。在运行的过程中发现SimpleControllerHandlerAdapter是支持Controller类型的控制器的。
来看一下SimpleControllerHandlerAdapter的代码
找它的实现类:Ctrl+H SimpleControllerHandlerAdapter
public class SimpleControllerHandlerAdapter implements HandlerAdapter {  
    public boolean supports(Object handler) {
        return (handler instanceof Controller);
    }  
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {  
        return ((Controller) handler).handleRequest(request, response);
    }  
    public long getLastModified(HttpServletRequest request, Object handler) {
        if (handler instanceof LastModified) {
            return ((LastModified) handler).getLastModified(request);
        }
        return -1L;
    }  
}  
它support来判断是否是处理器
拿到处理器在中央调度器一处调用了handle方法
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;
            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);
                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }
                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//就是上面这处
看看handle方法,因为被执行调用到,它返回ModelAndView
里面return走的handleRequest是Controller接口的,找它的实现类
AbstractController抽象类,它有实现handleRequest
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception { // Delegate to WebContentGenerator for checking and preparing.
checkRequest(request);
prepareResponse(response); // Execute handleRequestInternal in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return handleRequestInternal(request, response);
}
}
} return handleRequestInternal(request, response);
}
看到最后面的那个返回值了吗?是ModelAndView对象,它调用了handleRequestInternal(request,respone)这个方法
还记得AbstractController的实现类吗?不是有种处理器的定义方法就是继承AbstractController
package cn.dawn.day04abstractController; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* Created by Dawn on 2018/3/19.
*/
//处理器
public class FirstController extends AbstractController { protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView me=new ModelAndView();
me.setViewName("index");
return me;
}
}
它的实现类默认要求必须实现handleRequestInternal(request,response)这个方法
所以,理清了吧,再一步步return回去,最后回到了中央调度器
结论,中央处理器DispatcherServlet通过处理器执行链找到handlerAdapter处理器适配器,后者调度了它的处理器,通过处理器处理,返回一个ModelAndView模型和视图对象,一路返回,到中央调度器
SSM-SpringMVC-17:SpringMVC中深度剖析HandlerAdapter处理器适配器底层的更多相关文章
- 零基础学习java------38---------spring中关于通知类型的补充,springmvc,springmvc入门程序,访问保护资源,参数的绑定(简单数据类型,POJO,包装类),返回数据类型,三大组件,注解
		一. 通知类型 spring aop通知(advice)分成五类: (1)前置通知[Before advice]:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常. (2)正常返回通知 ... 
- SpringMVC学习--springmvc原理
		简介 springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合.springmvc是一个基于mvc的web框架. spring的结构图: mvc在b/ ... 
- springmvc(一) springmvc框架原理分析和简单入门程序
		springmvc这个框架真的非常简单,感觉比struts2还更简单,好好沉淀下来学习~ --WH 一.什么是springmvc? 我们知道三层架构的思想,并且如果你知道ssh的话,就会更加透彻的理解 ... 
- SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释(转)
		原文:https://blog.csdn.net/yijiemamin/article/details/51156189# 这几天一直在整合SSM框架,虽然网上有很多已经整合好的,但是对于里面的配置文 ... 
- 0927-转载:SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释
		这篇文章暂时只对框架中所要用到的配置文件进行解释说明,而且是针对注解形式的,框架运转的具体流程过两天再进行总结. spring+springmvc+mybatis框架中用到了三个XML配置文件:web ... 
- SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释
		这几天一直在整合SSM框架,虽然网上有很多已经整合好的,但是对于里面的配置文件并没有进行过多的说明,很多人知其然不知其所以然,经过几天的搜索和整理,今天总算对其中的XML配置文件有了一定的了解,所以拿 ... 
- 使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(二)(代码篇)
		这篇是上一篇的延续: 用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(一) 源代码在github上可以下载,地址:https://github.com/guoxia ... 
- Maven+SSM框架(Spring+SpringMVC+MyBatis) - Hello World(转发)
		[JSP]Maven+SSM框架(Spring+SpringMVC+MyBatis) - Hello World 来源:http://blog.csdn.net/zhshulin/article/de ... 
- SSM(Spring+SpringMVC+MyBatis)高并发优化思路
		SSM(Spring+SpringMVC+MyBatis)框架集由Spring.MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容).常作为数据源较简单的web项目的框架 ... 
随机推荐
- Unable To Import Or Enter Sale Order - ORA-20001: APP-FND-01564: ORACLE error - 1422 in get_seq_info
			In this Document Symptoms Cause Solution APPLIES TO: Oracle Order Management - Version 12.0.4 ... 
- 尽量用pass-by-reference-to-const(const引用)替换pass-by-value(传值)
			默认情况下C++以pass-by-value传递对象至函数(或从函数返回). eg1: class Person { public: Person(); virtual ~Person(); priv ... 
- windows下ruby中显示中文的3种方法
			A: 1将x.rb编码为ascii格式 2 在x.rb开头加上 #code:gbk或者 #coding:gbk B: 1 将x.rb编码为utf-8格式 2 在x.rb开头加上 #code:utf-8 ... 
- python 字典dict类型合并(不能错过哦)
			我要的字典的键值有些是数据库中表的字段名, 但是有些却不是, 我需要把它们整合到一起, 因此有些这篇文章.(非得凑够150个字,我也是没有办法,扯一点昨天的问题吧,话说python中的session就 ... 
- webapi从入门到放弃(一)OWIN 自寄宿模式
			1.创建web空项目 2.创建完如图 3.安装如下程序包Microsoft.AspNet.WebApi.Core (5.2.4)Microsoft.Owin.Host.SystemWeb (4.0. ... 
- JAVA全套学习视频
			链接: https://pan.baidu.com/s/1miE7kvQ 密码: jj8x 
- Convert Sorted Array to Binary Search Tree(将一个有序数组转换成一颗二叉搜索树)
			Given an array where elements are sorted in ascending order, convert it to a height balanced BST. Fo ... 
- iOS 博客资源精选
			摘要:记录一些网上非常牛的人写的博文.收藏起来. 以备日后需要时学习备用. 1:iOS中UIWebView的Javascript与Objective-C通信 http://imchao.net/201 ... 
- 运行Applet程序
			[操作方法1:]① 编辑源程序welcome.java.② 编译程序 javac welcome.java③ 将Applet嵌入HTML网页.方法是,用记事本创建一个文件,文件内容如下:<app ... 
- Kapacitor之TICK脚本,监控输出
			好久没更新博客园了,说来也惭愧,之前说好每隔几天更新一个的,虽然没什么人看,但是作为一个记录,回顾也是能有新的认识,这篇博客是讲的目前我在工作中使用的一个结束点,这个技术点目前网上资料少之甚少,也是希 ... 
