spring MVC的流程
Spring MVC 是 Spring 框架中用于构建 Web 应用程序的核心模块,基于 MVC(Model-View-Controller)设计模式,通过清晰的职责分离简化开发。以下是 Spring MVC 的完整工作流程及核心组件详解:
1. Spring MVC 核心流程图示
2. 详细步骤解析
步骤 1:客户端发起请求
-
用户通过浏览器访问 URL(如
/user/list),请求被发送到DispatcherServlet(Spring MVC 的前端控制器)。
步骤 2:DispatcherServlet 接收请求
-
DispatcherServlet是 Spring MVC 的核心,负责协调各组件工作。 -
它继承自
HttpServlet,在web.xml或 Java 配置中映射为全局拦截器(通常配置为/)。
步骤 3:HandlerMapping 查找控制器
-
DispatcherServlet调用HandlerMapping(如RequestMappingHandlerMapping)根据 URL 找到对应的Controller和方法。 -
返回
HandlerExecutionChain(包含目标Controller方法和配置的拦截器)。
步骤 4:调用 Controller 方法
-
DispatcherServlet通过HandlerAdapter(如RequestMappingHandlerAdapter)调用Controller中的目标方法。 -
方法参数(如
@RequestParam、@PathVariable、@RequestBody)由ArgumentResolver解析。 -
方法返回
ModelAndView或直接返回数据(如 JSON 通过@ResponseBody)。
步骤 5:处理业务逻辑
-
Controller调用Service层处理业务逻辑,将数据存入Model对象(或直接返回 DTO)。
步骤 6:返回 ModelAndView
-
Controller返回ModelAndView(包含模型数据 + 视图名),例如:@GetMapping("/user/list") public String listUsers(Model model) { model.addAttribute("users", userService.getAllUsers()); return "user/list"; // 视图名 }
步骤 7:视图解析(ViewResolver)
-
DispatcherServlet调用ViewResolver(如InternalResourceViewResolver)将逻辑视图名(如"user/list")解析为实际视图(如/WEB-INF/views/user/list.jsp)。
步骤 8:渲染视图(View)
-
View对象(如 JSP、Thymeleaf)使用Model中的数据渲染 HTML。 -
渲染结果写入
HttpServletResponse。
步骤 9:返回响应
-
DispatcherServlet将渲染后的 HTML 返回给客户端。
3. 关键组件说明
| 组件 | 作用 |
|---|---|
| DispatcherServlet | 前端控制器,统一接收请求并协调各组件。 |
| HandlerMapping | 映射请求 URL 到对应的 Controller 方法(如 @RequestMapping)。 |
| HandlerAdapter | 实际调用 Controller 方法,处理参数绑定和返回值。 |
| Controller | 处理业务逻辑,返回模型和视图。 |
| Model | 存储业务数据(键值对),传递给视图。 |
| ViewResolver | 将逻辑视图名解析为实际视图(如 JSP、Thymeleaf 模板)。 |
| View | 渲染模型数据生成最终响应(HTML/JSON/XML)。 |
| Interceptor | 拦截请求(如权限检查、日志),在 Controller 前后执行。 |
4. 注解驱动开发示例
Controller 示例
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/list")
public String listUsers(Model model) {
model.addAttribute("users", userService.getAllUsers());
return "user/list"; // 视图名
}
@PostMapping("/save")
public String saveUser(@ModelAttribute User user) {
userService.save(user);
return "redirect:/user/list"; // 重定向
}
@ResponseBody
@GetMapping("/api/{id}")
public User getUserApi(@PathVariable Long id) {
return userService.getById(id); // 直接返回JSON
}
}
配置类示例(Java Config)
@Configuration
@EnableWebMvc
@ComponentScan("com.example")
public class WebConfig implements WebMvcConfigurer {
// 配置视图解析器
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
// 静态资源处理
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("/static/");
}
}
5. 常见问题
Q1: 如何返回 JSON 数据?
-
使用
@RestController或@ResponseBody,并添加 Jackson 依赖:@RestController @RequestMapping("/api/user") public class UserApiController { @GetMapping("/{id}") public User getUser(@PathVariable Long id) { return userService.getById(id); } }
Q2: 如何全局处理异常?
-
使用
@ControllerAdvice:@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception e) { return ResponseEntity.status(500).body("Error: " + e.getMessage()); } }
Q3: 如何自定义拦截器?
-
实现
HandlerInterceptor接口并注册:public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getSession().getAttribute("user") == null) { response.sendRedirect("/login"); return false; } return true; } } // 注册拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**"); }
总结
Spring MVC 通过 DispatcherServlet 协调各组件,实现请求的路由、处理、渲染。掌握其流程和关键组件(如 HandlerMapping、ViewResolver)是开发高效 Web 应用的基础。现代 Spring Boot 进一步简化了配置,但底层机制仍遵循此流程。


浙公网安备 33010602011771号