Spring mvc工作的顺序图

@startuml
interface HandlerInterceptor{
    + boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler);
    + void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView);
    + void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex);
}

interface HandlerMapping{}

class HandlerExecutionChain{
    - Object handler;
    - final List<HandlerInterceptor> interceptorList;
    - int interceptorIndex

    + HandlerExecutionChain(Object handler, List<HandlerInterceptor> interceptorList)

    ~ boolean applyPreHandler(HttpservletRequestt,HttpServletResponse response);
    ~ boolean applyPostHandle(HttpservletRequestt,HttpServletResponse response);
    ~ boolean triggerAfterCompletion(HttpservletRequestt,HttpServletResponse response);
}

interface HandlerAdapter{
    ~ ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);
}

interface WebMvcConfigurer {
    
    + void addInterceptors(InterceptorRegistry registry);
    
}
@enduml

1 HandlerInterceptor

springf-webmvc-5.3.9.jar org.springframework.web.servlet

工作流接口,它允许定制化的handler执行链。应用可以注册任何数量的已经存在的或定制的拦截器给特定组的handlers,目的是在不必修改handler实现的情况下来增加前处理行为。

?handler指的是什么?————指方法吗?

一个handler拦截器会在合适的HandlerAdapter触发handler执行之前被调用。这个机制可以被用在很多前处理方面。例如权限校验,或通用行为语言或主题的变换。他的主要目的就是提取重复的hanler代码。

在异步处理的场景,hanlder也许会被执行在一个分离的线程,与此同时,主线程没有渲染或执行postHandleafterCompletion 回调函数。当并行的handler 执行完成,请求会被分配回来,为了执行渲染模型,并且这个contract的所有方法会被再触发一遍。异步的请看AsyncHandlerInterceptor

典型的情况就是 每个HandlerMapping Bean 都会定义一个拦截器链。为了能够应用一个特定的拦截器链给一组特定的Handler,我们需要给一个HandlerMapping bean 匹配想要的handler。拦截器被定义成bean保存在上下文中,通过interceptors变量来被匹配的bean引用。

HandlerInterceptorServlet Filter基本相似。但是相较于后者,HandlerInterceptor他有一个前处理的选项:禁止执行Hander本身及其后续的定制化后处理。Filters更强力,例如他们允许调换链上的请求和响应。需要强调的是Filter在web.xml中配置。拦截器在上下文中配置。

作为一个基本的指导,细粒度的handler相关的任务最好交给HanlerInterceptor实现,特别是分离handler通用代码的功能或校验权限。另一方面,Filter适合request和view内容的处理,例如multipartforms 和 GZIP的压缩。当一个人需要匹配filter给特定content(e.g. 图片) 或匹配给所有request时。

2 HandlerMapping

给定义了请求和处理器之间的映射关系的对象来实现的接口

HanlerMapping 的实现可以支持被匹配好的拦截器,但不是必须的。一个Handler总是被HandlerExecutionChain实例包装起来,可选的选项还有HandlerInterceptor实例。DispatcherServlet会先调用HandlerInterceptor的preHandler方法,最终调用hanler自己的方法,如果所有的preHandle都返回true.

将映射参数化的能力是MVC framework 的强力的不同寻常的能力。例如,它能够基于session 状态,cookie状态或其他变量 来写出一个定制化的mapping.其他框架没有这么灵活。

3 HandlerExecutionChain

Handler execution chain ,包含了handler,handler拦截器

4 HandlerAdapter

  MVC 框架的SPI,允许将核心的MVC工作流参数化

SPI SPI是一种回调的思想,回调是指我们在使用api时,我们可以向api传入一个类或者方法,api在合适的时间调用类或者方法。SPI是在一些通用的标准中,为标准的实现产商提供的扩展点。标准在上层提供API,API内部使用了SPI,当API被客户使用时,会动态得从当前运行的classpath中寻找该SPI的实现,然后使用该SPI的实现来完成API的功能。

  处理请求的每种类型的handler一定要实现的接口。这个接口是用来让DispathcerServlet能够无限扩展。DispatcherServlet访问所有的Handler通过这个接口,意味着他不包含特定handler类型的代码。

  值得注意的是,handler的类型是Object.目的是能够让其他框架的handler整合进框架二不用特定编码,也让注解驱动的handler对象不用遵从特定的Java接口。

  这个接口的目的不是给应用开发者用的。给框架扩展者使用的。

