SpringMVC

SpringMVC_第1张图片
图片.png

Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。

1. DispatcherServlet 接口

Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。

2. HandlerMapping接口

能够完成客户请求到Controller映射。

3. Controller接口

需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。
Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。
从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。

4. ViewResolver接口

Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。

运行过程

  1. 客户端请求提交到DispatcherServlet
  2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller。HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个 HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
  3. DispatcherServlet将请求提交到Controller
  4. Controller调用业务逻辑处理后,返回ModelAndView
  5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
  6. 视图负责将结果显示到客户端

DispatcherServlet是整个Spring MVC的核心。它负责接收HTTP请求组织协调Spring MVC的各个组成部分。其主要工作有以下三项:
1. 截获符合特定格式的URL请求。
2. 初始化DispatcherServlet上下文对应的WebApplicationContext,并将其与业务层、持久化层的WebApplicationContext建立关联。
3. 初始化Spring MVC的各个组成组件,并装配到DispatcherServlet中。

拦截器原理

HandlerInterceptor拦截器接口

package org.springframework.web.servlet; 
public interface HandlerInterceptor { 
    boolean preHandle( 
            HttpServletRequest request, HttpServletResponse response,  
            Object handler)  
            throws Exception; 
  
    void postHandle( 
            HttpServletRequest request, HttpServletResponse response,  
            Object handler, ModelAndView modelAndView)  
            throws Exception; 
   
    void afterCompletion( 
            HttpServletRequest request, HttpServletResponse response,  
            Object handler, Exception ex) 
            throws Exception; 
}

使用时 需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,spring也提供了一个HandlerInterceptorAdapter适配器(一种适配器设计模式的实现),允许我们只实现需要的回调方法。

  • preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);返回值:true表示继续流程(如调用下一个拦截器或处理器); false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
  • postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
  • afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。

拦截器处理机制

中断流程中,比如是HandlerInterceptor2中断的流程(preHandle返回false),此处仅调用它之前拦截器的preHandle返回true的afterCompletion方法。

DispatcherServlet内部是如何工作 (伪代码)

//doDispatch方法 
//1、处理器拦截器的预处理(正序执行) 
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); 
if (interceptors != null) { 
    for (int i = 0; i < interceptors.length; i++) { 
    HandlerInterceptor interceptor = interceptors[i]; 
        if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { 
            //1.1、失败时触发afterCompletion的调用 
            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 
            return; 
        } 
        interceptorIndex = i;//1.2、记录当前预处理成功的索引 
} 
} 
//2、处理器适配器调用我们的处理器 
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 
//当我们返回null或没有返回逻辑视图名时的默认视图名翻译(详解4.15.5 RequestToViewNameTranslator) 
if (mv != null && !mv.hasView()) { 
    mv.setViewName(getDefaultViewName(request)); 
} 
//3、处理器拦截器的后处理(逆序) 
if (interceptors != null) { 
for (int i = interceptors.length - 1; i >= 0; i--) { 
      HandlerInterceptor interceptor = interceptors[i]; 
      interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); 
} 
} 
//4、视图的渲染 
if (mv != null && !mv.wasCleared()) { 
render(mv, processedRequest, response); 
    if (errorView) { 
        WebUtils.clearErrorRequestAttributes(request); 
} 
//5、触发整个请求处理完毕回调方法afterCompletion 
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

//==============================
// triggerAfterCompletion方法 
private void triggerAfterCompletion(HandlerExecutionChain mappedHandler, int interceptorIndex, 
        HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception { 
    // 5、触发整个请求处理完毕回调方法afterCompletion (逆序从上面预处理成功的索引处的拦截器执行) 
    if (mappedHandler != null) { 
        HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); 
        if (interceptors != null) { 
            for (int i = interceptorIndex; i >= 0; i--) { 
                HandlerInterceptor interceptor = interceptors[i]; 
                try { 
                    interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex); 
                } 
                catch (Throwable ex2) { 
                    logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); 
                } 
            } 
        } 
    } 
}  

spring-mvc配置:


     
           
                    
                    
                     
                   
                    
                    

           
          
    

你可能感兴趣的:(SpringMVC)