Spring MVC


一、Spring MVC 功能

# Spring MVC 本质上还是在使用 Servlet 处理;
# 并在其基础上进行了封装简化了开发流程;
# 提高易用性、并使用程序逻辑结构变得更清晰。

# - MVC 体系结构:
1. 基于注解的URL映射。
2. 表单参数映射。
3. 缓存处理。
4. 全局统一异常处理。
5. 拦截器的实现。
6. 下载处理。

1. Servlet 处理流程

在这里插入图片描述

1. 请求Servlet。
2. 处理业务逻辑。
3. 设置业务Model。
4. Forward Jsp Servlet。
5. Jsp Servlet 解析封装 html,并返回。

2. MVC 处理流程

在这里插入图片描述

1. URL映射。
2. 表单参数映射。
3. 调用目标Controller。
4. 数据模型映射。
5. 视图解析。
6. 异常处理。

二、Spring MVC 开始

1. pom.xml

<!-- servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

<!-- spring-webmvc -->
<dependency>
 	<groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.8.RELEASE</version>
</dependency>

2. web.xml

<!-- 全局调度器 -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <!-- mvc配置路径 -->
        <param-name>contextConfigLocation</param-name>
        <!-- classpath加*表示在所有jar包中寻找配置文件 -->
        <!--<param-value>classpath*:/spring-mvc.xml</param-value>-->
        <param-value>classpath:/spring-mvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!-- 这里不要写 /* 访问静态资源会有问题 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

3. Controller

public class FastController implements Controller {

    /**
     * 1. Controller接口
     * <bean name="/fast.do" class="com.qs.spring_mvc_fast.controller.FastController"/>
     * <p>
     * <a href="http://localhost:8888/fast.do">...</a>
     */
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("[FastController].[handleRequest]");
        ModelAndView modelAndView = new ModelAndView("/WEB-INF/page/fast_view.jsp");
        modelAndView.addObject("name", "FastController");
        return modelAndView;
    }
}

4. fast_view.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Spring MVC 开始</title>
</head>
<body>
登录人:${name}
</body>
</html>

5. spring-mvc.xml

<!-- 1. Controller接口 -->
<bean name="/fast.do" class="com.qs.spring_mvc_fast.controller.FastController"/>

三、Spring MVC 组件

  • MVC 组件:

在这里插入图片描述

1. DispatcherServlet 前端控制器

# - 核心调度器:
作为整个 Spring MVC 框架的核心组件,负责接收所有的 HTTP 请求;
并根据请求的 URL 将其分发给相应的处理程序。
# - 请求处理流程控制:
它管理着整个请求处理的生命周期;
从接收请求、调用处理方法到返回响应,协调各个组件之间的工作。

2. HandlerMapping 处理器映射器

# - 请求与处理器的匹配:
根据请求的 URL、HTTP 方法等信息,将请求映射到对应的处理器(Handler);
即具体的@Controller注解标注的方法或Controller接口的实现类中的方法。
# - 多种映射策略:
支持多种映射方式,如基于 URL 路径的简单映射、基于注解的映射等;
以灵活地满足不同的业务需求。

在这里插入图片描述

# - URI与控制器的映射:
1. 其为 MVC 中 URI 路径与 Controller 对象的映射。
2. DispatcherServlet 就是基于此组件,来寻找对应的 Controller。
3. 如果找不到就会报 `No mapping found for HTTP request with URI` 的异常。

# HandlerMapping:
1. HandlerMapping 的作用是通过 URI 找到对应的 Handler。
2. 但其方法 handlerMapping.getHandler(request) 并不会直接返回 Handler 对象。
3. 而是返回 HandlerExecutionChain 对象。
4. 再通过 handlerExecutionChain.getHandler() 返回最终的 Handler。
1. HandlerMapping、HandlerExecutionChain 接口方法

在这里插入图片描述

2. HandlerMapping 接口实现类

在这里插入图片描述

# HandlerMapping 接口实现类:

