设为首页 加入收藏

TOP

day15-SpringMVC执行流程(一)
2023-07-25 21:42:56 】 浏览:37
Tags:day15-SpringMVC

SpringMVC执行流程

1.SpringMVC执行流程分析图

例子

(1)创建 HaloHandler

package com.li.web.debug;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 李
 * @version 1.0
 */
@Controller
public class HaloHandler {
    //编写方法,响应请求,返回一个 ModelAndView对象
    @RequestMapping(value = "/debug/springmvc")
    public ModelAndView halo(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView modelAndView = new ModelAndView();
        //对应到 WEB-INF/pages/ok.jsp (ok的前后缀是你在视图解析器中配置的前后缀)
        modelAndView.setViewName("ok");
        //在model中放入数据 k-v,ModelAndView的属性也会被springmvc放入到request域中
        modelAndView.addObject("name", "齐天大圣");
        return modelAndView;
    }
}

(2)创建ok.jsp,作为响应后跳转的页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>ok</title>
</head>
<body>
<h1>进入到ok页面</h1>
<h2>name-${requestScope.name}</h2>
</body>
</html>

2.源码debug

我们以上述代码为例子进行源码分析。

(1)在 DispatcherServlet 的 doService 方法中打上断点,在浏览器中访问目标方法,可以看到光标跳转到断点处:当请求发送到服务器时,tomcat 将 http 请求包装成 request 对象,前端控制器 DispatcherServlet 使用 doService() 方法接收这个 request 对象。

image-20230220213910330 image-20230220203713801

(2)点击 step over 前进,可以看到这里的 getWebApplicationContext() 就是 spring 容器对象。也就是说,当接收到url请求的时候,前端控制器就会进行spring 容器的初始化,将各种 bean 放入到容器中。

image-20230220204141473

(3)点击 step over,在经过一系列处理之后调用了 doDispatch() 方法。这是一个核心的方法。

image-20230220204445920

(4)点击 step into,进入 doDispatch() 方法,该方法中首先定义了一个处理器执行链,它用于存放拦截器(多个)和目标 Handler。然后定义了ModelAndView 对象,用于存放视图信息和数据。

image-20230220213959367 image-20230220205326737

执行下面的语句后,就通过映射拿到了处理器执行链 HandlerExecutionChain 的目标 Handler 和拦截器链

image-20230220210019024

(5)点击 step over,跳到如下:获取适配器,包含要执行的目标 Handler

image-20230220210743139 image-20230220214118074

(6)点击 step over,跳到如下:调用 handle() 方法,进行反射调用目标 Handler。

image-20230220211201477

(7)点击 step into,进入到 handle 方法中调用的 handleInternal() 方法,handleInternal() 方法中反射调用了目标 Handler的方法,然后返回视图对象。

image-20230220211812556 image-20230220214704657

(8)在目标方法中打上断点,点击 resume 进入目标方法

image-20230220212955654

(9)点击 step over,ModelAndView 对象返回给适配器。

image-20230220213514030 image-20230220214807691

(10)然后返回到第7步的方法中,因此第7步中返回的视图就是目标方法操作后返回的视图对象

image-20230220215320257

(11)继续一直点击 step over,方法 return 返回到第6步,将获取的视图对象返回给前端控制器。

image-20230220215703488 image-20230220215805035

(12)点击 step over,在前端控制器的 doService 方法中执行如下语句,processDispatchResult() 方法对前面返回的视图进行解析。

image-20230220220003548

(13)step into 进入processDispatchResult 方法,该方法调用 render() 进行渲染。

image-20230220220233835

(14)render() 方法从 ModelAndView 对象中得到视图名称 viewName,如果 viewName 不为空,就进行视图解析。

image-20230220220630961

resolveViewName() 方法进行视图解析,然后返回 view 给前端控制器。

@Nullable
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
      Locale locale, HttpServletRequest request) throws Exception {

   if (this.viewResolvers != null) {
      for (ViewResolver viewResolver : this.viewResolvers) {
         View view = viewResolver.resolveViewName(viewName, locale);
         if (view != null) {
            return view;
         }
      }
   }
   return null;
}
image-20230220220937160

(15)返回前端控制器之后,又调用 View的 render() 方法进行视图的渲染。

注意和前端控制器的 render 方法区分

image-20230220221538252 image-20230220222131962

View 的 render() 方法:

@Override
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
      HttpServletResponse response) throws Exception {

   if (logger.isDebugEnabled()) {
      logger.debug("View " + formatViewName() +
            ", model " + (model != null ? model : Collections.emptyMap()) +
            (this.staticAttributes.isEmpty() ? &q
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇《分布式技术原理与算法解析》学.. 下一篇学习笔记——Linux中搜索查找类命..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目