DispatcherServlet
DispatcherServlet 是 Spring MVC 的前端控制器,它负责接收所有的 HTTP 请求,并将请求分发到相应的处理器。它是整个 Spring MVC 框架的核心组件。
初始化:DispatcherServlet 在启动时会初始化一系列的组件,如 HandlerMapping、HandlerAdapter、ViewResolver 等。 请求处理:接收到请求后,DispatcherServlet 会通过 HandlerMapping 找到合适的处理器,然后通过 HandlerAdapter 调用处理器方法。
HandlerMapping HandlerMapping 负责将请求映射到处理器。Spring MVC 提供了多种 HandlerMapping 实现,包括:
RequestMappingHandlerMapping:基于 @RequestMapping 注解进行请求映射。 BeanNameUrlHandlerMapping:基于 Bean 名称进行请求映射。 SimpleUrlHandlerMapping:基于 URL 模式进行请求映射。
HandlerAdapter HandlerAdapter 负责调用处理器方法。Spring MVC 提供了多种 HandlerAdapter 实现,包括:
RequestMappingHandlerAdapter:支持基于 @RequestMapping 注解的方法调用。 HttpRequestHandlerAdapter:支持 HttpRequestHandler 接口的方法调用。
Controller 控制器是处理请求的主要组件。在 Spring MVC 中,控制器类通常使用 @Controller 注解标记,并且方法上使用 @RequestMapping 或其派生注解(如 @GetMapping, @PostMapping)来指定处理哪些请求。
ModelAndView ModelAndView 对象用于封装模型数据和视图信息。控制器方法可以返回 ModelAndView 对象,其中包含模型数据和视图名称。
ViewResolver 视图解析器负责将逻辑视图名称解析为具体的视图对象。常用的视图解析器有:
InternalResourceViewResolver:用于 JSP 视图。 ThymeleafViewResolver:用于 Thymeleaf 视图。 FreeMarkerViewResolver:用于 FreeMarker 视图。
View 视图负责渲染最终的页面,展示给用户。视图可以是 JSP、FreeMarker、Thymeleaf 等模板引擎生成的页面。
工作流程
客户端发送请求:客户端(如浏览器)发送 HTTP 请求到服务器。 请求到达 DispatcherServlet:请求被 DispatcherServlet 捕获。 HandlerMapping 定位处理器:DispatcherServlet 使用 HandlerMapping 查找处理请求的控制器方法。 HandlerAdapter 调用处理器:DispatcherServlet 使用 HandlerAdapter 调用控制器方法。 控制器处理请求:控制器方法处理请求,返回 ModelAndView 对象。 ViewResolver 解析视图:DispatcherServlet 使用 ViewResolver 将逻辑视图名称解析为具体的视图对象。 视图渲染:视图对象渲染最终的页面,并返回给客户端。 配置方式 XML 配置 传统的 Spring MVC 配置通常是通过 XML 文件完成的。
Java 配置
现代的 Spring MVC 项目通常使用 Java 配置。以下是一个简单的 Java 配置示例:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration @ComponentScan(basePackages = "com.example.controller") @EnableWebMvc public class WebConfig implements WebMvcConfigurer {
@Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; }
}
最佳实践 分层设计:将应用分为控制器层、服务层和数据访问层,保持各层职责清晰。 异常处理:使用 @ControllerAdvice 和 @ExceptionHandler 注解来集中处理异常。 数据验证:使用 JSR-303 标准的数据验证框架(如 Hibernate Validator)来验证请求参数。 国际化:使用 Spring 的国际化支持来提供多语言界面。 安全性:使用 Spring Security 来保护应用的安全性。 性能优化:合理使用缓存、异步处理等技术来提升应用性能。 示例项目 假设我们有一个简单的 Spring Boot 项目,使用 Spring MVC 构建一个基本的 Web 应用程序。
项目目录结构
src/main/java │── com.example │ └── controller │ └── HelloWorldController.java │── com.example.service │ └── HelloWorldService.java │── com.example.repository │ └── HelloWorldRepository.java └── Application.java
src/main/resources │── static │── templates │── application.properties
控制器 (HelloWorldController.java)
package com.example.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import com.example.service.HelloWorldService;
@Controller public class HelloWorldController {
@Autowired private HelloWorldService helloWorldService; @GetMapping("/hello") public String hello(Model model) { String message = helloWorldService.getMessage(); model.addAttribute("message", message); return "hello"; // 返回视图名称 }
}
服务层 (HelloWorldService.java)
package com.example.service;
import org.springframework.stereotype.Service;
@Service public class HelloWorldService {
public String getMessage() { return "Hello, Spring MVC!"; }
}
全局异常处理 (GlobalExceptionHandler.java)
package com.example.controller;
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView handleException(Exception ex) { ModelAndView modelAndView = new ModelAndView("error"); modelAndView.addObject("errorMessage", ex.getMessage()); return modelAndView; }
}