论坛首页 Java企业应用论坛

SPRING MVC的实现机制

浏览 6196 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (2)
作者 正文
   发表时间:2011-12-20   最后修改:2011-12-21



 

  SPRING MVC 的相关概念:

 

DispatcherServlet:前端控制器,也是整个架构的核心,负责处理和分发请求。

  1. HandlerMapping:处理器映射,他主要包含的是控制器的列表,对于特定的请求,根据HandlerMapping的映射关系,可以找到特定的控制器。最简单的便是url到控制器的映射。
  2. HandlerAdapter:对于不同类型的控制器,该类负责把Handler请求处理的结果统一转换成ModelAndView。
  3. ModelAndView:包含数据和视图的信息,一般包含视图名,和这个视图需要用的数据,这里的Model大家不要误会为模型的概念,它只不过同时包含视图信息及这个视图需要显示的相关信息而已。
  4. ViewResolver:它View名称解析成View对象。
  5. View:定义response显示的详细内容。

在配置文件中我们看到了ViewResolver,HandlerAdapter,HandlerMapping的配置信息,

 

 

  

 

如果不看源码会有如下疑问:这些元素之间的调用关系为啥没在配置文件中体现出来;

 

 

我们看看DispatcherServlet的源码:

 

 

 

 

 

 

 这段代码对应的活动图如下:(一共包含四个活动)

 

 

 

 

 

现在来具体看看这四个方法的具体实现:

1. getHandler 其实就是取 Controller的实现类,(对应的是STRUTS中的*Action);

这里的handlerMappings 就是我们在SPRING 配置文件中配置的 handlerMapping实现类的集合;

这个方法中采用循环的方式去解析客户的URL请求;

    protected Object getHandler(HttpServletRequest request) throws Exception {  

  1.         Iterator<HandlerMapping> it = this.handlerMappings.iterator();  
  2.         while (it.hasNext()) {  
  3.             HandlerMapping hm = it.next();  
  4.             if (LOGGER.isDebugEnabled()) {  
  5.                 LOGGER.debug("Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName()  
  6.                         + "'");  
  7.             }  
  8.             return hm.getHandler(request);  
  9.         }  
  10.         return null;  
  11.     }  

2.getHandlerAdapter 方法类似的;handlerAdapters是配置在spring 配置文件中的handlerAdapter实现类的集合;也是一样的采用循环的方式去判断 handlerAdapter的实现类是否可以处理Controller的实现类,如何可以处理就返回该handlerAdapter的实现类;

 

 protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {  

  1.         Iterator<HandlerAdapter> it = this.handlerAdapters.iterator();  
  2.         while (it.hasNext()) {  
  3.             HandlerAdapter ha = it.next();  
  4.             if (LOGGER.isDebugEnabled()) {  
  5.                 LOGGER.debug("Testing handler adapter [" + ha + "]");  
  6.             }  
  7.             if (ha.supports(handler)) {  
  8.                 return ha;  
  9.             }  
  10.         }  
  11.         throw new ServletException("No adapter for handler [" + handler  
  12.                 + "]: Does your handler implement a supported interface like Controller?");  
  13.     }  

 3.ModelAndView mv = ha.handle(request, response, handler);  

这一步由HandlerAdapter 的实现类 来执行handle(request, response, handler)方法;

我们来看一个具体的HandlerAdapter 的实现类HttpRequestHandlerAdapter ,他的handle方法:

 

注意到这个 handler的数据类型是Object ,通常写代码时我们都是继承Controller; 那么这个方法其实是调用Controller的实现类来处理request, response;

 

总结:第一个函数handlerMapping解析URL请求,指向具体的Controller实现类

 

第2,3函数,SPRING 调用具体的Controller实现类来执行用户请求;

 

为啥会有第二步? 因为不同的Controller实现类差异很大,这个时候SPRING框架采用Adapter适配器的模式,来屏蔽Controller实现类的差异;如何做的?

 

1.首先判断适配器是否可以处理该Controller 见supports(Object handler)

 

2.然后执行handle(HttpServletRequest  , HttpServletResponse  , Object  )

