SpringMVC_执行流程

Spring MVC框架简介

Spring MVC是什么呢,它是属于Spring FrameWork的后续产品,已经融合在Spring Web Flow里面。 Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。可以简单的把springMVC理解为是spring的一个模块(类似AOP,IOC这样的模块),网络上经常会说springMVC和spring无缝集成,其实springMVC就是spring的一个子模块,所以根本不需要同spring进行整合。

Spring MVC框架提供了构建web应用程序的全功能MVC模块,使用了Spring可插入架构,可以选择是使用内置的Spring web框架还是struts这样的web框架,通过接口,Spring 框架是高度可配置的,而且包含多种视图技术。Spring MVC 框架并不知道使用视图,Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

Spring MVC原理图

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。

SpringMVC运行原理

我们再来看看SpringMVC的流程:

  1. 用户发送请求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器一并返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter处理器适配器。
  5. HandlerAdapter经过适配调用具体的处理器。
  6. Controller执行完成返回ModelAndView。
  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体View。
  10. DispatcherServlet根据View进行渲染视图。
  11. DispatcherServlet响应用户,DispatcherServlet也是整个Spring MVC的核心,它负责接收HTTP请求组织协调Spring MVC的各个组成部分。

HandlerMapping

HandlerMapping(如:BeanNameUrlHandlerMapping)是请求映射处理器,也就是通过请求的url找到对应的逻辑处理单元(Controller),注意这里只是建立请求与Controller的映射关系,最终的处理是通过HandlerAdapter来进行处理的。

DispatcherServlet的初始化中会调用initStrategies()方法,实际上HandlerMapping的初始化是调用initStrategies()中的initHandlerMappings(context);

HandlerMapping的任务就是建立url与Bean(Controller)的对应关系,并将对应关系保存在handlerMap中;

对应关系在HandlerMapping初始化的时候就已经建立好了;

当请求到来时,会通过DispatcherServlet找到HandlerMapping,然后通过请求的url在handlerMap中找到对应的Controller,至此HandlerMapping的任务完成了,下一步就是HandlerAdapter出场了。

HandlerAdapter

HandlerMapping在初始化时就将@RequestMapping对应的url与Controller建立了对应关系,前端的Http请求通过对应关系找到Controller,这就是HandlerMapping的使命,接下来就是HandlerAdapter来进行处理了。在HandlerMapping中有讲到DispatcherServlet的初始化中会调用initStrategies()方法,这里面也包含了HanderAdapter的初始化initHandlerAdapters(context);

同HandlerMapping初始化一样,默认的HanderAdapter实现也是配置在DispatcherServlet.properties文件中。

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

从配置可以看出,HandlerAdapter默认有三种类型的实现,分别是:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter。

回到DispatcherServlet中来,看到请求处理的方法doDispatch()方法中有这么一段:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

这段就是通过HandlerMapping返回的Handler,来找到对应的Controller执行相应的逻辑,下面我们来具体看一下内部实现:

复制代码
//重点看一下AnnotationMethodHandlerAdapter的handler方法
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    //获取class对象
    Class<?> clazz = ClassUtils.getUserClass(handler);
    //检查class对象是否含有SessionAttributes注解
    Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
    if (annotatedWithSessionAttributes == null) {
        annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
        this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
    }

    if (annotatedWithSessionAttributes) {
        checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
    }
    else {
        checkAndPrepare(request, response, true);
    }

    // Execute invokeHandlerMethod in synchronized block if required.
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                return invokeHandlerMethod(request, response, handler);
            }
        }
    }
    //重点是invoke方法来做的调用
    return invokeHandlerMethod(request, response, handler);
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    //我们知道handler就是从上一步HandlerMapping拿到的Controller,这里通过handler拿到HandlerMethodResolver
    //那HandlerMethodResolver到底是个什么鬼?它里面主要是存储Controller中方法上@RequestMapping的url以及所有的方法
    ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
    //通过methodResolver与当前的request进行匹配,通过请求的url找到需要调用的方法
    Method handlerMethod = methodResolver.resolveHandlerMethod(request);
    ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    ExtendedModelMap implicitModel = new BindingAwareModelMap();

    //重点看该方法调用,看下面具体源码
    Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
    ModelAndView mav =
            methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
    methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
    return mav;
}

public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
        NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {

    Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
    try {
        boolean debug = logger.isDebugEnabled();
        for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
            Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
            if (attrValue != null) {
                implicitModel.addAttribute(attrName, attrValue);
            }
        }
        for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
            Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
            Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
            if (debug) {
                logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
            }
            String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
            if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
                continue;
            }
            ReflectionUtils.makeAccessible(attributeMethodToInvoke);
            Object attrValue = attributeMethodToInvoke.invoke(handler, args);
            if ("".equals(attrName)) {
                Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
                attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
            }
            if (!implicitModel.containsAttribute(attrName)) {
                implicitModel.addAttribute(attrName, attrValue);
            }
        }
        //这里即将调用方法的参数,对参数进行处理
        Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
        if (debug) {
            logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
        }
        ReflectionUtils.makeAccessible(handlerMethodToInvoke);
        //将参数传入,利用反射来进行方法调用
        return handlerMethodToInvoke.invoke(handler, args);
    }
    catch (IllegalStateException ex) {
        // Internal assertion failed (e.g. invalid signature):
        // throw exception with full handler method context...
        throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
    }
    catch (InvocationTargetException ex) {
        // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
        ReflectionUtils.rethrowException(ex.getTargetException());
        return null;
    }
}
复制代码