# 1. BeanNameUrlHandlerMapping:【默认】
基于 IOC beanName 中"/"开头的 Bean 进行注册至映射。
# 2. SimpleUrlHandlerMapping:
基于手动配置 URI 与 Controller 映射。
# 3. RequestMappingHandlerMapping:
基于 @RequestMapping 注解配置对应映射。

2. HandlerMapping 实现类

1. BeanNameUrlHandlerMapping Bean名称Url【默认】
1. BeanNameUrlHandlerMapping 类结构

在这里插入图片描述

BeanNameUrlHandlerMapping 实现上与 SimpleUrlHandlerMapping 一至;
唯一区别在于继承自 AbstractDetectingUrlHandlerMapping;
通过对应 detectHandlers 可以在无配置的情况下发现 URI 与 Handler 映射。
2. spring-mvc_BeanNameUrlHandlerMapping.xml
<!-- 一、BeanNameUrlHandlerMapping:Bean名称Url【默认】
基于 IOC beanName 中 "/" 开头的 Bean 进行注册至映射。
默认配置:spring-webmvc-4.3.8.RELEASE.jar!\org\springframework\web\servlet\DispatcherServlet.properties -->

<!-- 1. Controller接口
http://localhost:8888/beanNameUrlHandlerMapping.do -->
<bean name="/beanNameUrlHandlerMapping.do"
      class="com.qs.spring_mvc_fast.controller.HandlerMapping.HandlerMappingController"/>

<!-- 2. HttpServlet接口 -->
<!-- 2.1 配置控制器
http://localhost:8888/beanNameUrlHandlerMapping2.do -->
<bean id="/beanNameUrlHandlerMapping2.do"
      class="com.qs.spring_mvc_fast.controller.HandlerAdapter.SimpleServletHandlerAdapterController"/>
<!-- 2.2 配置适配器 -->
<bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/>

<!-- 3. HttpRequestHandler接口
http://localhost:8888/beanNameUrlHandlerMapping3.do -->
<bean name="/beanNameUrlHandlerMapping3.do"
      class="com.qs.spring_mvc_fast.controller.HandlerAdapter.HttpRequestHandlerAdapterController"/>
2. SimpleUrlHandlerMapping 简单Url
1. SimpleUrlHandlerMapping 类结构

在这里插入图片描述

# - SimpleUrlHandlerMapping 初始化流程:
1. org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#setUrlMap
2. org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#initApplicationContext
3. org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#registerHandlers
4. org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#registerHandler()
`
/ # 表示根Handler。
/* # 表示默认Handler。
`

# - 获取 Handler 流程:
1. org.springframework.web.servlet.DispatcherServlet#doService
2. org.springframework.web.servlet.DispatcherServlet#doDispatch
3. org.springframework.web.servlet.DispatcherServlet#getHandler
4. org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
5. org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#getHandlerInternal
6. org.springframework.web.util.UrlPathHelper#getPathWithinApplication
# 获取 URI 路径
7. org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#lookupHandler
# 查找 Handler
8. org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandlerExecutionChain
# 封装执行链
2. spring-mvc_SimpleUrlHandlerMapping.xml
<!-- 二、SimpleUrlHandlerMapping:简单Url
基于手动配置 URI 与 Controller映射 -->

<bean name="simpleUrlHandlerMapping"
      class="com.qs.spring_mvc_fast.controller.HandlerMapping.HandlerMappingController"/>
<bean name="simpleUrlHandlerMapping2"
      class="com.qs.spring_mvc_fast.controller.HandlerMapping.HandlerMappingController"/>

<!-- 源码:org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(java.lang.String, java.lang.Object) -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="order" value="100"/>
    <!-- 属性注入 -->
    <property name="urlMap">
        <props>
        	<!-- 1. Url映谢器 -->
            <!-- http://localhost:8888/simpleUrlHandlerMapping.do -->
            <prop key="/simpleUrlHandlerMapping.do">simpleUrlHandlerMapping</prop>
            <!-- http://localhost:8888/simpleUrlHandlerMapping2.do -->
            <prop key="/simpleUrlHandlerMapping2.do">simpleUrlHandlerMapping2</prop>
            <!-- http://localhost:8888/simpleUrlHandlerMapping2-back.do -->
            <prop key="/simpleUrlHandlerMapping2-back.do">simpleUrlHandlerMapping2</prop>
        </props>
    </property>