5 DispatcherServlet

  http 请求的中央调度器,比如 给web ui的controllers或基于http的远程服务的暴露接口。调度给已注册的handlers来处理网页请求,提供便利的匹配和异常处理。

  这个servlet非常灵活,配合合适的适配器,它能够被任何workflow使用。它提供以下的功能,这些功能将dispatcherservlet 与其他请求驱动的webMVC框架区分开:

  • 基于javaBean配置机制
  • 它可以使用任何HandlerMapping的实现,来控制requests到某个handler的路由。默认的实现是org.springframework.web.servlet.handler.BeanNameUrlHandlerMappingorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.
  • 他可以使用任何HandlerAdapter。借此它能够使用任何的handler接口。默认的适配器是org.springframework.web.servlet.mvc.HttpRequestHandlerAdapterorg.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter 这两个适配器适配的是 org.springframework.web.HttpRequestHandlerorg.springframework.web.servlet.mvc.Controller的接口。默认的org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter 也会被注册。handlerAdapter作为一个bean,会被注册在应用上下文中
  • 异常处理是通过HandlerExceptionResolver,例如将特定异常map到特殊的页面。默认的是org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolverorg.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolverorg.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
  • View 处理,multipart请求处理,locale处理和theme 处理略

6 WebMvcConfigurer

  定义回调方法来定制化java-based 配置Spring MVC 。被@EnableWebMvc注解的配置类可以实现这个接口来被回调并且得到定制化配置的机会。

7 DispacherServlet顺序图

@startuml
Client->DispatcherServlet++:doService
note right
暴露了DispatcherServlet特有的属性,并且将任务分给`doDispatch`方法来做实际的分配任务.
end note
    DispatcherServlet->DispatcherServlet++:doDispatch()
    note right
    通过按顺序调用Servlet的HanderMapping,能够获得handler.通过Servlet中的HanderAdaptor List 中支持handler的class类型的adapter,来获取对应的handlerAdaptor.
    所有http 方法由改函数处理。由handlerAdapters或handlers 来决定哪个方法是可接受的。
    end note
        DispatcherServlet->DispatcherServlet++:getHandler()
            loop 遍历DispatcherServlet中的HandlerMapping list
                note right
                返回这个请求的处理程序和任何拦截程序。可以根据请求的URL、会话状态或实现类选择的任何因素进行选择。
                返回的HandlerExecutionChain包含一个处理程序对象,甚至不是一个标签接口,所以处理程序不会受到任何限制。例如,可以写一个HandlerAdapter来允许使用另一个框架的处理程序对象。
                end note
                DispatcherServlet->HandlerMapping++:getHandler()
                return HandlerExecutionChain
            end
        return HandlerExecutionChain

        DispatcherServlet->DispatcherServlet++:getHandlerAdapter()
            loop 遍历DispatcherServlet中的HandlerAdapter list
                note right
                返回handler对应的HandlerAdapter
                end note
                DispatcherServlet->HandlerAdapter++:support()
                return boolean
            end
        return HandlerAdapter
        
        DispatcherServlet->HandlerExecutionChain++:applyPreHandle()
        note right
        应用所有的拦截器的preHandle()方法
        end note
            loop 遍历HandlerExecutionChain中的HandlerInterceptor
                HandlerExecutionChain->HandlerInterceptor++:preHandle()
                return
            end
        return

        DispatcherServlet-> HandlerAdapter++:handle()
        note right
        处理请求
        end note
        
        return
        note right
        一般请求里面将hanlder->HandlerMethod->ServletInvocableHandlerMethod#invokeAndHandle();
        里面还有参数绑定之类的
        end note

        DispatcherServlet->HandlerExecutionChain++:applyPostHandle()
        note right
        应用所有的拦截器的postHandle()方法
        end note
            loop 遍历HandlerExecutionChain中的HandlerInterceptor
                HandlerExecutionChain->HandlerInterceptor++:postHandle()
                return
            end
        return

        DispatcherServlet->DispatcherServlet++:processDispatchResult()
        note right
        处理异常或ModelAndView
        end note
        return

        DispatcherServlet->HandlerExecutionChain++:triggerAfterCompletion()
        note right
        应用所有的拦截器的afterCompletion()方法
        end note
            loop 遍历HandlerExecutionChain中的HandlerInterceptor
                HandlerExecutionChain->HandlerInterceptor++:afterCompletion()
                return
            end
        return
    return
return


 @enduml
  • 请求命中的HanderMappingRequestMappingHandlerMapping,返回的HandlerExecutionChain 中的Handler是Controller#method(),还有三个拦截器ResourceUrlProviderExposingInterceptor,ConversionServiceExposingInterceptorLongTaskTimingHandlerInterceptor

  • 根据Handler查找Adapter 命中的是RequestMappingHandlerAdapter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值