一、引言
Spring MVC 是 Spring 框架的一个重要组成部分,它是基于 Java 实现的一个轻量级 Web 框架,遵循 MVC(Model-View-Controller)设计模式,用于构建 Web 应用程序。理解 Spring MVC 的请求处理流程对于开发高效、可维护的 Web 应用至关重要。本文将详细介绍 Spring MVC 的请求处理流程。
二、Spring MVC 核心组件
在深入了解请求处理流程之前,先认识一下 Spring MVC 的几个核心组件:
- DispatcherServlet:作为 Spring MVC 的前端控制器,它是整个请求处理流程的核心调度者,负责接收所有的 HTTP 请求,并将请求分发给合适的处理器进行处理。
- HandlerMapping:用于将请求映射到具体的处理器(Controller)和处理器拦截器(HandlerInterceptor)。它根据请求的 URL 等信息,找到对应的处理器。
- HandlerAdapter:由于不同的处理器可能有不同的方法签名和调用方式,HandlerAdapter 的作用就是将 DispatcherServlet 传递过来的请求适配到具体的处理器方法上进行调用。
- Controller:处理器,负责处理具体的业务逻辑。它接收请求参数,调用业务服务进行处理,并返回处理结果。
- ViewResolver:根据处理器返回的视图名称,解析出具体的视图对象(如 JSP、Thymeleaf 模板等)。
- View:视图对象,负责将模型数据渲染成最终的 HTML 页面返回给客户端。
三、请求处理流程详细步骤
3.1 客户端发送请求
客户端(如浏览器)向服务器发送 HTTP 请求,请求的目标是 Spring MVC 应用的某个 URL。
3.2 DispatcherServlet 接收请求
所有的请求首先会被 DispatcherServlet 接收,它作为前端控制器,是请求的入口点。在 Spring MVC 应用启动时,会在 web.xml 或 Java 配置类中配置 DispatcherServlet,将其映射到特定的 URL 模式,例如 *.do 或 /。
3.3 HandlerMapping 查找处理器
DispatcherServlet 接收到请求后,会调用 HandlerMapping 组件,根据请求的 URL 等信息查找对应的处理器(Controller)和处理器拦截器。HandlerMapping 会返回一个 HandlerExecutionChain 对象,该对象包含了处理器和与之关联的拦截器列表。
3.4 HandlerAdapter 适配处理器
DispatcherServlet 拿到 HandlerExecutionChain 后,会根据处理器的类型选择合适的 HandlerAdapter。HandlerAdapter 的作用是将 DispatcherServlet 传递过来的请求适配到具体的处理器方法上进行调用。不同类型的处理器(如实现了 Controller 接口的处理器、使用 @RequestMapping 注解的处理器等)需要不同的 HandlerAdapter 来进行适配。
3.5 执行处理器方法
HandlerAdapter 调用处理器的具体方法进行业务逻辑处理。在处理过程中,处理器可以接收请求参数、调用业务服务进行数据处理,并返回一个 ModelAndView 对象,该对象包含了模型数据和视图名称。
3.6 执行处理器拦截器的后置处理方法
如果在 HandlerExecutionChain 中存在处理器拦截器,在处理器方法执行完成后,会依次调用拦截器的后置处理方法(postHandle)。这些方法可以对处理器的执行结果进行进一步的处理,如修改模型数据、设置响应头信息等。
3.7 ViewResolver 解析视图
DispatcherServlet 拿到处理器返回的 ModelAndView 对象后,会调用 ViewResolver 组件,根据视图名称解析出具体的视图对象。ViewResolver 会根据配置的规则,将视图名称映射到实际的视图资源,如 JSP 文件、Thymeleaf 模板等。
3.8 视图渲染
DispatcherServlet 将模型数据传递给解析出的视图对象,视图对象根据模型数据进行渲染,生成最终的 HTML 页面。渲染完成后,将 HTML 页面作为响应内容返回给客户端。
3.9 执行处理器拦截器的完成处理方法
在视图渲染完成后,会依次调用处理器拦截器的完成处理方法(afterCompletion)。这些方法可以进行一些资源清理、日志记录等操作。
四、示例代码及配置
4.1 Java 配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class AppConfig {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
4.2 处理器(Controller)
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/hello")
public String sayHello(Model model) {
model.addAttribute("message", "Hello, Spring MVC!");
return "hello";
}
}
4.3 web.xml 配置(如果使用传统的 XML 配置方式)
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.example.config.AppConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4.4 JSP 视图(/WEB-INF/views/hello.jsp)
<!DOCTYPE html>
<html>
<head>
<title>Hello Spring MVC</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
五、总结
Spring MVC 的请求处理流程是一个有序的、模块化的过程,通过各个核心组件的协同工作,实现了请求的接收、处理和响应。理解这个流程有助于开发者更好地进行 Spring MVC 应用的开发和调试,能够更灵活地配置和扩展应用的功能。
777

被折叠的 条评论
为什么被折叠?