</bean>
3. RequestMappingHandlerMapping @RequestMapping注解
1. spring-mvc2_RequestMappingHandlerMapping.xml
<!-- 三、RequestMappingHandlerMapping:@RequestMapping注解
基于 @RequestMapping 注解配置对应映射
基于注解实现 -->

<!-- 1. @RequestMapping注解 -->
<!-- 1.1 包扫描
http://localhost:8888/anno/handlerMethod.do
-->
<context:component-scan base-package="com.qs.spring_mvc_fast.controller"/>
<!-- 1.2 注解驱动 -->
<mvc:annotation-driven/>

3. HandlerAdapter 处理器适配器

# - 适配处理器执行:
由于不同的处理器可能有不同的接口或实现方式;
HandlerAdapter 负责调用具体的处理器方法,并将请求参数等信息传递给处理器;
使 DispatcherServlet 能够统一地调用各种类型的处理器。
# - 支持多种处理器类型:
可以适配不同类型的处理器;
如基于注解的控制器、实现了特定接口的控制器等;
增强了框架的灵活性和扩展性。

# 1. Spring MVC 采用适配器模式来适配调用指定 Handler;
# 2. 根据 Handler 的不同种类,采用不同的 Adapter。

当 IOC 实例化这些类之后;
DispatcherServlet 就会通过 dispatcherServlet.getHandlerAdapter(handler) 方法查找对应 Handler 适配器;
如果找不到就会报异常 `No adapter for handler`
1. HandlerAdapter 接口方法

在这里插入图片描述

2. HandlerAdapter 接口实现类

在这里插入图片描述

# 1. SimpleControllerHandlerAdapter
标准控制器,返回 ModelAndView。
# 2. SimpleServletHandlerAdapter
基于标准的 Servlet 处理。
# 3. HttpRequestHandlerAdapter
业务自行处理请求,不需要通过 ModelAndView 转到视图。
# 4. RequestMappingHandlerAdapter
基于 @RequestMapping 对应方法处理。

4. Handler 处理器

# - 业务逻辑处理:
也称为控制器(Controller),是具体处理业务逻辑的组件。
通常使用@Controller注解标注,在其方法中编写处理 HTTP 请求的业务逻辑;
如调用服务层接口获取数据、进行数据处理等,并返回相应的结果或视图名称。

在这里插入图片描述

在 AbstractUrlHandlerMapping 类可以看到存储 Handler 的 Map 值类型是 Object;
意味着所有的类都可以做来 Handler 来使用。

在这里插入图片描述

1. Controller接口。
2. HttpRequestHandler接口。
3. HttpServlet接口。
4. @RequestMapping方法注解。

# - 可以看出 Handler 没有统一的接口;
# 当 DispatchServlet 获取当对应的 Handler 之后如何调用呢?调用其哪个方法?
# 这里有两种解决办法:
1. 一是用 instanceof 判断 Handler 类型然后调用相关方法。
2. 二是通过引入适配器,每个适配器实现对指定 Handler 的调用。
3. Spring 采用后者。

4. Handler 与 HandlerAdapter 对应关系

Handler类别对应适配器说明
Controller接口SimpleControllerHandlerAdapter标准控制器,返回 ModelAndView。
HttpServlet接口SimpleServletHandlerAdapter基于标准的 Servlet 处理。
HttpRequestHandler接口HttpRequestHandlerAdapter业务自行处理请求,不需要通过 ModelAndView 转到视图。
HandlerMethodRequestMappingHandlerAdapter基于 @RequestMapping 对应方法处理。
1. SimpleControllerHandlerAdapter 控制器适配器
2. SimpleServletHandlerAdapter Servlet适配器
/**
 * 2. HttpServlet接口
 * SimpleServletHandlerAdapter
 * 基于标准的 Servlet 处理。
 *
 * @author wy
 */
