🌐 Spring MVC请求处理流程:从请求到响应的完整旅程!

48 阅读6分钟

副标题:DispatcherServlet的精妙设计,MVC的完美实现!🎯


🎬 开场:Spring MVC是什么?

MVC模式

MVC(Model-View-Controller):

┌──────────┐
│  浏览器   │
└─────┬────┘
      │ HTTP请求
      ↓
┌─────────────────────────────┐
│    Controller(控制器)      │
│    - 接收请求                │
│    - 调用Service             │
│    - 返回数据                │
└─────┬───────────────────────┘
      │
      ↓
┌─────────────────────────────┐
│    Model(模型)             │
│    - 业务逻辑                │
│    - 数据处理                │
└─────┬───────────────────────┘
      │
      ↓
┌─────────────────────────────┐
│    View(视图)              │
│    - 渲染页面                │
│    - 展示数据                │
└─────┬───────────────────────┘
      │ HTML响应
      ↓
┌──────────┐
│  浏览器   │
└──────────┘

📚 核心组件

组件总览

Spring MVC核心组件:

1. DispatcherServlet(前端控制器)
   - 接收所有请求
   - 调度其他组件

2. HandlerMapping(处理器映射器)
   - 根据URL找到Handler

3. HandlerAdapter(处理器适配器)
   - 执行Handler

4. Handler(处理器/Controller)
   - 处理业务逻辑

5. ViewResolver(视图解析器)
   - 解析视图名称

6. View(视图)
   - 渲染页面

7. HandlerInterceptor(拦截器)
   - 前置/后置处理

🎯 请求处理流程

完整流程图

Spring MVC请求处理流程(9步):

1. 用户发起请求
   http://localhost:8080/user/1232. DispatcherServlet接收请求
   前端控制器
      ↓
3. HandlerMapping查找Handler
   根据URL找到@RequestMapping("/user/{id}")
      ↓
4. 返回HandlerExecutionChain
   包含Handler和Interceptor
      ↓
5. 执行Interceptor.preHandle()
   前置拦截器
      ↓
6. HandlerAdapter执行Handler
   调用Controller方法
      ↓
7. Handler返回ModelAndView
   包含数据和视图名
      ↓
8. ViewResolver解析视图
   将视图名解析为View对象
      ↓
9. View渲染页面
   生成HTML返回给浏览器
      ↓
10. 执行Interceptor.afterCompletion()
    后置拦截器

详细流程

/**
 * 详细的请求处理流程
 */

// 1. DispatcherServlet.doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
    
    // 2. 获取Handler
    HandlerExecutionChain mappedHandler = getHandler(request);
    
    // 3. 获取HandlerAdapter
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // 4. 执行前置拦截器
    if (!mappedHandler.applyPreHandle(request, response)) {
        return;  // 拦截器返回false,直接返回
    }
    
    // 5. 执行Handler(Controller方法)
    ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());
    
    // 6. 执行后置拦截器
    mappedHandler.applyPostHandle(request, response, mv);
    
    // 7. 处理结果(渲染视图)
    processDispatchResult(request, response, mappedHandler, mv, exception);
}

// 8. 渲染视图
private void processDispatchResult(HttpServletRequest request, 
                                   HttpServletResponse response,
                                   HandlerExecutionChain mappedHandler,
                                   ModelAndView mv,
                                   Exception exception) {
    
    // 解析视图
    render(mv, request, response);
    
    // 执行完成拦截器
    mappedHandler.triggerAfterCompletion(request, response, null);
}

// 9. 解析和渲染视图
protected void render(ModelAndView mv, HttpServletRequest request, 
                     HttpServletResponse response) {
    
    // 视图解析
    View view = resolveViewName(mv.getViewName(), mv.getModelMap(), locale, request);
    
    // 渲染
    view.render(mv.getModelMap(), request, response);
}

🔍 核心组件详解

1️⃣ DispatcherServlet(前端控制器)

/**
 * DispatcherServlet:前端控制器
 * 
 * 所有请求的入口
 */
public class DispatcherServlet extends FrameworkServlet {
    
    /** HandlerMapping列表 */
    private List<HandlerMapping> handlerMappings;
    
    /** HandlerAdapter列表 */
    private List<HandlerAdapter> handlerAdapters;
    
    /** ViewResolver列表 */
    private List<ViewResolver> viewResolvers;
    
