Loading

当调用一个controller时,spring做了哪些工作?

Spring 和 Tomcat 处理请求的源码分析涉及多个层次,包括 Tomcat 的请求接收和分发、Spring 的 DispatcherServlet 处理流程等。以下是详细的源码级别解析:


1. Tomcat 接收和分发请求

1.1 Tomcat 的 Connector 和 Processor

  • Tomcat 的 Connector 监听指定的端口(例如 8080)并接收 HTTP 请求。核心类是:
    • org.apache.coyote.http11.Http11Processor
    • 它通过 process 方法解析 HTTP 请求,将其转化为 Request 对象。

1.2 Servlet 容器调用

  • Tomcat 的 StandardWrapperValve 将请求交给注册的 Servlet
    • 代码路径:
      public final void invoke(Request request, Response response) {
          // 找到对应的 Servlet 并调用其 service 方法
          servlet.service(request, response);
      }
      
  • 如果是 Spring Boot 项目,DispatcherServlet 会被注册为主处理 Servlet。

2. DispatcherServlet 的处理流程

2.1 DispatcherServlet 的核心逻辑

DispatcherServlet 是一个扩展自 HttpServlet 的类,其核心方法是 doDispatch。代码路径:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HandlerExecutionChain mappedHandler = null;

    try {
        // 1. 根据请求查找对应的处理器(控制器)
        mappedHandler = getHandler(request);

        if (mappedHandler == null) {
            noHandlerFound(request, response);
            return;
        }

        // 2. 获取适配器(HandlerAdapter)调用控制器
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

        // 3. 执行前置拦截器
        if (!mappedHandler.applyPreHandle(request, response)) {
            return;
        }

        // 4. 调用控制器的方法并获取返回值
        ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());

        // 5. 渲染视图或直接返回数据
        processDispatchResult(request, response, mappedHandler, mv);
    } finally {
        // 6. 执行后置拦截器
        if (mappedHandler != null) {
            mappedHandler.triggerAfterCompletion(request, response, null);
        }
    }
}

3. 核心组件源码解析

3.1 HandlerMapping

HandlerMapping 用于根据请求路径找到对应的处理器(控制器)。示例:

  • 默认实现是 RequestMappingHandlerMapping,其核心方法:
    public HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        return lookupHandlerMethod(lookupPath, request);
    }
    

3.2 HandlerAdapter

HandlerAdapter 用于调用控制器。常用实现是 RequestMappingHandlerAdapter,其核心方法:

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    HandlerMethod handlerMethod = (HandlerMethod) handler;

    // 1. 解析方法参数
    Object[] args = getMethodArgumentValues(request, response, handlerMethod);

    // 2. 调用控制器方法
    Object returnValue = invokeHandlerMethod(handlerMethod, args);

    // 3. 处理返回值
    return getModelAndView(returnValue, handlerMethod);
}

3.3 HttpMessageConverter

  • 如果控制器返回的是数据(如 JSON),Spring 使用 HttpMessageConverter 序列化为响应体。
  • 核心方法:
    public void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException {
        ObjectMapper mapper = ...; // 使用 Jackson 处理 JSON
        mapper.writeValue(outputMessage.getBody(), t);
    }
    

3.4 ViewResolver

  • 如果控制器返回视图名称,Spring 使用 ViewResolver 查找具体的视图实现。
  • 核心方法:
    @Nullable
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        return this.viewResolvers.get(viewName);
    }
    

4. 流程总结

  1. Tomcat 接收请求
    • 通过 Http11Processor 解析请求并调用 Spring 的 DispatcherServlet
  2. DispatcherServlet 分发请求
    • 使用 HandlerMapping 查找控制器。
    • 使用 HandlerAdapter 调用控制器方法。
  3. 控制器处理逻辑
    • Spring 解析参数,调用业务逻辑,并返回结果。
  4. 处理返回值
    • 数据返回:通过 HttpMessageConverter 序列化为 JSON。
    • 视图返回:通过 ViewResolver 渲染页面。
  5. Tomcat 返回响应
    • HttpServletResponse 的内容被写入,并通过网络发送给客户端。

关键源码位置

  1. Tomcat

    • org.apache.coyote.http11.Http11Processor
    • org.apache.catalina.core.StandardWrapperValve
  2. Spring

    • org.springframework.web.servlet.DispatcherServlet
    • org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
    • org.springframework.web.servlet.view.ViewResolver
    • org.springframework.http.converter.HttpMessageConverter

通过上述源码分析,Spring 和 Tomcat 协同完成了请求接收、分发、处理、到响应的完整流程。

posted @ 2025-01-05 20:39  天山琴子  阅读(29)  评论(0)    收藏  举报