public class SimpleServletHandlerAdapterController extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	System.out.println("[SimpleServletHandlerAdapterController].[doGet]");
        super.doGet(req, resp);
        resp.getWriter().println("SimpleServletHandlerAdapterController");
    }
}
<!-- 2. HttpServlet接口 -->
<!-- 2.1 配置控制器 -->
<bean id="/simpleServletHandlerAdapter.do"
      class="com.qs.spring_mvc_fast.controller.HandlerAdapter.SimpleServletHandlerAdapterController"/>
<!-- 2.2 配置适配器 -->
<bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/>
3. HttpRequestHandlerAdapter Http适配器
4. RequestMappingHandlerAdapter @RequestMapping适配器

5. ViewResolver 视图解析器

# - 视图选择与解析:
根据处理器返回的视图名称,选择并解析相应的视图;
如 JSP、Thymeleaf、FreeMarker 等视图技术,将模型数据填充到视图中,生成最终的 HTML 页面或其他响应内容返回给客户端。
# - 视图配置与管理:
可以配置多种视图解析策略,支持不同的视图技术和视图文件的存放位置等;
方便开发者根据项目需求进行选择和调整。

找到应的 Adapter 之后,就会基于适配器调用业务处理;
处理完业务方法之后,会返回一个 ModelAndView,再去查找对应的视图进行处理;
其在 dispatcherServlet.resolveViewName(viewName,model,..) 中遍历 viewResolvers 列表查找;
如果找不到就会报一个异常 `Could not resolve view with name`
1. ViewResolver 实现类

在这里插入图片描述

1. BeanNameViewResolver Bean名称视图解析器
<!-- 五、Bean名称视图解析器 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>

<!-- 默认资源视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/ViewResolver/"/>
    <property name="suffix" value=".jsp"/>
    <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
</bean>
<!-- 视图仓库 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/ViewResolver/"/>
    <property name="suffix" value=".jsp"/>
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
</bean>

6. ModelAndView 模型与视图

# - 数据与视图封装:
用于封装处理器处理请求后生成的模型数据和视图信息。
模型数据可以是各种 Java 对象,视图信息则包含视图名称等;
方便在处理器和视图解析器之间传递数据和视图相关的信息。

基于 viewResolver.resolveViewName(viewName,.) 获取对应 View;
来解析生成 html 并返回。
1. View 接口实现类

在这里插入图片描述

/**
 * 自定义视图
 *
 * @author wy
 */
public class ViewX implements View {

    @Override
    public String getContentType() {
    	System.out.println("[ViewX].[getContentType]");
        return null;
    }

    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("[ViewX].[render] model = " + model);
        response.getWriter().print(String.format("ViewX:%s", model.get("name")));
    }
}
<!-- 六、配置自定义视图 -->
<bean name="viewX" class="com.qs.spring_mvc_fast.controller.ModelAndView.ViewX"/>

7. 数据绑定与验证组件

# - 数据绑定:
将 HTTP 请求中的参数自动绑定到处理器方法的参数或 Java 对象中;
方便开发者获取和处理请求数据,减少了手动获取和转换请求参数的繁琐工作。
# - 数据验证:
对绑定的数据进行合法性验证,如检查必填字段、数据格式等,确保数据的有效性和完整性。
通常与 Java Bean Validation 等验证框架集成使用。

8. HandlerInterceptor 拦截器

# - 请求预处理与后处理:
可以在请求处理的前后进行一些通用的操作,如权限验证、日志记录、性能监控等。
类似于 Servlet 中的过滤器,但更侧重于对请求处理过程的拦截和增强。
# - 链式调用与灵活配置:
多个拦截器可以组成一个拦截器链,按照一定的顺序对请求进行处理;
并且可以根据需要灵活配置拦截器的执行顺序和作用范围。

# - HandlerInterceptor 用于对请求拦截;
与原生 Filter 区别在于 Filter 只能在业务执行前拦截;
而 HandlerInterceptor 可以在业务处理前、中、后进行处理。

