大佬详解:SpringMVC从基础到源码,厉害了

本文由Java大蜗牛讲解SpringMVC框架,详细介绍了其从请求处理到源码分析的过程。文章提及SpringMVC是围绕Servlet设计的,核心是DispatcherServlet,处理请求包括Controller查找、ModelAndView返回等步骤。对比了SpringMVC与Servlet、Structs2的区别,强调SpringMVC的开发效率和性能优势。最后,简述了SpringMVC源码分析的关键点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好,我是Java大蜗牛,一个渴望在互联网行业做到很牛的蜗牛。

可柔可刚,点赞则柔,白嫖则刚!死鬼~~~看完记得给我来个三连哦!

大佬详解:SpringMVC从基础到源码,厉害了

 

文章目录

  • 认识SpringMVCSpringMVC 处理请求过程Servlet 与 SpringMVCStructs2 与 Spring MVCSpringMVC源码分析

 

认识SpringMVC

SpringMVC 框架是以请求为驱动,围绕 Servlet 设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。其中核心类是 DispatcherServlet,它是一个 Servlet,顶层是实现的Servlet接口。

大佬详解:SpringMVC从基础到源码,厉害了

 


SpringMVC 处理请求过程

大佬详解:SpringMVC从基础到源码,厉害了

 

  • 客户端发起请求,会首先经过前端控制器 DispatcherServlet 进行转发,转发到 Handler Mapping
  • DispatcherServlet 从 Handler Mapping 查找处理请求的 Controller,Handler Mapping 作用就是完成 URL 到 Controller 的映射
  • Controller 处理请求并返回 ModelAndView 对象,ModelAndView 是封装结果视图的组件
  • 再将视图结果返回给客户端

Servlet 与 SpringMVC

SpringMVC 是在 Servlet 的基础上进行了扩展,看看他们的继承关系是什么样的。

Servlet 继承关系

大佬详解:SpringMVC从基础到源码,厉害了

 


SpringMVC 继承关系

大佬详解:SpringMVC从基础到源码,厉害了

Java学习交流群:927953692   欢迎讨论交流,另外可免费领取一份(Java学习视频,技术文档,电子书籍,基础面试题)


Servlet 与 SpringMVC 对比

  • Servlet 需要每个请求都在 web.xml 文件中配置一个 sevlet 节点
  • SpringMVC 的 DispatcherServlet 会拦截所有请求,让 Controller 去处理

Structs2 与 Spring MVC

相同点

  • 都是基于MVC模型的

不同点

  • Structs2 是基于类的,一个 request 创建一个 action,一个action 对应一个 request ;Servlet 是基于方法的,也就是一个 request 对应一个方法
  • Structs2 入口是 Filter;SpringMVC 入口是 Servlet
  • SpringMVC 的开发速度和性能优于 Structs2 ,流程更易理解
  • SpringMVC 和 Spring 是无缝的,可以认为 SpringMVC 是100% 零配置

SpringMVC源码分析

1、ApplicationContext 初始化时建立所有的URL和Controller 的对应关系

/**
* 建立当前ApplicationContext中的所有controller和url的对应关系*/
protected void detectHandlers() throws BeansException {
    //日志级别是否是 Debug
    if (logger.isDebugEnabled()) {
        //应用上下文就是工程的访问路径
        logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
    }
     // 获取ApplicationContext容器中所有bean的Name---Controller
    String[] beanNames = (this.detectHandlersInAncestorContexts ?
            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
            getApplicationContext().getBeanNamesForType(Object.class));
    // 遍历beanNames,并找到这些bean对应的url
    for (String beanName : beanNames) {
       // 获取Controller上的所有url(类上的url+方法上的url)
        String[] urls = determineUrlsForHandler(beanName);
        if (!ObjectUtils.isEmpty(urls)) {
            // 保存urls和beanName的对应关系,put it to Map<urls,beanName>,该方法在父类AbstractUrlHandlerMapping中实现
            registerHandler(urls, beanName);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
            }
        }
    }
}
1234567891011121314151617181920212223242526272829

2、根据访问URL找到对应 Controller 中处理请求的方法

/** 中央控制器,控制请求的转发 **/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
   ModelAndView mv;
   boolean errorView = false;
   try {
    // 1.检查是否是文件上传的请求
       processedRequest = checkMultipart(request);
       // 2.取得处理当前请求的controller,这里也称为hanlder,处理器,第一个步骤的意义就在这里体现了.
       这里并不是直接返回controller,而是返回的HandlerExecutionChain请求处理器链对象,该对象封装了handler和interceptors.
       mappedHandler = getHandler(processedRequest, false);
    // 如果handler为空,则返回404
       if (mappedHandler == null || mappedHandler.getHandler() == null) {
           noHandlerFound(processedRequest, response);
           return;
       }
       //3. 获取处理request的处理器适配器handler adapter 
       HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
       // 处理 last-modified 请求头
       String method = request.getMethod();
       boolean isGet = "GET".equals(method);
       if (isGet || "HEAD".equals(method)) {
           long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
           if (logger.isDebugEnabled()) {
               String requestUri = urlPathHelper.getRequestUri(request);
               logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
           }
           if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
               return;
           }
       }
       // 4.拦截器的预处理方法
       HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
       if (interceptors != null) {
           for (int i = 0; i < interceptors.length; i++) {
               HandlerInterceptor interceptor = interceptors[i];
               if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
                   triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
                   return;
               }
               interceptorIndex = i;
           }
       }
       // 5.实际的处理器处理请求,返回结果视图对象
       mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
       // 结果视图对象的处理
       if (mv != null && !mv.hasView()) {
           mv.setViewName(getDefaultViewName(request));
       }
       // 6.拦截器的后处理方法
       if (interceptors != null) {
           for (int i = interceptors.length - 1; i >= 0; i--) {
               HandlerInterceptor interceptor = interceptors[i];
               interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
           }
       }
   }
   catch (ModelAndViewDefiningException ex) {
       logger.debug("ModelAndViewDefiningException encountered", ex);
       mv = ex.getModelAndView();
   }
   catch (Exception ex) {
       Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
       mv = processHandlerException(processedRequest, response, handler, ex);
       errorView = (mv != null);
   }
      if (mv != null && !mv.wasCleared()) {
       render(mv, processedRequest, response);
       if (errorView) {
           WebUtils.clearErrorRequestAttributes(request);
       }
   }
   else {
       if (logger.isDebugEnabled()) {
           logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                   "': assuming HandlerAdapter completed request handling");
       }
   }
   // 请求成功响应之后的方法
   triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293

3、反射调用处理请求的方法返回结果视图

/** 获取处理请求的方法,执行并返回结果视图 **/
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
	throws Exception {
   // 1.获取方法解析器
   ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);     
   // 2.解析request中的url,获取处理request的方法 
   //通过 request 找 controller 中的处理方法,request的url与 controller 的url 进行匹配
   Method handlerMethod = methodResolver.resolveHandlerMethod(request);     
   // 3.方法调用器
   ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
   ServletWebRequest webRequest = new ServletWebRequest(request, response);
   ExtendedModelMap implicitModel = new BindingAwareModelMap();
     // 4.执行方法
   Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);     
   // 5.封装结果视图
   ModelAndView mav =
           methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
   methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
   return mav;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值