spring MVC的流程

Spring MVC 是 Spring 框架中用于构建 Web 应用程序的核心模块,基于 MVC(Model-View-Controller)设计模式,通过清晰的职责分离简化开发。以下是 Spring MVC 的完整工作流程及核心组件详解:


1. Spring MVC 核心流程图示

image

 

 
 
 

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(包含模型数据 + 视图名),例如:

    java
     
    @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 示例

java
 
@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)

java
 
@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 依赖:

    java
     
    @RestController
    @RequestMapping("/api/user")
    public class UserApiController {
        @GetMapping("/{id}")
        public User getUser(@PathVariable Long id) {
            return userService.getById(id);
        }
    }

Q2: 如何全局处理异常?

  • 使用 @ControllerAdvice

    java
     
    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(Exception.class)
        public ResponseEntity<String> handleException(Exception e) {
            return ResponseEntity.status(500).body("Error: " + e.getMessage());
        }
    }

Q3: 如何自定义拦截器?

  • 实现 HandlerInterceptor 接口并注册:

    java
     
    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 协调各组件,实现请求的路由、处理、渲染。掌握其流程和关键组件(如 HandlerMappingViewResolver)是开发高效 Web 应用的基础。现代 Spring Boot 进一步简化了配置,但底层机制仍遵循此流程。

posted @ 2025-08-06 13:39  苹果芒  阅读(40)  评论(0)    收藏  举报