    /**
     * 处理请求的核心方法
     */
    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) 
        throws Exception {
        
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        ModelAndView mv = null;
        Exception dispatchException = null;
        
        try {
            // 1. 检查是否是文件上传请求
            processedRequest = checkMultipart(request);
            
            // 2. 获取Handler
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }
            
            // 3. 获取HandlerAdapter
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            
            // 4. 执行前置拦截器
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }
            
            // 5. 执行Handler
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            
            // 6. 设置默认视图名
            applyDefaultViewName(processedRequest, mv);
            
            // 7. 执行后置拦截器
            mappedHandler.applyPostHandle(processedRequest, response, mv);
            
        } catch (Exception ex) {
            dispatchException = ex;
        }
        
        // 8. 处理结果
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    
    /**
     * 获取Handler
     */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }
}

2️⃣ HandlerMapping(处理器映射器)

/**
 * HandlerMapping:处理器映射器
 * 
 * 根据请求URL找到对应的Handler
 */
public interface HandlerMapping {
    
    /**
     * 获取Handler
     */
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

/**
 * RequestMappingHandlerMapping:基于@RequestMapping的映射器
 */
public class RequestMappingHandlerMapping extends AbstractHandlerMapping {
    
    // 存储URL和HandlerMethod的映射关系
    private final MappingRegistry mappingRegistry = new MappingRegistry();
    
    @Override
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        // 1. 获取请求路径
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        
        // 2. 查找HandlerMethod
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        
        // 3. 创建HandlerMethod实例
        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    }
    
    /**
     * 查找HandlerMethod
     */
    protected HandlerMethod lookupHandlerMethod(String lookupPath, 
                                               HttpServletRequest request) throws Exception {
        
        List<Match> matches = new ArrayList<>();
        
        // 直接匹配
        List<RequestMappingInfo> directPathMatches = 
            this.mappingRegistry.getMappingsByUrl(lookupPath);
        
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        
        if (matches.isEmpty()) {
            // 模式匹配
            addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }
        
        if (!matches.isEmpty()) {
            // 排序
            Collections.sort(matches);
            
            Match bestMatch = matches.get(0);
            return bestMatch.handlerMethod;
        }
        
        return null;
    }
}

3️⃣ HandlerAdapter(处理器适配器)

/**
 * HandlerAdapter:处理器适配器
 * 
 * 执行Handler(Controller方法)
 */
public interface HandlerAdapter {
    
    /**
     * 是否支持该Handler
     */
    boolean supports(Object handler);
    
    /**
     * 执行Handler
     */
    ModelAndView handle(HttpServletRequest request, 
                       HttpServletResponse response, 
                       Object handler) throws Exception;
}

/**
 * RequestMappingHandlerAdapter:基于@RequestMapping的适配器
 */
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
    
    @Override
    protected ModelAndView handleInternal(HttpServletRequest request,
                                         HttpServletResponse response,
                                         HandlerMethod handlerMethod) throws Exception {
        
        ModelAndView mav;
        
        // 执行Handler方法
        mav = invokeHandlerMethod(request, response, handlerMethod);
        
        return mav;
    }
    
    /**
     * 调用Handler方法
     */
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                              HttpServletResponse response,
                                              HandlerMethod handlerMethod) throws Exception {
        
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        
        try {
            // 创建参数绑定器
            WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
            
            // 创建Model工厂
            ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
            
            // 创建可调用的方法
            ServletInvocableHandlerMethod invocableMethod = 
                createInvocableHandlerMethod(handlerMethod);
            
            // 设置参数解析器
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            
            // 设置返回值处理器
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            
            // 设置参数绑定器工厂
            invocableMethod.setDataBinderFactory(binderFactory);
            
            // 执行方法
            invocableMethod.invokeAndHandle(webRequest, mavContainer);
            
            // 获取ModelAndView
            return getModelAndView(mavContainer, modelFactory, webRequest);
            
        } finally {
            webRequest.requestCompleted();
        }
    }
}

4️⃣ ViewResolver(视图解析器)

/**
 * ViewResolver:视图解析器
 * 
 * 将视图名解析为View对象
 */
public interface ViewResolver {
    
    /**
     * 解析视图
     */
    View resolveViewName(String viewName, Locale locale) throws Exception;
}

/**
 * InternalResourceViewResolver:JSP视图解析器
 */
public class InternalResourceViewResolver extends UrlBasedViewResolver {
    
    /**
     * 解析视图名
     */
    @Override
    protected View createView(String viewName, Locale locale) throws Exception {
        // 前缀 + 视图名 + 后缀
        // 例如:/WEB-INF/views/ + user/list + .jsp
        // 结果:/WEB-INF/views/user/list.jsp
        
        return super.createView(viewName, locale);
    }
}

/**
 * 配置示例
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");  // 前缀
        resolver.setSuffix(".jsp");             // 后缀
        return resolver;
    }
}

💻 完整示例

Controller

/**
 * 用户Controller
 */
