位置: 文档库 > Java > 面试官:你说的SpringMVC的请求处理流程是网上抄的吧?

面试官:你说的SpringMVC的请求处理流程是网上抄的吧?

大张伟 上传于 2023-07-09 09:25

《面试官:你说的SpringMVC的请求处理流程是网上抄的吧?》

面试室内,空调发出轻微的嗡嗡声,李明坐在面试官对面,双手不自觉地攥紧了膝盖上的简历。他刚刚回答完一个关于SpringMVC请求处理流程的问题,但面试官王总监的眉头微微皱起,眼神中透露出几分怀疑。"你说的流程,听起来像网上教程的模板,能详细解释下每个环节的具体实现吗?"王总监的话像一盆冷水浇在李明心头。

### 一、从"背流程"到"懂原理"的转折

李明记得三天前,自己还在对着B站的教学视频机械地复述:"DispatcherServlet接收请求→HandlerMapping查找处理器→HandlerAdapter执行处理器→ViewResolver解析视图..."。这种"填空式"的学习让他误以为掌握了SpringMVC,直到此刻被当面质疑。

"其实...我对DispatcherServlet的初始化过程不太清楚。"李明擦了擦额头的汗,"比如它如何加载配置文件,如何注册处理器映射?"王总监的眼神缓和了些:"那你说说HandlerMapping的几种实现方式?"

### 二、SpringMVC核心组件深度解析

#### 1. DispatcherServlet:前端控制器的中枢

作为SpringMVC的入口,DispatcherServlet继承自HttpServlet,其初始化过程在web.xml中配置:


    dispatcher
    org.springframework.web.servlet.DispatcherServlet
    
        contextConfigLocation
        classpath:spring-mvc.xml
    
    1

在init()方法中,DispatcherServlet会初始化9个核心组件:

protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);  // 文件上传解析器
    initLocaleResolver(context);     // 区域解析器
    initThemeResolver(context);      // 主题解析器
    initHandlerMappings(context);    // 处理器映射器
    initHandlerAdapters(context);    // 处理器适配器
    initHandlerExceptionResolvers(context); // 异常解析器
    initRequestToViewNameTranslator(context); // 视图名称转换器
    initViewResolvers(context);      // 视图解析器
    initFlashMapManager(context);    // FlashMap管理器
}

#### 2. HandlerMapping:路由决策的核心

SpringMVC提供三种主要实现:

1)SimpleUrlHandlerMapping:基于URL路径映射


    
        
            userController
        
    

2)RequestMappingHandlerMapping:注解驱动映射(Spring3.1+)

@Controller
@RequestMapping("/api")
public class UserController {
    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id) {
        // ...
    }
}

3)BeanNameUrlHandlerMapping:基于bean名称映射

#### 3. HandlerAdapter:适配器模式典范

三种适配器对应不同处理器类型:

// 1. SimpleControllerHandlerAdapter 处理Controller接口实现
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    @Override
    public ModelAndView handle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) throws Exception {
        return ((Controller)handler).handleRequest(request, response);
    }
}

// 2. HttpRequestHandlerAdapter 处理HttpRequestHandler
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    @Override
    public void handle(HttpServletRequest request, 
                      HttpServletResponse response, 
                      Object handler) throws Exception {
        ((HttpRequestHandler)handler).handleRequest(request, response);
    }
}

// 3. RequestMappingHandlerAdapter 处理@RequestMapping注解方法(Spring3.1+)

### 三、请求处理全流程实战解析

以用户登录为例,完整流程如下:

1)请求到达:用户访问/login,DispatcherServlet通过HandlerMapping查找处理器

// 伪代码展示查找过程
HandlerExecutionChain chain = handlerMapping.getHandler(request);
// 可能返回:
// HandlerExecutionChain{
//     handler=LoginController@123,
//     interceptors=[SecurityInterceptor, LogInterceptor]
// }

2)参数绑定:HandlerAdapter调用参数解析器

// Spring自动完成以下转换:
// 请求参数:username=admin&password=123456
// → 方法参数:@RequestParam String username, @RequestParam String password
public String login(@RequestParam String username, 
                   @RequestParam String password, 
                   Model model) {
    // ...
}

3)数据验证:通过Validator接口或JSR-303注解

public class User {
    @NotBlank(message="用户名不能为空")
    private String username;
    
    @Size(min=6, max=20, message="密码长度6-20位")
    private String password;
    // getters/setters
}

4)业务处理:调用Service层

@Service
public class AuthService {
    @Autowired
    private UserRepository userRepository;
    
    public User authenticate(String username, String password) {
        return userRepository.findByUsernameAndPassword(username, password);
    }
}

5)视图解析:根据返回字符串查找视图

// spring-mvc.xml配置

    
    


// 控制器返回"login/success" → 解析为/WEB-INF/views/login/success.jsp

### 四、异常处理机制

SpringMVC提供三级异常处理:

1)控制器内部处理

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity handleUserNotFound(UserNotFoundException ex) {
    return ResponseEntity.status(404).body("用户不存在");
}

2)@ControllerAdvice全局处理

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception ex) {
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("message", ex.getMessage());
        return mav;
    }
}

3)SimpleMappingExceptionResolver配置处理


    
        
            error/mathError
        
    

### 五、面试官的终极追问

王总监敲了敲桌子:"如果让你设计一个简化版MVC框架,核心类怎么设计?"李明深吸一口气:"首先需要Dispatcher类处理请求分发,然后定义Handler接口处理业务逻辑,最后需要ViewResolver接口渲染视图..."

"那如何解决线程安全问题?"王总监继续追问。

"每个请求应该创建独立的处理器实例,或者使用ThreadLocal存储请求上下文。"李明想起之前看过的源码分析。

### 六、走出面试室后的思考

三天后,李明收到offer邮件。这次经历让他明白:技术面试不是背诵比赛,而是考察对原理的理解和解决问题的能力。他打开笔记本,新建了一个"SpringMVC源码解析"的项目,准备从DispatcherServlet的doDispatch方法开始,逐行分析请求处理流程

**关键词**:SpringMVC、请求处理流程、DispatcherServlet、HandlerMapping、HandlerAdapter、视图解析、异常处理、源码分析、面试技巧

**简介**:本文通过一场技术面试的对话形式,深入解析SpringMVC请求处理的核心机制。从DispatcherServlet的初始化过程到HandlerMapping的路由决策,从HandlerAdapter的适配器模式到视图解析的完整流程,结合代码示例和源码分析,揭示"背流程"与"懂原理"的本质区别。文章不仅讲解技术细节,更强调理解原理的重要性,为Java开发者提供面试准备和深入学习的参考。