在该方法中进行强制类型转化成Controller实现类,然后执行该Controller实现类的handleRequest;

 

(为啥会有supports(Object handler)方法? 因为在第2步中会进行强制类型转化,如果没有第一步的判断,第二步就会报错!!)

 

 

 @Override  

  1.     public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)  
  2.             throws Exception {  
  3.         ((HttpRequestHandler) handler).handleRequest(request, response);  
  4.         return null;  
  5.     }  

 

  1. package com.google.mvc.web.servlet.mvc;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import com.google.mvc.web.servlet.HandlerAdapter;  
  7. import com.google.mvc.web.servlet.ModelAndView;  
  8.   
  9. public class HttpRequestHandlerAdapter implements HandlerAdapter {  
  10.   
  11.     @Override  
  12.     public long getLastModified(HttpServletRequest request, Object handler) {         
  13.         return 0;  
  14.     }  
  15.   
  16.     @Override  
  17.     public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)  
  18.             throws Exception {  
  19.         ((HttpRequestHandler) handler).handleRequest(request, response);  
  20.         return null;  
  21.     }  
  22.   
  23.     @Override  
  24.     public boolean supports(Object handler) {         
  25.         return (handler instanceof HttpRequestHandler);  
  26.     }  
  27. }  

 

 4 . 第四步render(ModelAndView  , HttpServletRequest  , HttpServletResponse  ) 

又是循环查找ViewResolver  的实现类来处理

  1.  protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.         View view = null;  
  3.         if (mv.isReference()) {  
  4.             // We need to resolve the view name.  
  5.             view = resolveViewName(mv.getViewName(), mv.getModelInternal(), request);  
  6.             if (view == null) {  
  7.                 throw new ServletException("Could not resolve view with name '" + mv.getViewName()  
  8.                         + "' in servlet with name '" + getServletName() + "'");  
  9.             }  
  10.         } else {  
  11.             // No need to lookup: the ModelAndView object contains the actual  
  12.             // View object.  
  13.             view = mv.getView();  
  14.             if (view == null) {  
  15.                 throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a "  
  16.                         + "View object in servlet with name '" + getServletName() + "'");  
  17.             }  
  18.         }  
  19.         // Delegate to the View object for rendering.  
  20.         if (LOGGER.isDebugEnabled()) {  
  21.             LOGGER.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");  
  22.         }  
  23.         view.render(mv.getModelInternal(), request, response);  
  24.     }  
  25.   
  26.     protected View resolveViewName(String viewName, Map<String, Object> model, HttpServletRequest request)  
  27.             throws Exception {  
  28.         for (Iterator<ViewResolver> it = this.viewResolvers.iterator(); it.hasNext();) {  
  29.             ViewResolver viewResolver = it.next();  
  30.             View view = viewResolver.resolveViewName(viewName);  
  31.             if (view != null) {  
  32.                 return view;  
  33.             }  
  34.         }  
  35.         return null;  
  36.     }  

 分析了这4个步骤后,我们会发现除了第3步,其他几步都是循环查找合适的ViewResolver,HandlerAdapter,HandlerMapping的实现类 ;而第三步其实是调用Controller实现类来处理请求;

 

 

讲的比较粗略。ViewResolver,HandlerAdapter,HandlerMapping的实现类可以直接翻看源码!

 

 

 

 

 

 

 

  • 大小: 43.7 KB
  • 大小: 49.8 KB
  • 大小: 84.8 KB
   发表时间:2011-12-21   最后修改:2011-12-21
发贴要有点含量,还有点让大家探讨的欲望,不然真水了
按照这个逻辑,一天发10个实现机制都可以 

0 请登录后投票
   发表时间:2011-12-21  
昨天网络不行,今天补充。呵呵
0 请登录后投票
   发表时间:2011-12-24  
直接上源代码
0 请登录后投票
   发表时间:2011-12-24  
DispatcherServlet 直接看JAR包中的这个类;贴源代码,要贴几页。看着烦
0 请登录后投票
   发表时间:2012-03-08  
感觉还不错啊,条理挺清晰的
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics