SpringMVC的执行流程

一、SpringMVC执行流程图

二、验证这个流程

1.准备工作

(1)准备thymeleaf来实现

因为我们没有去使用前后端分离,所以使用thymeleaf来渲染视图。先自定义一个controller,里面的方法作用就是设置视图和一个数据模型。

package com.csc.contorller;

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

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/info")
    public ModelAndView info(){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("userInfo");
        mv.addObject("username","小明");
        return mv;
    }
}

 同时使用thymeleaf的语法,把对应的数据模型获取。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1 th:text="${username}"></h1>
</body>
</html>

可以看见,浏览器输出的内容就是我们之前设置的数据模型。

(2)配置拦截器

自定义的拦截器。

package com.csc.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * 自定义的拦截器
 */
@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor...preHandle...执行了...");
        //true:放行  false:拦截
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor...postHandle...执行了...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor...afterCompletion...执行了...");
    }
}

还需要在配置类里面配置拦截器。

package com.csc.config;

import com.csc.interceptor.MyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 配置类
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor);
    }
}

(3)配置全局异常处理器

自定义的异常处理器,为了方便展示效果,使用ModelAndView来返回进行视图的展示。

package com.csc.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

/**
 * 自定义的全局异常处理器
 */
@ControllerAdvice
public class MyGlobalExceptionHandle {

    @ExceptionHandler({Exception.class}) //处理所有异常
    public ModelAndView handleException(Exception ex){
        ex.printStackTrace();
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        return mv;
    }
}

异常error.html。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>服务器异常</h1>
    <h1>服务器异常</h1>
    <h1>服务器异常</h1>
    <h1>服务器异常</h1>
</body>
</html>

至此,准备工作就已经完成。

2.debug看源码

(1)先搜索DispatcherServlet类

找到doDispatch()方法,这里面就是核心的SpringMVC的执行流程。

(2)获取HandlerExecutionChain

1.先找到mappedHandler对象。

2.步入进去发现,在循环迭代添加HandlerMapping对象。

3.直接看handlerMappings对象,可以看见非常清楚,这几个就是我们自己写的contoller里面的路径,以及对应的方法,也是用Map储存的。

4.步过,可以看mappedHandler对象的HandlerMethod有了对应的方法,以及还有自定义的拦截器,由此,HandlerExecutionChain对象就获取到了。

(3)获取HandlerAdapter

1.找到对应的代码。

2.步入进去,可以看见HandlerAdapter有许多处理适配器,其中就有熟悉的参数解析器和结果返回处理器。

(4)执行拦截器的preHandle方法

1.这段代码就是应用preHandle。

2.步入进去,就是循环把所有的拦截器的preHandle方法执行,直到返回值为false的时候停止。也可以看见控制台输出的内容就是自定义的拦截器的preHandle方法执行输出的内容。

(5)执行HandlerAdapter(HandlerMethod)

1.找到对应的代码,因为ha就是前面获取的HandlerAdapter对象。

2.在controller层打上断点,验证是否就是真正执行的该方法,发现就是在这。

3.放行,回到刚刚的位置,可以发现mv就已经有了视图的数据模型。

(6)执行拦截器的postHandle

1.可以看见该方法名字就是对应的执行拦截器的后置处理器。

2.步入,就是循环把所有的拦截器的后置处理器方法执行。

(7)执行异常处理器逻辑(全局异常处理器)

1.该方法就是处理全局异常的方法。

2.处理异常的逻辑代码。

3.如果有异常,就会执行自定义的异常处理方法,并返回对应的视图。

(8)解析视图(使用response对象响应数据)

1.找到了render也就是渲染的意思。

2.步入this.render(mv, request, response)进去。可以看见代码比较清晰,就是把mv里面的视图和数据模型通过视图解析器解析,然后通过response对象响应。

(9)渲染视图

这个render方法里面的render方法就是真正渲染视图的方法。

(10)执行拦截器的afterCompletion方法

1.这个mappedHandler.triggerAfterCompletion()就是执行拦截器afterCompletion方法。

2.步入进去,这个方法就是执行所有拦截器的afterCompletion方法。

3.面试应该如何说呢?

参考了黑马程序员的图片,如下图所示:

相关推荐

  1. SpringMVC执行流程

    2024-02-03 00:48:01       9 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-03 00:48:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-03 00:48:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-03 00:48:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-03 00:48:01       20 阅读

热门阅读

  1. HTTP无状态协议和服务器端状态管理

    2024-02-03 00:48:01       29 阅读
  2. 重新配置vue项目时出现的:连接已断开问题

    2024-02-03 00:48:01       26 阅读
  3. linux ssh 时环境变量

    2024-02-03 00:48:01       31 阅读
  4. 学术写作|第二篇论文写作记录|GPT4论文润色Prompt

    2024-02-03 00:48:01       24 阅读
  5. C语言的流程结构和语句分类

    2024-02-03 00:48:01       29 阅读
  6. git的使用

    2024-02-03 00:48:01       26 阅读
  7. 基于Qt5录音项目演示

    2024-02-03 00:48:01       32 阅读
  8. vue插槽

    vue插槽

    2024-02-03 00:48:01      28 阅读
  9. 力扣0117——填充每一个节点的下一个右侧指针II

    2024-02-03 00:48:01       31 阅读
  10. linux的nginx安装

    2024-02-03 00:48:01       29 阅读
  11. Axios 和 Ajax 的区别

    2024-02-03 00:48:01       32 阅读
  12. Android中 Gradle与 AGP 版本对应关系表

    2024-02-03 00:48:01       29 阅读