进行到这里已经调用完了方法,再回到上一步看看返回值的情况:

复制代码
//根据handler处理的结果,封装一个ModelAndView给前端
public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
        ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {

    ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class);
    if (responseStatus != null) {
        HttpStatus statusCode = responseStatus.code();
        String reason = responseStatus.reason();
        if (!StringUtils.hasText(reason)) {
            webRequest.getResponse().setStatus(statusCode.value());
        }
        else {
            webRequest.getResponse().sendError(statusCode.value(), reason);
        }

        // to be picked up by the RedirectView
        webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, statusCode);

        this.responseArgumentUsed = true;
    }

    // Invoke custom resolvers if present...
    if (customModelAndViewResolvers != null) {
        for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
            ModelAndView mav = mavResolver.resolveModelAndView(
                    handlerMethod, handlerType, returnValue, implicitModel, webRequest);
            if (mav != ModelAndViewResolver.UNRESOLVED) {
                return mav;
            }
        }
    }
    //以下是判断返回值的各种类型,给出不同的处理
    if (returnValue instanceof HttpEntity) {
        handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest);
        return null;
    }
    //@ResponseBody注解的处理
    else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
        handleResponseBody(returnValue, webRequest);
        return null;
    }
    //看这里,就是我们很熟悉的ModelAndView的处理
    else if (returnValue instanceof ModelAndView) {
        ModelAndView mav = (ModelAndView) returnValue;
        mav.getModelMap().mergeAttributes(implicitModel);
        return mav;
    }
    //返回Model
    else if (returnValue instanceof Model) {
        return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
    }
    //返回View
    else if (returnValue instanceof View) {
        return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
    }
    //@ModelAttribute注解的处理
    else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
        addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
        return new ModelAndView().addAllObjects(implicitModel);
    }
    //返回Map
    else if (returnValue instanceof Map) {
        return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue);
    }
    //返回String
    else if (returnValue instanceof String) {
        return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
    }
    //返回null的处理
    else if (returnValue == null) {
        // Either returned null or was 'void' return.
        if (this.responseArgumentUsed || webRequest.isNotModified()) {
            return null;
        }
        else {
            // Assuming view name translation...
            return new ModelAndView().addAllObjects(implicitModel);
        }
    }
    else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
        // Assume a single model attribute...
        addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
        return new ModelAndView().addAllObjects(implicitModel);
    }
    else {
        throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
    }
}
复制代码

下面来看一下ModelAndView是个什么?

复制代码
//根据handler处理的结果,封装一个ModelAndView给前端
public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
        ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {

    ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class);
    if (responseStatus != null) {
        HttpStatus statusCode = responseStatus.code();
        String reason = responseStatus.reason();
        if (!StringUtils.hasText(reason)) {
            webRequest.getResponse().setStatus(statusCode.value());
        }
        else {
            webRequest.getResponse().sendError(statusCode.value(), reason);
        }

        // to be picked up by the RedirectView
        webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, statusCode);

        this.responseArgumentUsed = true;
    }

    // Invoke custom resolvers if present...
    if (customModelAndViewResolvers != null) {
        for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
            ModelAndView mav = mavResolver.resolveModelAndView(
                    handlerMethod, handlerType, returnValue, implicitModel, webRequest);
            if (mav != ModelAndViewResolver.UNRESOLVED) {
                return mav;
            }
        }
    }
    //以下是判断返回值的各种类型,给出不同的处理
    if (returnValue instanceof HttpEntity) {
        handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest);
        return null;
    }
    //@ResponseBody注解的处理
    else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
        handleResponseBody(returnValue, webRequest);
        return null;
    }
    //看这里,就是我们很熟悉的ModelAndView的处理
    else if (returnValue instanceof ModelAndView) {
        ModelAndView mav = (ModelAndView) returnValue;
        mav.getModelMap().mergeAttributes(implicitModel);
        return mav;
    }
    //返回Model
    else if (returnValue instanceof Model) {
        return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
    }
    //返回View
    else if (returnValue instanceof View) {
        return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
    }
    //@ModelAttribute注解的处理
    else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
        addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
        return new ModelAndView().addAllObjects(implicitModel);
    }
    //返回Map
    else if (returnValue instanceof Map) {
        return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue);
    }
    //返回String
    else if (returnValue instanceof String) {
        return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
    }
    //返回null的处理
    else if (returnValue == null) {
        // Either returned null or was 'void' return.
        if (this.responseArgumentUsed || webRequest.isNotModified()) {
            return null;
        }
        else {
            // Assuming view name translation...
            return new ModelAndView().addAllObjects(implicitModel);
        }
    }
    else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
        // Assume a single model attribute...
        addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
        return new ModelAndView().addAllObjects(implicitModel);
    }
    else {
        throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
    }
}
复制代码
  1. HanderAdapter从上一步HandlerMapping拿到Controller;
  2. 通过Controller,经过反射拿到Controller中@requestMapping上url与方法的对应关系,返回ServletHandlerMethodResolver;
  3. 通过request请中的url与ServletHandlerMethodResolver中的mappings匹配,可以找到需要调用的方法;
  4. 利用反射调用找到的方法,返回Object;
  5. 处理返回结果,根据不同的返回值类型(ModelAndView、String、Map、View等)进行处理后,封装成ModelAndView返回给前台。

 

posted @   残城碎梦  阅读(120)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示