@Controller
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    /**
     * 查询用户列表
     * 
     * GET /user/list
     */
    @GetMapping("/list")
    public String list(Model model) {
        // 1. 调用Service
        List<User> users = userService.list();
        
        // 2. 添加到Model
        model.addAttribute("users", users);
        
        // 3. 返回视图名
        return "user/list";  // /WEB-INF/views/user/list.jsp
    }
    
    /**
     * 查询用户详情
     * 
     * GET /user/123
     */
    @GetMapping("/{id}")
    public String detail(@PathVariable Long id, Model model) {
        User user = userService.getById(id);
        model.addAttribute("user", user);
        return "user/detail";
    }
    
    /**
     * 创建用户
     * 
     * POST /user
     */
    @PostMapping
    public String create(@ModelAttribute User user) {
        userService.save(user);
        
        // 重定向
        return "redirect:/user/list";
    }
    
    /**
     * 更新用户
     * 
     * PUT /user/123
     */
    @PutMapping("/{id}")
    @ResponseBody
    public Result update(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        userService.update(user);
        return Result.success();
    }
    
    /**
     * 删除用户
     * 
     * DELETE /user/123
     */
    @DeleteMapping("/{id}")
    @ResponseBody
    public Result delete(@PathVariable Long id) {
        userService.deleteById(id);
        return Result.success();
    }
}

拦截器

/**
 * 自定义拦截器
 */
public class LoginInterceptor implements HandlerInterceptor {
    
    /**
     * 前置处理
     * 
     * Controller方法执行之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        
        System.out.println("===== preHandle =====");
        System.out.println("请求URI:" + request.getRequestURI());
        
        // 检查是否登录
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");
        
        if (user == null) {
            // 未登录,重定向到登录页
            response.sendRedirect("/login");
            return false;  // 不继续执行
        }
        
        return true;  // 继续执行
    }
    
    /**
     * 后置处理
     * 
     * Controller方法执行之后,视图渲染之前
     */
    @Override
    public void postHandle(HttpServletRequest request, 
                          HttpServletResponse response, 
                          Object handler,
                          ModelAndView modelAndView) throws Exception {
        
        System.out.println("===== postHandle =====");
        
        if (modelAndView != null) {
            // 添加公共数据
            modelAndView.addObject("currentTime", new Date());
        }
    }
    
    /**
     * 完成处理
     * 
     * 视图渲染之后
     */
    @Override
    public void afterCompletion(HttpServletRequest request, 
                               HttpServletResponse response, 
                               Object handler,
                               Exception ex) throws Exception {
        
        System.out.println("===== afterCompletion =====");
        
        if (ex != null) {
            System.out.println("异常:" + ex.getMessage());
        }
    }
}

/**
 * 注册拦截器
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
            .addPathPatterns("/**")              // 拦截所有请求
            .excludePathPatterns("/login", "/register");  // 排除登录和注册
    }
}

🎯 配置方式

Java配置(推荐)

/**
 * Spring MVC配置
 */
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    
    /**
     * 视图解析器
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }
    
    /**
     * 静态资源处理
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
            .addResourceLocations("/static/");
    }
    
    /**
     * 拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/login");
    }
    
    /**
     * 跨域配置
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("*")
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
    }
    
    /**
     * 消息转换器
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // Jackson
        MappingJackson2HttpMessageConverter converter = 
            new MappingJackson2HttpMessageConverter();
        
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
    }
}

🎉 总结

核心流程

1. DispatcherServlet接收请求
2. HandlerMapping查找Handler
3. HandlerAdapter执行Handler
4. Handler处理业务逻辑
5. 返回ModelAndView
6. ViewResolver解析视图
7. View渲染页面
8. 返回响应

记忆口诀

Spring MVC请求处理,
九步流程要记牢。

Dispatcher前端控制器,
所有请求入口处。
HandlerMapping来映射,
URL找到Handler。

HandlerAdapter适配器,
执行Handler处理器。
前置拦截preHandle,
可以决定是否执行。

Handler处理业务逻辑,
返回ModelAndView对象。
后置拦截postHandle,
视图渲染之前执行。

ViewResolver解析视图,
视图名变成View对象。
View渲染生成页面,
HTML返回给浏览器。

afterCompletion最后执行,
清理资源记录日志。

三大组件要记牢:
HandlerMapping找Handler,
HandlerAdapter执行Handler,
ViewResolver解析视图。

一个中心记心上:
DispatcherServlet是核心!

愿你的MVC架构清晰优雅,请求处理流畅高效! 🌐✨