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

简介:

博学,切问,近思--詹子知 (https://jameszhan.github.io)

直接利用web.xml去配置和定义我们的对象组件显然是不灵活和不方便扩展的,由于我们系统中将会需要配置很多个不同的对象资源,比如控制器,View对象,HandlerMapping对象等等,如何对它们进行管理,如何能让我们的前端控制器访问和利用到到它们便是我们不得不面对的问题。还好,现在有了Spring,现在很多流行的MVC框架都支持使用Spring对自己容器里的对象资源进行管理。尽管Spring千好万好,我们这里还是决定不使用它,而是自己来写一个对象容器来管理我们的相关资源,这样我们不仅可以了解对象资源配置管理的细节,还可以顺带学习一下Spring等IOC容器的实现原理。当然,我们这里的实现方案将会尽可能的简单。
如下便是我们的WebApplicationContext类的实现,它能够自动查找WEB-INF路径下所有以config结尾的xml文件,并把其中定义的对象抽取出来,放到Application作用域中,由于我们这里只是个Sample,不需要考虑太多的并发的情况,所有对象的类型,我们都是用Singleton,也就是定义的每个对象都为所有的请求和Servlet共享。 WebApplicationContext中还定义了一个很有用的方法,beansOfType(Class<T>),该方法用于查找出系统中定义的所有的属于当前类型的所有对象资源。package com.google.mvc.web.context; import java.io.InputStream; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.ServletContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public class WebApplicationContext { private static final Logger LOGGER = Logger.getLogger(WebApplicationContext.class); private static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".CONTEXT"; private Map<String, Object> cacheMap; private ServletContext servletContext; private DocumentBuilder builder; public WebApplicationContext(ServletContext servletContext) { this.servletContext = servletContext; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { LOGGER.error("Can't load dom builder", e); } } public void init() { ServletContext context = getServletContext(); Set<?> set = context.getResourcePaths("/WEB-INF"); Object map = servletContext.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE); if (map != null) { cacheMap = (Map<String, Object>) map; } else { cacheMap = new ConcurrentHashMap<String, Object>(); servletContext.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, cacheMap); for (Object o : set) { String path = (String) o; if (path.endsWith("config.xml")) { try { loadResource(servletContext.getResourceAsStream(path)); } catch (Exception ex) { LOGGER.error("Can't load resource " + path); } } } } } private void loadResource(InputStream resource) throws Exception{ Document doc = builder.parse(resource); Element root = doc.getDocumentElement(); NodeList nodeList = root.getElementsByTagName("bean"); for(int i = 0; i < nodeList.getLength(); i++){ Element el = (Element)nodeList.item(i); String id = el.getAttribute("id"); String className = el.getAttribute("class"); Class<?> clazz = this.getClass().getClassLoader().loadClass(className); Object o = createBean(id, clazz); NodeList propertyList = el.getElementsByTagName("property"); for(int j = 0; j < propertyList.getLength(); j++){ Element prop = (Element)propertyList.item(j); String methodName = getMethodName(prop.getAttribute("name")); Method m = clazz.getMethod(methodName, String.class); String property = prop.getAttribute("value"); Object dependObject = cacheMap.get(property); if(dependObject != null){ m.invoke(o, dependObject); } else { m.invoke(o, property); } } cacheMap.put(id, o); } } protected String getMethodName(String methodName){ StringBuilder sb = new StringBuilder(); sb.append("set"); sb.append(methodName.substring(0, 1).toUpperCase(Locale.US)); sb.append(methodName.substring(1)); return sb.toString(); } public Object createBean(Class<?> clazz) throws Exception{ return createBean(clazz.getCanonicalName(), clazz); } public Object createBean(String name, Class<?> clazz) throws Exception{ Object o = cacheMap.get(name); if(o == null){ o = clazz.newInstance(); if(o instanceof WebApplicationContextAware){ ((WebApplicationContextAware)o).setWebApplicationContext(this); } cacheMap.put(name, o); } LOGGER.info(name + "=" + clazz.getCanonicalName()); return o; } public Object getBean(String beanName){ return servletContext.getAttribute(beanName); } public ServletContext getServletContext() { return servletContext; } public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } public <T> Map<String, T> beansOfType(Class<T> clazz){ Map<String, T> map = new HashMap<String, T>(); for(String key : cacheMap.keySet()){ Object o = cacheMap.get(key); if(clazz.isAssignableFrom(o.getClass())){ map.put(key, (T)o); } } return map; } } 我们再来看一下*.config.xml文件里对象资源的定义示例:<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="ControllerAdapter" class="com.google.mvc.web.servlet.mvc.ControllerHandlerAdapter" /> <bean id="HttpRequestAdapter" class="com.google.mvc.web.servlet.mvc.HttpRequestHandlerAdapter" /> <bean id="ViewResolver" class="com.google.mvc.web.servlet.mvc.DefaultViewResolver"> <property name="viewClass" value="com.google.mvc.web.servlet.mvc.InternalResourceView"/> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> <bean id="login.do" class="com.google.mvc.web.sample.LoginController" /> <bean id="hello.do" class="com.google.mvc.web.sample.HelloController" /> <bean id="404" class="com.google.mvc.web.servlet.mvc.HandlerFor404" /> </beans> 如果哪个对象资源需要在运行过程中使用到WebApplicationContext的资源及方法,只需实现接口WebApplicationContextAware即可,一旦实现了该接口,当前的WebApplicationContext会被自动的注入到此对象资源中。package com.google.mvc.web.context; public interface WebApplicationContextAware { void setWebApplicationContext(WebApplicationContext wac); }