# - 实现机制是基于 HandlerExecutionChain 分别在 doDispatch 方法中执行以下方法:
1. preHandle() # 业务处理前执行。
2. postHandle() # 业务处理后(异常则不执行)。
3. afterCompletion() # 视图处理后。

# - 逻辑源码 
org.springframework.web.servlet.DispatcherServlet#doDispatch 方法。
/**
 * 自定义拦截器
 *
 * @author wy
 */
public class HandlerInterceptorX implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("[HandlerInterceptorX].[preHandle] handler = " + handler);
        // 返回false拦截
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("[HandlerInterceptorX].[postHandle] handler = " + handler + ", modelAndView = " + modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("[HandlerInterceptorX].[afterCompletion] handler = " + handler + ", ex = " + ex);
    }

}
<!-- 八、配置自定义拦截器 -->
<bean name="handlerInterceptor"
	  class="com.qs.spring_mvc_fast.controller.HandlerInterceptor.HandlerInterceptorX"/>

9. HandlerExceptionResolver 异常处理器

# - 异常处理与统一响应:
用于处理在请求处理过程中发生的各种异常情况,如业务异常、运行时异常等。
可以根据不同的异常类型进行针对性的处理,返回统一的错误页面或错误信息给客户端;
提高了系统的稳定性和用户体验。

# - 该组件用于指示当出现异常时,MVC 该如何处理: 
1. DispatcherServlet 会调用 dispatcherServlet.processHandlerException(request,response,handler,ex) 方法;
2. 遍历 handlerExceptionResolvers 处理异常;
3. 处理完成之后返回 errorView 跳转到异常视图。
1. HandlerExceptionResolver 接口实现类

在这里插入图片描述

# 1. DefaultHandlerExceptionResolver:【默认】
Spring mvc 默认异常处理。
# 2. ResponseStatusExceptionResolver:【默认】
用于解析带 @ResponseStatus 的自定义异常。
# 3. SimpleMappingExceptionResolver:
异常映射,将指定异常与错误页面相对应。

9. HandlerExceptionResolver 实现类

1. DefaultHandlerExceptionResolver 默认异常处理器
/**
 * 自定义异常处理器
 * <p>
 * 默认异常处理器:
 * {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#doResolveException(HttpServletRequest, HttpServletResponse, Object, Exception)}
 *
 * @author wy
 */
public class HandlerExceptionResolverX implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView modelAndView = new ModelAndView("/WEB-INF/HandlerExceptionResolver/HandlerExceptionResolver.jsp");
        // 错误类型
        if (ex instanceof IllegalArgumentException) { // 非法参数异常
            modelAndView.addObject("errorType", "非法参数");
        } else {
            modelAndView.addObject("errorType", ex.getClass().getName());
        }
        // 错误信息
        modelAndView.addObject("message", ex.getMessage());
        // 堆栈信息
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ex.printStackTrace(new PrintStream(outputStream, true));
        modelAndView.addObject("stack", outputStream.toString());
        return modelAndView;
    }
}
<!-- 九、配置异常处理器 -->

<!-- 1. 自定义异常处理器 -->
<bean class="com.qs.spring_mvc_fast.controller.HandlerExceptionResolver.HandlerExceptionResolverX"/>
<!-- 2. 响应状态异常处理器(默认存在的)-->
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver"/>
2. SimpleMappingExceptionResolver 简单的映射异常解析器
<!-- 3. 简单的映射异常解析器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!-- 全局默认异常 -->
    <property name="defaultErrorView" value="error"/>
    <property name="defaultStatusCode" value="500"/>
    <property name="exceptionMappings">
        <map>
            <!-- 指定异常 -->
            <entry key="java.lang.RuntimeException" value="runtime_exception"/>
            <!-- IllegalArgumentException 是 RuntimeException 子类 -->
            <entry key="java.lang.IllegalArgumentException" value="illegal_argument_exception"/>
        </map>
    </property>
</bean>

10. 本地化与国际化组件

