每个牛逼的框架设计的背后都有一群头脑灵活、闷骚幽默的人。他们对待工作乐观积极,总是能拿出有效的解决方案来处理那些棘手难解的问题。
近来越发的感觉到配置文件的强大之处,也佩服第一个尝试着用这种方式分解变化、消减 耦合的程序猿。层出不穷的框架,都是有着各自的特殊使命,带着不同的解决方案在项目中大放异彩。可能我们更多在使用着框架,没多想过每一个框架都有着自己独特的设计思想,都有博人眼球的地方。它们有共同的地方,那也是我要多次提到的配置文件。
XML(Extensible MarkupLanguage),是一种可扩展的标记性语言。(推荐,学习XML的系列文章)在xml文件的<>中间我们可以随心所欲的定义标签,拓展性和易用性很强大,我们常见的xml内容如下:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
其中<?xmlversion="1.0" encoding="ISO-8859-1" ?>是用来标识我们该xml文件版本和编码,而DOCTYPE则是定义该xml文件的一个规范(格式校验)文件。也就是我们在Struts-config.xml中定义的那些<struts-config>、<form-beans>、<form-property>等等,都是可以在struts-core-1.3.jar中找到的struts-config_1.3.dtd文件中看到其相关的标签定义:
同样,在我们Struts1的框架中核心ActionServlet.class也定义了一些方法来加载和实例化我们xml配置文件中的各类标签实体,如下:
/**
* <p>Initialize the servlet mapping under which our controller servlet is
* being accessed. This will be used in the <code>&html:form></code>
* tag to generate correct destination URLs for form submissions.</p>
*
* @throws ServletException if error happens while scanning web.xml
*/
protected void initServlet()
throws ServletException {
// Remember our servlet name
this.servletName = getServletConfig().getServletName();
// Prepare a Digester to scan the web application deployment descriptor
Digester digester = new Digester();
digester.push(this);
digester.setNamespaceAware(true);
digester.setValidating(false);
// Register our local copy of the DTDs that we can find
for (int i = 0; i < registrations.length; i += 2) {
URL url = this.getClass().getResource(registrations[i + 1]);
if (url != null) {
digester.register(registrations[i], url.toString());
}
}
// Configure the processing rules that we need
digester.addCallMethod("web-app/servlet-mapping", "addServletMapping", 2);
digester.addCallParam("web-app/servlet-mapping/servlet-name", 0);
digester.addCallParam("web-app/servlet-mapping/url-pattern", 1);
// Process the web application deployment descriptor
if (log.isDebugEnabled()) {
log.debug("Scanning web.xml for controller servlet mapping");
}
InputStream input =
getServletContext().getResourceAsStream("/WEB-INF/web.xml");
if (input == null) {
log.error(internal.getMessage("configWebXml"));
throw new ServletException(internal.getMessage("configWebXml"));
}
try {
digester.parse(input);
} catch (IOException e) {
log.error(internal.getMessage("configWebXml"), e);
throw new ServletException(e);
} catch (SAXException e) {
log.error(internal.getMessage("configWebXml"), e);
throw new ServletException(e);
} finally {
try {
input.close();
} catch (IOException e) {
log.error(internal.getMessage("configWebXml"), e);
throw new ServletException(e);
}
}
// Record a servlet context attribute (if appropriate)
if (log.isDebugEnabled()) {
log.debug("Mapping for servlet '" + servletName + "' = '"
+ servletMapping + "'");
}
if (servletMapping != null) {
getServletContext().setAttribute(Globals.SERVLET_KEY, servletMapping);
}
}
当然我拿到的只是一部分框架中有关配置文件的类和文件,我们做好一个优秀的框架,只是这些是远远不够的。比如在Struts1中还有很多类来处理框架中的点点滴滴,比如org.apache.struts.config包下都是处理框架中配置相关的内容。
反射机制是和配置文件协作而来的,我们要把配置中的逻辑对象和实体对象映射起来,还要借助反射技术来实现。
没有太多精力去深入研究一个框架的林林总总,暂对他们的共性做点了解。的确,现在用xml来灵活的帮我们实现功能成了很普遍的事情,越是如此轻量没有多少侵入性的东西越是受到大家的欢迎。