相关文章:

  1. MVC架构探究及其源码实现(1)-理论基础
  2. MVC架构探究及其源码实现(2)-核心组件定义
  3. MVC架构探究及其源码实现(4)-前端控制器
  4. MVC架构探究及其源码实现(5)-相关组件实现
  5. MVC架构探究及其源码实现(6)-简单示例

目录
相关文章
|
2天前
|
存储 SQL 网络协议
C语言C/S架构PACS影像归档和通信系统源码 医院PACS系统源码
医院影像科PACS系统,意为影像归档和通信系统。它是应用在医院影像科室的系统,主要的任务是把日常产生的各种医学影像(包括核磁、CT、超声、各种X光机、各种红外仪、显微仪等设备产生的图像)通过各种接口(模拟、DICOM、网络)以数字化的方式海量保存起来,并在需要的时候在一定授权下能够快速地调回使用。同时,PACS系统还增加了一些辅助诊断管理功能。
40 11
|
2天前
|
存储 开发框架 前端开发
前端框架EXT.NET Dotnet 3.5开发的实验室信息管理系统(LIMS)成品源码 B/S架构
发展历史:实验室信息管理系统(LIMS),就是指通过计算机网络技术对实验的各种信息进行管理的计算机软、硬件系统。也就是将计算机网络技术与现代的管理思想有机结合,利用数据处理技术、海量数据存储技术、宽带传输网络技术、自动化仪器分析技术,来对实验室的信息管理和质量控制等进行全方位管理的计算机软、硬件系统,以满足实验室管理上的各种目标(计划、控制、执行)。
20 1
|
2天前
|
安全 数据管理 中间件
云LIS系统源码JavaScript+B/S架构MVC+SQLSugar医院版检验科云LIS系统源码 可提供演示
检验科云LIS系统源码是医疗机构信息化发展的重要趋势。通过云计算技术实现数据的集中管理和共享可以提高数据利用效率和安全性;通过高效灵活的系统设计和可扩展性可以满足不同医疗机构的需求;通过移动性和智能化可以提高医疗服务的精准度和效率;通过集成性可以实现医疗服务的协同性和效率。因此,多医院版检验科云LIS系统源码将成为未来医疗机构信息化发展的重要方向之一。
27 2
|
2天前
|
Java 关系型数据库 MySQL
java+B/S架构医院绩效考核管理系统源码 医院绩效管理系统4大特点
医院绩效考核管理系统,采用多维度综合绩效考核的形式,针对院内实际情况分别对工作量、KPI指标、科研、教学、管理等进行全面考核。医院可结合实际需求,对考核方案中各维度进行灵活配置,对各维度的权重、衡量标准、数据统计方式进行自定义维护。
10 0
|
2天前
|
前端开发 Java 数据库
MVC架构简述
MVC架构简述
11 4
|
2天前
|
前端开发 Java 关系型数据库
Java医院绩效考核系统源码B/S架构+springboot三级公立医院绩效考核系统源码 医院综合绩效核算系统源码
作为医院用综合绩效核算系统,系统需要和his系统进行对接,按照设定周期,从his系统获取医院科室和医生、护士、其他人员工作量,对没有录入信息化系统的工作量,绩效考核系统设有手工录入功能(可以批量导入),对获取的数据系统按照设定的公式进行汇算,且设置审核机制,可以退回修正,系统功能强大,完全模拟医院实际绩效核算过程,且每步核算都可以进行调整和参数设置,能适应医院多种绩效核算方式。
31 2
|
2天前
|
存储 前端开发 Java
软件体系结构 - 架构风格(13)MVC架构风格
【4月更文挑战第21天】软件体系结构 - 架构风格(13)MVC架构风格
30 0
|
2天前
|
前端开发 Java PHP
信息系统架构模型(1) MVC
信息系统架构模型(1) MVC
23 0
|
2天前
|
消息中间件 运维 Java
B/S架构,采用JAVA编程的医院云HIS系统源码,公立二甲医院应用案例
SaaS模式Java版云HIS系统,在公立二甲医院应用多年,经过多年持续优化系统运行稳定、功能齐全,界面布局合理、操作简便。融合B/S版电子病历系统,支持电子病历四级,HIS与电子病历系统均拥有自主知识产权。 云HIS系统采用云端SaaS服务的方式提供,使用用户通过浏览器即能访问,无需关注系统的部署、维护、升级等问题,系统充分考虑了模板化、配置化、智能化、扩展化等设计方法,覆盖了基层医疗机构的主要工作流程,能够与监管系统有序对接,并能满足未来系统扩展的需要。
B/S架构,采用JAVA编程的医院云HIS系统源码,公立二甲医院应用案例
|
2天前
|
缓存 小程序
Java+saas模式 智慧校园系统源码MySQL5.7+ elmentui前后端分离架构 让校园管理更高效的数字化平台系统源码
智慧校园是在数字通增强版基础上,研发的一套面向教育行业的数字化校园软件,其显著特点是集学校网站、协同办公、即时通讯、网络空间、移动办公于一体。在满足教职工日常办公需要的同时,拥有诸多教育行业功能,并提供便捷易用的“家校通”平台以满足老师、学生、家长的日常交流。数字通智慧校园教育版中的协同办公、即时通讯、移动办公等功能模块随通用版一同改进,将网络办公最新技术应用到教育行业。
47 1