# - 语言与地区支持:
支持根据客户端的语言偏好和地区设置,对应用中的文本信息进行本地化和国际化处理;
使应用能够以不同的语言和格式展示给用户。
# - 资源文件管理:
通过配置资源文件,将不同语言和地区的文本信息进行统一管理;
方便在视图中引用和显示本地化的内容。

四、Spring MVC 执行流程

在这里插入图片描述

五、DispatchServlet 初始化流程

1. 创建 WebApplicationContext

1. org.springframework.web.servlet.HttpServletBean#init
2. org.springframework.web.servlet.FrameworkServlet#initServletBean
3. org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext
4. org.springframework.web.servlet.FrameworkServlet#createWebApplicationContext(org.springframework.context.ApplicationContext)
# 基于当前存在的 Spring 上下文做为 Root,创建 MVC 上下文。 
5. org.springframework.web.servlet.FrameworkServlet#configureAndRefreshWebApplicationContext
6. org.springframework.context.support.AbstractApplicationContext#refresh

2. 基于策略模型加载各组件

六、@RequestMapping 注解

<!-- 4. @RequestMapping注解 -->
<!-- 4.1 包扫描 -->
<context:component-scan base-package="com.qs.spring_mvc_fast.controller"/>
<!-- 4.2 注解驱动 -->
<mvc:annotation-driven/>

/**
 * 4. HandlerMethod
 * RequestMappingHandlerAdapter适配器
 * 基于 @RequestMapping 对应方法处理。
 *
 * @author wy
 */
@Controller
@RequestMapping("anno")
public class RequestMappingController {

	/**
	 * <!-- 4. @RequestMapping注解 -->
	 * <!-- 4.1 包扫描 -->
	 * <context:component-scan base-package="com.qs.spring_mvc_fast.controller.HandlerAdapter"/>
	 * <!-- 4.2 注解驱动 -->
	 * <mvc:annotation-driven/>
	 * <p>
	 * <a href="http://localhost:8888/anno/handlerMethod.do">...</a>
	 * <p>
	 * 参数封装:org.springframework.core.ParameterNameDiscoverer
	 */
	@RequestMapping("/handlerMethod.do")
	public ModelAndView handlerMethod(String name) {
	    System.out.println("[RequestMappingController].[handlerMethod] name = " + name);
	    ModelAndView modelAndView = new ModelAndView("/WEB-INF/HandlerAdapter/HandlerAdapter.jsp");
	    modelAndView.addObject("name", "RequestMappingController");
	    return modelAndView;
	}
}
# - 为什么基于 <mvc:annotation-driven/> 配置就能实现 MVC 的整个配置了;
# 之前所提到的 handlerMapping 与 handlerAdapter 组件都不适用了?
1. 认识 NamespaceHandler 接口。
2. 查看 MvcNamespaceHandler。
3. 查看 AnnotationDrivenBeanDefinitionParser。

# - 结论:在 <mvc:annotation-driven/> 对应的解析器,自动向 IOC 里面注册了两个 BeanDefinition。
分别是 RequestMappingHandlerMapping 与 BeanNameUrlHandlerMapping 组件。

1. 实现结构

在这里插入图片描述

1. RequestMappingHandlerMapping # URI 映射器。
2. RequestMappingHandlerAdapter # 执行适配器。
3. InvocableHandlerMethod # Controller目标对象,包含了 Controller Bean 及对应的 Method 对象,及调用方法。
`
1. HandlerMethodArgumentResolverComposite # 参数处理器。
2. ParameterNameDiscoverer # 参数名称处理器。
3. HandlerMethodReturnValueHandlerComposite # 返回结构处理器。
`

2. 执行流程

# - 映射流程:
1. org.springframework.web.servlet.DispatcherServlet#getHandler
# 基于注解查找映射Api。
2. org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
3. org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod
4. org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#getMappingsByUrl

# - 调用流程:
1. org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
2. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
3. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
4. org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
5. org.springframework.web.method.support.InvocableHandlerMethod#doInvoke
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑士梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值