`

MVC架构探究及其源码实现(4)-前端控制器

 
阅读更多

前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用Filter实现(Struts2采用这种方式),也可以使用Servlet来实现。这里我们就采用后一种方式来实现我们的MVC框架。

 ds

1.配置web.xml,使得我们的前端控制器可以拦截所有符合要求的用户请求,这里我们的前端控制器能处理所有以.do结尾的用户请求。 

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="ISO-8859-1"?>  
  2. <web-app xmlns="http://java.sun.com/xml/ns/javaee"  
  3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  5.    version="2.5">   
  6.   
  7.     <description>MVC Sample</description>  
  8.     <display-name>MVC</display-name>  
  9.       
  10.     <servlet>  
  11.       <servlet-name>DispatcherServlet</servlet-name>  
  12.       <servlet-class>com.google.mvc.web.servlet.DispatcherServlet</servlet-class>  
  13.     </servlet>     
  14.   
  15.     <servlet-mapping>  
  16.         <servlet-name>DispatcherServlet</servlet-name>  
  17.         <url-pattern>*.do</url-pattern>  
  18.     </servlet-mapping>  
  19. </web-app>  

  2.FrameworkServlet实现。
FrameworkServlet是DispatcherServlet的直接父类,继承自HttpServlet,主要用来初始话WebApplicationContext,把不同的Http请求操作委托给同一个方法去处理。

[java] view plaincopy
  1. package com.google.mvc.web.servlet;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.ServletException;  
  6. import javax.servlet.http.HttpServlet;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. import org.apache.log4j.Logger;  
  11. import com.google.mvc.web.context.WebApplicationContext;  
  12.   
  13. public abstract class FrameworkServlet extends HttpServlet {  
  14.   
  15.     private static final long serialVersionUID = 1L;  
  16.     private static final Logger LOGGER = Logger.getLogger(FrameworkServlet.class);  
  17.     private WebApplicationContext webApplicationContext;      
  18.       
  19.     @Override  
  20.     public void init() throws ServletException {  
  21.           
  22.         if (LOGGER.isDebugEnabled()) {  
  23.             LOGGER.debug("----------Initializing servlet '" + getServletName() + "'----------");  
  24.         }  
  25.   
  26.         this.webApplicationContext = initWebApplicationContext();  
  27.           
  28.         initServletBean();  
  29.   
  30.         if (LOGGER.isDebugEnabled()) {  
  31.             LOGGER.debug("----------Servlet '" + getServletName() + "' configured successfully----------/n/n");  
  32.         }  
  33.   
  34.     }     
  35.       
  36.     private WebApplicationContext initWebApplicationContext() {       
  37.         WebApplicationContext wac = new WebApplicationContext(getServletContext());  
  38.         wac.init();   
  39.         onRefresh(wac);  
  40.         return wac;       
  41.     }  
  42.   
  43.     protected void onRefresh(WebApplicationContext context) {  
  44.         // For subclasses: do nothing by default.  
  45.     }  
  46.       
  47.     protected void initServletBean(){  
  48.           
  49.     }  
  50.       
  51.     protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception;  
  52.       
  53.   
  54.     protected final void processRequest(HttpServletRequest request, HttpServletResponse response)  
  55.             throws ServletException, IOException {  
  56.   
  57.         long startTime = System.currentTimeMillis();  
  58.         Throwable failureCause = null;  
  59.   
  60.         try {  
  61.             doService(request, response);  
  62.         } catch (ServletException ex) {  
  63.             failureCause = ex;  
  64.             throw ex;  
  65.         } catch (IOException ex) {  
  66.             failureCause = ex;  
  67.             throw ex;  
  68.         } catch (Throwable ex) {  
  69.             failureCause = ex;  
  70.             throw new NestedServletException("Request processing failed", ex);  
  71.         } finally {  
  72.             if (failureCause != null) {  
  73.                 LOGGER.error("Could not complete request", failureCause);  
  74.             } else {  
  75.                 long processingTime = System.currentTimeMillis() - startTime;  
  76.                 if (LOGGER.isDebugEnabled()) {  
  77.                     LOGGER.info("Successfully completed request, cost " + processingTime + " ms/n");  
  78.                 }  
  79.             }  
  80.         }  
  81.     }  
  82.   
  83.     @Override  
  84.     protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  85.             IOException {  
  86.         processRequest(request, response);  
  87.     }  
  88.   
  89.     @Override  
  90.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  91.         processRequest(request, response);  
  92.     }  
  93.   
  94.     @Override  
  95.     protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  96.             IOException {  
  97.         processRequest(request, response);  
  98.     }  
  99.   
  100.     @Override  
  101.     protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  102.             IOException {  
  103.         processRequest(request, response);  
  104.     }  
  105.   
  106.     @Override  
  107.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  108.             IOException {  
  109.         processRequest(request, response);  
  110.     }  
  111.   
  112.     @Override  
  113.     protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  114.         processRequest(request, response);  
  115.     }  
  116.   
  117.     @Override  
  118.     protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  119.             IOException {  
  120.         processRequest(request, response);  
  121.     }  
  122.   
  123.     @Override  
  124.     public void destroy() {  
  125.         if(LOGGER.isDebugEnabled()){  
  126.             LOGGER.info("Servlet destory");  
  127.         }  
  128.         super.destroy();  
  129.     }  
  130.   
  131.     public WebApplicationContext getWebApplicationContext() {  
  132.         return webApplicationContext;  
  133.     }  
  134.       
  135.       
  136.   
  137. }  

  3.DispatcherServlet实现。

[java] view plaincopy
  1. package com.google.mvc.web.servlet;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.ArrayList;  
  5. import java.util.Collections;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9. import java.util.Properties;  
  10. import java.util.StringTokenizer;  
  11.   
  12. import javax.servlet.ServletException;  
  13. import javax.servlet.http.HttpServletRequest;  
  14. import javax.servlet.http.HttpServletResponse;  
  15.   
  16. import org.apache.log4j.Logger;  
  17. import com.google.mvc.web.context.WebApplicationContext;  
  18.   
  19. public class DispatcherServlet extends FrameworkServlet {  
  20.   
  21.     private static final long serialVersionUID = 1L;  
  22.     private static final Logger LOGGER = Logger.getLogger(DispatcherServlet.class);  
  23.     private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";  
  24.     private static final Properties defaultStrategies = new Properties();  
  25.   
  26.     private List<HandlerMapping> handlerMappings;  
  27.     private List<HandlerAdapter> handlerAdapters;  
  28.     private List<ViewResolver> viewResolvers;  
  29.   
  30.     static {  
  31.         try {  
  32.             defaultStrategies.load(DispatcherServlet.class.getResourceAsStream(DEFAULT_STRATEGIES_PATH));  
  33.         } catch (IOException ex) {  
  34.             throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());  
  35.         }  
  36.     }  
  37.   
  38.     @Override  
  39.     protected void onRefresh(WebApplicationContext wac) {  
  40.         initHandlerMappings(wac);  
  41.         initHandlerAdapters(wac);  
  42.         initViewResolvers(wac);  
  43.     }  
  44.   
  45.     private void initHandlerMappings(WebApplicationContext wac) {  
  46.         Map<String, HandlerMapping> map = wac.beansOfType(HandlerMapping.class);  
  47.         if (!map.isEmpty()) {  
  48.             this.handlerMappings = new ArrayList<HandlerMapping>(map.values());  
  49.         }  
  50.         if (this.handlerMappings == null) {  
  51.             if (LOGGER.isDebugEnabled()) {  
  52.                 LOGGER.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");  
  53.             }  
  54.             this.handlerMappings = getDefaultStrategies(wac, HandlerMapping.class);  
  55.         }  
  56.     }  
  57.   
  58.     private void initHandlerAdapters(WebApplicationContext wac) {  
  59.         Map<String, HandlerAdapter> map = wac.beansOfType(HandlerAdapter.class);  
  60.         if (!map.isEmpty()) {  
  61.             this.handlerAdapters = new ArrayList<HandlerAdapter>(map.values());  
  62.         }  
  63.         if (this.handlerAdapters == null) {  
  64.             if (LOGGER.isDebugEnabled()) {  
  65.                 LOGGER.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");  
  66.             }  
  67.             this.handlerAdapters = getDefaultStrategies(wac, HandlerAdapter.class);  
  68.         }  
  69.     }  
  70.   
  71.     private void initViewResolvers(WebApplicationContext wac) {  
  72.         Map<String, ViewResolver> map = wac.beansOfType(ViewResolver.class);  
  73.         if (!map.isEmpty()) {  
  74.             this.viewResolvers = new ArrayList<ViewResolver>(map.values());  
  75.         }  
  76.         if (this.viewResolvers == null) {  
  77.             if (LOGGER.isDebugEnabled()) {  
  78.                 LOGGER.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");  
  79.             }  
  80.             this.viewResolvers = getDefaultStrategies(wac, ViewResolver.class);  
  81.         }  
  82.     }  
  83.   
  84.     @Override  
  85.     protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  86.   
  87.         if (LOGGER.isDebugEnabled()) {  
  88.             LOGGER.debug("DispatcherServlet with name '" + getServletName() + "' received request for ["  
  89.                     + request.getRequestURI() + "]");  
  90.         }  
  91.         doDispatch(request, response);  
  92.     }  
  93.   
  94.     protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  95.         if (LOGGER.isDebugEnabled()) {  
  96.             LOGGER.debug("Bound request context to thread: " + request);  
  97.         }  
  98.   
  99.         Object handler = getHandler(request);  
  100.         HandlerAdapter ha = getHandlerAdapter(handler);  
  101.         ModelAndView mv = ha.handle(request, response, handler);  
  102.   
  103.         // Do we need view name translation?  
  104.         if (mv != null && !mv.hasView()) {  
  105.             mv.setViewName(getDefaultViewName(request));  
  106.         }  
  107.   
  108.         // Did the handler return a view to render?  
  109.         if (mv != null && !mv.wasCleared()) {  
  110.             render(mv, request, response);  
  111.         }  
  112.     }  
  113.   
  114.     protected <T> List<T> getDefaultStrategies(WebApplicationContext wac, Class<T> strategyInterface) {  
  115.         String key = strategyInterface.getName();  
  116.         List<T> strategies = new ArrayList<T>();  
  117.         String value = defaultStrategies.getProperty(key);  
  118.         if (value != null) {  
  119.             StringTokenizer token = new StringTokenizer(value, ",");  
  120.             while (token.hasMoreTokens()) {  
  121.                 String className = token.nextToken();  
  122.                 try {  
  123.                     Class<?> clazz = this.getClass().getClassLoader().loadClass(className);  
  124.                     strategies.add((T) wac.createBean(clazz));  
  125.                 } catch (Exception e) {  
  126.                     LOGGER.error("Can't load class " + className + "", e);  
  127.                 }  
  128.             }  
  129.         } else {  
  130.             strategies = Collections.emptyList();  
  131.         }  
  132.         return strategies;  
  133.     }  
  134.   
  135.     protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {  
  136.         View view = null;  
  137.         if (mv.isReference()) {  
  138.             // We need to resolve the view name.  
  139.             view = resolveViewName(mv.getViewName(), mv.getModelInternal(), request);  
  140.             if (view == null) {  
  141.                 throw new ServletException("Could not resolve view with name '" + mv.getViewName()  
  142.                         + "' in servlet with name '" + getServletName() + "'");  
  143.             }  
  144.         } else {  
  145.             // No need to lookup: the ModelAndView object contains the actual  
  146.             // View object.  
  147.             view = mv.getView();  
  148.             if (view == null) {  
  149.                 throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a "  
  150.                         + "View object in servlet with name '" + getServletName() + "'");  
  151.             }  
  152.         }  
  153.         // Delegate to the View object for rendering.  
  154.         if (LOGGER.isDebugEnabled()) {  
  155.             LOGGER.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");  
  156.         }  
  157.         view.render(mv.getModelInternal(), request, response);  
  158.     }  
  159.   
  160.     protected View resolveViewName(String viewName, Map<String, Object> model, HttpServletRequest request)  
  161.             throws Exception {  
  162.         for (Iterator<ViewResolver> it = this.viewResolvers.iterator(); it.hasNext();) {  
  163.             ViewResolver viewResolver = it.next();  
  164.             View view = viewResolver.resolveViewName(viewName);  
  165.             if (view != null) {  
  166.                 return view;  
  167.             }  
  168.         }  
  169.         return null;  
  170.     }  
  171.   
  172.     protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {  
  173.         Iterator<HandlerAdapter> it = this.handlerAdapters.iterator();  
  174.         while (it.hasNext()) {  
  175.             HandlerAdapter ha = it.next();  
  176.             if (LOGGER.isDebugEnabled()) {  
  177.                 LOGGER.debug("Testing handler adapter [" + ha + "]");  
  178.             }  
  179.             if (ha.supports(handler)) {  
  180.                 return ha;  
  181.             }  
  182.         }  
  183.         throw new ServletException("No adapter for handler [" + handler  
  184.                 + "]: Does your handler implement a supported interface like Controller?");  
  185.     }  
  186.   
  187.     protected Object getHandler(HttpServletRequest request) throws Exception {  
  188.         Iterator<HandlerMapping> it = this.handlerMappings.iterator();  
  189.         while (it.hasNext()) {  
  190.             HandlerMapping hm = it.next();  
  191.             if (LOGGER.isDebugEnabled()) {  
  192.                 LOGGER.debug("Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName()  
  193.                         + "'");  
  194.             }  
  195.             return hm.getHandler(request);  
  196.         }  
  197.         return null;  
  198.     }  
  199.   
  200.     private String getDefaultViewName(HttpServletRequest request) {  
  201.         String url = request.getServletPath();  
  202.         url = url.replaceAll("/""");  
  203.         url = url.replaceAll(".html""");  
  204.         url = url.replaceAll(".htm""");  
  205.   
  206.         url = "WEB-INF/" + url + ".jsp";  
  207.   
  208.         return url;  
  209.     }  
  210.   
  211. }  

 

初始化操作.

  1. 检查系统中是否已经定义HandlerMapping。如果没有定义,则使用默认配置。
  2. 检查系统中是否已经定义HandlerAdapter。如果没有定义,则使用默认配置。
  3. 检查系统中是否已经定义ViewResolover。如果没有定义,则使用默认配置。

 

请求处理.

  1. 根据特定的请求,使用HandlerMapping找到相应的控制器Handler。
  2. 找到支持此种handler的HandlerAdapter,handler处理完响应业务后,HandlerAdapter把它转化为ModelAndView对象。
  3. 利用ViewResolver对ModelAndView进行分析,生成相应的View对象。
  4. 生成响应。

 

 

默认配置

  1. com.google.mvc.web.servlet.HandlerMapping=com.google.mvc.web.servlet.handler.URLHandlerMapping  
  2. com.google.mvc.web.servlet.HandlerAdapter=com.google.mvc.web.servlet.mvc.HttpRequestHandlerAdapter,/  
  3. com.google.mvc.web.servlet.mvc.ControllerHandlerAdapter  
  4. com.google.mvc.web.servlet.ViewResolver=com.google.mvc.web.servlet.mvc.DefaultViewResolver  

 

文章来源:http://blog.csdn.net/zhiqiangzhan/article/details/4767758

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics