`

MVC架构探究及其源码实现(3)-WebApplicationContext

 
阅读更多

直接利用web.xml去配置和定义我们的对象组件显然是不灵活和不方便扩展的,由于我们系统中将会需要配置很多个不同的对象资源,比如控制器,View对象,HandlerMapping对象等等,如何对它们进行管理,如何能让我们的前端控制器访问和利用到到它们便是我们不得不面对的问题。还好,现在有了Spring,现在很多流行的MVC框架都支持使用Spring对自己容器里的对象资源进行管理。尽管Spring千好万好,我们这里还是决定不使用它,而是自己来写一个对象容器来管理我们的相关资源,这样我们不仅可以了解对象资源配置管理的细节,还可以顺带学习一下Spring等IOC容器的实现原理。当然,我们这里的实现方案将会尽可能的简单。
如下便是我们的WebApplicationContext类的实现,它能够自动查找WEB-INF路径下所有以config结尾的xml文件,并把其中定义的对象抽取出来,放到Application作用域中,由于我们这里只是个Sample,不需要考虑太多的并发的情况,所有对象的类型,我们都是用Singleton,也就是定义的每个对象都为所有的请求和Servlet共享。 WebApplicationContext中还定义了一个很有用的方法,beansOfType(Class<T>),该方法用于查找出系统中定义的所有的属于当前类型的所有对象资源。

[java] view plaincopy
  1. package com.google.mvc.web.context;  
  2.   
  3. import java.io.InputStream;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import java.util.HashMap;  
  7. import java.util.Locale;  
  8. import java.util.Map;  
  9. import java.util.Set;  
  10. import java.util.concurrent.ConcurrentHashMap;  
  11.   
  12. import javax.servlet.ServletContext;  
  13. import javax.xml.parsers.DocumentBuilder;  
  14. import javax.xml.parsers.DocumentBuilderFactory;  
  15. import javax.xml.parsers.ParserConfigurationException;  
  16.   
  17. import org.apache.log4j.Logger;  
  18. import org.w3c.dom.Document;  
  19. import org.w3c.dom.Element;  
  20. import org.w3c.dom.NodeList;  
  21.   
  22. public class WebApplicationContext {  
  23.       
  24.     private static final Logger LOGGER = Logger.getLogger(WebApplicationContext.class);   
  25.     private static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".CONTEXT";  
  26.     private Map<String, Object> cacheMap;  
  27.     private ServletContext servletContext;  
  28.     private DocumentBuilder builder;      
  29.   
  30.     public WebApplicationContext(ServletContext servletContext) {  
  31.         this.servletContext = servletContext;                 
  32.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  33.         try {  
  34.             builder = factory.newDocumentBuilder();  
  35.         } catch (ParserConfigurationException e) {  
  36.             LOGGER.error("Can't load dom builder", e);  
  37.         }  
  38.     }  
  39.   
  40.     public void init() {          
  41.         ServletContext context = getServletContext();  
  42.         Set<?> set = context.getResourcePaths("/WEB-INF");  
  43.         Object map = servletContext.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE);  
  44.         if (map != null) {  
  45.             cacheMap = (Map<String, Object>) map;  
  46.         } else {  
  47.             cacheMap = new ConcurrentHashMap<String, Object>();  
  48.             servletContext.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, cacheMap);             
  49.             for (Object o : set) {  
  50.                 String path = (String) o;  
  51.                 if (path.endsWith("config.xml")) {  
  52.                     try {                         
  53.                         loadResource(servletContext.getResourceAsStream(path));  
  54.                     } catch (Exception ex) {  
  55.                         LOGGER.error("Can't load resource " + path);  
  56.                     }  
  57.                 }  
  58.             }  
  59.         }  
  60.     }  
  61.       
  62.     private void loadResource(InputStream resource) throws Exception{  
  63.         Document doc = builder.parse(resource);  
  64.         Element root = doc.getDocumentElement();  
  65.           
  66.         NodeList nodeList = root.getElementsByTagName("bean");    
  67.         for(int i = 0; i < nodeList.getLength(); i++){             
  68.             Element el = (Element)nodeList.item(i);           
  69.             String id = el.getAttribute("id");  
  70.             String className = el.getAttribute("class");              
  71.             Class<?> clazz = this.getClass().getClassLoader().loadClass(className);  
  72.             Object o = createBean(id, clazz);             
  73.             NodeList propertyList = el.getElementsByTagName("property");  
  74.             for(int j = 0; j < propertyList.getLength(); j++){  
  75.                 Element prop = (Element)propertyList.item(j);                 
  76.                 String methodName = getMethodName(prop.getAttribute("name"));                 
  77.                 Method m = clazz.getMethod(methodName, String.class);                 
  78.                 String property = prop.getAttribute("value");  
  79.                 Object dependObject = cacheMap.get(property);  
  80.                 if(dependObject != null){  
  81.                     m.invoke(o, dependObject);  
  82.                 } else {  
  83.                     m.invoke(o, property);  
  84.                 }                         
  85.             }             
  86.             cacheMap.put(id, o);  
  87.         }         
  88.     }  
  89.       
  90.     protected String getMethodName(String methodName){  
  91.         StringBuilder sb = new StringBuilder();  
  92.         sb.append("set");  
  93.         sb.append(methodName.substring(01).toUpperCase(Locale.US));  
  94.         sb.append(methodName.substring(1));  
  95.         return sb.toString();  
  96.     }  
  97.       
  98.     public Object createBean(Class<?> clazz) throws Exception{          
  99.         return createBean(clazz.getCanonicalName(), clazz);  
  100.     }  
  101.       
  102.     public Object createBean(String name, Class<?> clazz) throws Exception{             
  103.         Object o = cacheMap.get(name);        
  104.         if(o == null){  
  105.             o = clazz.newInstance();  
  106.             if(o instanceof WebApplicationContextAware){  
  107.                 ((WebApplicationContextAware)o).setWebApplicationContext(this);  
  108.             }  
  109.             cacheMap.put(name, o);    
  110.         }     
  111.         LOGGER.info(name + "=" + clazz.getCanonicalName());  
  112.         return o;  
  113.     }  
  114.       
  115.     public Object getBean(String beanName){  
  116.         return servletContext.getAttribute(beanName);  
  117.     }  
  118.       
  119.     public ServletContext getServletContext() {  
  120.         return servletContext;  
  121.     }  
  122.   
  123.     public void setServletContext(ServletContext servletContext) {  
  124.         this.servletContext = servletContext;  
  125.     }  
  126.       
  127.     public <T> Map<String, T> beansOfType(Class<T> clazz){  
  128.         Map<String, T> map = new HashMap<String, T>();  
  129.         for(String key : cacheMap.keySet()){  
  130.             Object o = cacheMap.get(key);  
  131.             if(clazz.isAssignableFrom(o.getClass())){  
  132.                 map.put(key, (T)o);  
  133.             }  
  134.         }  
  135.         return map;  
  136.     }  
  137.   
  138. }  

我们再来看一下*.config.xml文件里对象资源的定义示例:

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans>     
  3.     <bean id="ControllerAdapter" class="com.google.mvc.web.servlet.mvc.ControllerHandlerAdapter" />    
  4.     <bean id="HttpRequestAdapter" class="com.google.mvc.web.servlet.mvc.HttpRequestHandlerAdapter" />   
  5.     <bean id="ViewResolver" class="com.google.mvc.web.servlet.mvc.DefaultViewResolver">  
  6.         <property name="viewClass" value="com.google.mvc.web.servlet.mvc.InternalResourceView"/>  
  7.         <property name="prefix" value="/WEB-INF/"/>  
  8.         <property name="suffix" value=".jsp"/>  
  9.     </bean>   
  10.     <bean id="login.do" class="com.google.mvc.web.sample.LoginController" />  
  11.     <bean id="hello.do" class="com.google.mvc.web.sample.HelloController" />     
  12.     <bean id="404" class="com.google.mvc.web.servlet.mvc.HandlerFor404" />   
  13.   
  14. </beans>  

如果哪个对象资源需要在运行过程中使用到WebApplicationContext的资源及方法,只需实现接口WebApplicationContextAware即可,一旦实现了该接口,当前的WebApplicationContext会被自动的注入到此对象资源中。

[java] view plaincopy
  1. package com.google.mvc.web.context;  
  2.   
  3. public interface WebApplicationContextAware {  
  4.       
  5.     void setWebApplicationContext(WebApplicationContext wac);  
  6.   
  7. }  

 

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

分享到:
评论

相关推荐

    springmvc 学习指南 源码 app06-app12

    Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,专为构建 MVC(Model-View-Controller)架构的应用程序而设计。本学习指南涵盖从 app06 到 app12 的一系列源码,旨在帮助开发者深入...

    深入剖析Spring Web源码

    #### 三、Spring Web MVC的架构实现 **3.1 DISPATCHERSERVLET的实现** - **3.1.1 通用Servlet和HTTPServlet** - `Servlet`是Java Servlet API中定义的一个接口,它是Web容器的标准组件,用于处理客户端的HTTP请求...

    spring源码spring-framework-4.2.5.RELEASE

    《深入剖析Spring Framework 4.2.5.RELEASE源码》 Spring Framework是Java开发领域中的基石,它为构建高质量的、易于维护的应用程序提供了全面的基础设施。4.2.5.RELEASE版本作为Spring发展的一个重要里程碑,包含...

    spring-mvc-documentation-linesh-translation

    - **WebApplicationContext**: 这是 Spring Web MVC 的应用上下文,用于管理 Web 层的 Bean 和配置。 #### 默认配置 - **默认的DispatcherServlet配置**: DispatcherServlet 的默认配置包括自动检测控制器类、注册...

    第一次搭建spring3.x需要的jar和搭建源码

    - **MVC框架**:提供了一种用于构建Web应用程序的模型-视图-控制器架构。 - **数据访问**:支持JDBC、Hibernate、MyBatis等ORM框架,简化数据库操作。 **2. 搭建Spring 3.x环境所需的jar包** - **spring-beans.jar*...

    Spring MVC总结(一)

    Spring MVC架构与DispatcherServlet配置 Spring MVC是一种流行的基于Java的Web应用框架,它提供了一个灵活的架构来开发Web应用程序。在本文中,我们将对Spring MVC的架构和DispatcherServlet的配置进行总结。 ...

    SpringMVC源码剖析(二)- DispatcherServlet的前世今生1

    本文将深入探讨DispatcherServlet的两个核心设计原则及其在Spring MVC中的应用。 1. 对扩展开放,对修改封闭 Spring MVC遵循开放封闭原则(Open-Closed Principle,OCP),该原则是面向对象设计的基本准则之一。在...

    spring mvc jar包

    3. `org.springframework.web.servlet-3.0.2.RELEASE.jar`:这是 Spring MVC 的核心模块,提供了控制器(Controller)、模型视图(ModelAndView)以及调度器Servlet(DispatcherServlet)等关键组件。...

    Spring Web MVC外文翻译

    ### Spring Web MVC 外文翻译知识点解析 #### 一、Spring Web MVC介绍 ...特别是 DispatcherServlet 的配置及其与 WebApplicationContext 的交互方式,是深入掌握 Spring Web MVC 不可缺少的一部分。

    spring-mvc-rest-post-unit-testing:Spring MVC REST JSON发布请求单元测试示例

    在本文中,我们将深入探讨如何使用Java进行Spring MVC REST JSON发布请求的单元测试。Spring MVC是Spring框架的一个组件,主要用于构建Web应用程序,而REST(Representational State Transfer)是一种设计网络应用的...

    mvc问题代码

    Spring MVC是Spring框架的一个模块,它专为构建Web应用程序提供模型-视图-控制器(MVC)架构。下面我们将详细讲解Spring MVC的基础知识、CRUD操作的实现,以及可能遇到的问题。 1. **Spring MVC框架概述** Spring ...

    spring-web.jar spring-webmvc.jar

    1. **Servlet上下文**:`spring-web.jar`提供了`WebApplicationContext`,这是Spring应用程序在Web环境中的上下文。它允许bean与Servlet上下文进行交互,例如注册监听器、过滤器等。 2. **HTTP处理**:包括`...

    详解Spring mvc ant path的使用方法

    - **WebApplicationContext**:Spring MVC 中的应用上下文,用于存储应用范围内的bean,与普通的`ApplicationContext`相比,更关注web环境。 - **访问静态文件**:Spring MVC可以通过配置让服务器处理静态资源,如...

    spring mvc

    Spring MVC 使用 HandlerMapping 接口及其实现类来完成请求与处理方法的映射。常见的映射方式包括: - **路径映射**:通过 URL 路径匹配控制器方法。 - **注解映射**:使用 `@RequestMapping` 注解定义 URL 与方法的...

    Spring mvc 教程

    - **允许其他MVC实现**:Spring MVC 支持多种不同的 MVC 实现,这为开发者提供了更多的选择性。 - **DispatcherServlet**:这是 Spring MVC 的前端控制器,负责接收 HTTP 请求并分发给合适的后端组件处理。 - **...

    spring-webmvc.src.zip

    Spring Web MVC 是 Spring 框架的重要组成部分,它为构建基于Java的Web应用程序提供了模型-视图-控制器(MVC)架构。Spring Web MVC 提供了一种优雅的方式来处理HTTP请求和响应,允许开发者专注于业务逻辑,而将视图...

    spring mvc学习笔记

    在 Spring MVC 中,可以通过多种方式实现 HandlerMapping,例如通过 URL 映射、注解映射等。 - 上述示例中的 `SimpleUrlHandlerMapping` 就是一种简单的 URL 映射方式,通过配置文件定义了具体的 URL 路径到控制...

    Spring-5.1.5源码

    在Web应用中,`ContextLoaderListener`创建的是一个`WebApplicationContext`,这是专门为Web环境设计的ApplicationContext子类,它能与Servlet容器进行更紧密的集成。 2. **配置加载**:`ContextLoaderListener`...

    Spring MVC启动时初始化的几个常用方法

    在Spring MVC框架中,应用程序启动时会执行一系列初始化操作,这些操作对于理解Spring...在实际开发中,我们可以通过阅读源码、调试或日志跟踪,更深入地了解这些初始化操作的细节,从而提升我们的Spring MVC编程技能。

    spring mvc 快速入门深入分析

    3. `HandlerMapping`返回合适的`Handler`及其适配器`HandlerAdapter`。 4. `HandlerAdapter`执行`Handler`。 5. `Handler`执行完成后返回`ModelAndView`对象。 6. `DispatcherServlet`通过`ViewResolver`解析视图。 ...

Global site tag (gtag.js) - Google Analytics