`
z276356445t
  • 浏览: 151079 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

利用java反射模拟struts2工作(一)

阅读更多
最近闲来无事,就想着模拟一下struts2的工作机制,也没怎么去查看struts2的源码,大概了解它实现的机制,所以就磕磕碰碰的去写了一下这个东西,也许和struts2的实现机制不一样,但是目的总是一样的。
struts2首先也是装载相应的配置文件才能工作,当然struts2还有它的零配置也能完成工作,但是我模拟的是装载xml配置文件,要写xml文件当然也得写一个xsd文件来规范xml文件,现附上xsd文件。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.myblogs.org" elementFormDefault="qualified" targetNamespace="http://www.myblogs.org">


	<!-- 元素定义 -->
	<xs:element name="webwork" type="webworkType" />
	<xs:element name="action" />
	<xs:element name="result" />
	<xs:element name="param" />


	<xs:complexType name="webworkType">
		<xs:sequence>
			<xs:element name="action" minOccurs="1" maxOccurs="unbounded">
				<xs:complexType>
					<xs:sequence>
						<xs:element name="result" minOccurs="1" maxOccurs="unbounded">
							<xs:complexType mixed="true">
								<xs:sequence>
									<xs:element name="param" minOccurs="0" maxOccurs="unbounded">
										<xs:complexType>
											<xs:attribute name="name" type="xs:string" default="root"></xs:attribute>
										</xs:complexType>
									</xs:element>
								</xs:sequence>
								<xs:attributeGroup ref="resultValue" />
							</xs:complexType>
						</xs:element>
					</xs:sequence>
					<xs:attributeGroup ref="actionValue" />
				</xs:complexType>
			</xs:element>
		</xs:sequence>
	</xs:complexType>

	<xs:attributeGroup name="actionValue">
		<xs:attribute name="name" type="xs:string" use="required" />
		<xs:attribute name="class" type="xs:string" use="required" />
		<xs:attribute name="method" type="xs:string" default="execute" />
	</xs:attributeGroup>

	<xs:attributeGroup name="resultValue">
		<xs:attribute name="name" type="xs:string" use="required" />
		<xs:attribute name="type" type="xs:string" default="jsp" />
	</xs:attributeGroup>

</xs:schema>

xsd文件主要是规范xml文件中的元素以及各个属性,当然在eclipse中编写xml文件的时候,xsd将会验证xml文件是否符合xsd规范,如果是使用notepad来写xml文件的话,当然也只能用相应的语言来验证xml文件的规范了。
接着附上webwork.xml文件,类似于struts2中的struts2.xml
<?xml version="1.0" encoding="UTF-8"?>
<webwork xmlns="http://www.myblogs.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.myblogs.org webwork.xsd">
	<action name="AjaxAction" class="test.ajax.AjaxAction">
                <!-- result元素中目前支持jsp与json类型 -->
		<result name="ajaxResponse" type="json">
			<param name="root">user</param>
		</result>
	</action>

	<action name="LoginAction" class="blog.login.action.LoginAction">
		<result name="login" type="jsp">login.jsp</result>
	</action>
</webwork>

result元素中目前支持jsp与json类型,支持json类型的返回调用主要是为了ajax的支持,在ajax中使用json来传值当然方便很多,当然以后可以扩展更多的返回类型,比如freemarker等等。
下面来看看如何装载xml文件中的各个元素。为了以后方便扩展,分别写了4个相应的bean配置。
actionConfig.java,resultConfig.java,paramConfig.java,WebworkXmlConfig.java
package blog.base.config;

/**
 * @author 张廷 2011-5-18下午06:24:11
 * 
 */
public class ActionConfig {
	private String actionName;

	private Object actionClass;

	private String method;

	//省略getter 和setter
}

ResultConfig.java
package blog.base.config;

/**
 * @author 张廷 2011-5-18下午06:25:47
 * 
 */
public class ResultConfig {
	private String resultName;

	private String resultType;

	private String toUrl;

	private List<ParamConfig> paramConfigs;
	//省略getter 和setter
}

ParamConfig.java
package blog.base.config;

/**
 * 
 * @author 张廷 2011-5-18下午06:27:13
 * 
 */
public class ParamConfig {
	private String paramName;

	private String paramVarible;

	//省略getter和setter

}

WebworkXmlConfig.java
package blog.base.config;

import java.util.List;

/**
 * @author 张廷 2011-5-18下午08:25:53
 * 
 */
public class WebworkXmlConfig {
	private ActionConfig actionConfig;

	private List<ResultConfig> resultConfigs;

	//声裂getter和setter
}

最终操作在action的访问以及result返回时所操作的类全都是操作WebworkXmlConfig.java这个类,下面来看下装载xml文件的类,该类使用的是dom4j来解析xml文件。
/**
 * 
 */
package blog.base.util;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import blog.base.config.ActionConfig;
import blog.base.config.ParamConfig;
import blog.base.config.ResultConfig;
import blog.base.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-5-18下午02:59:27
 * 
 */
public class WebWorkXmlParser {

	private static WebworkXmlConfig webworkConfig;

	private static Logger logger = Logger.getLogger(WebWorkXmlParser.class);

	/**
	 * 装载webwork.xml中action节点的所有元素
	 * 
	 * @param path
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, WebworkXmlConfig> readActions(String configLocation) throws Exception {
		// 取得配置文件Url
		URL url = WebWorkXmlParser.class.getClassLoader().getResource(configLocation);
		SAXReader saxReader = new SAXReader();
		Map<String, WebworkXmlConfig> actionMapping = new HashMap<String, WebworkXmlConfig>();
		try {
			Document doc = saxReader.read(new File(path));
			Element rootElement = doc.getRootElement();
			if ("webwork".equals(rootElement.getName())) {
				for (Iterator<Element> actions = rootElement.elementIterator("action"); actions.hasNext();) {
					Element actionElmt = actions.next();
					webworkConfig = new WebworkXmlConfig();
					ActionConfig action = new ActionConfig();
					action.setActionName(actionElmt.attributeValue("name"));
					action.setActionClass(newInstance(actionElmt.attributeValue("class")));
					String method = actionElmt.attributeValue("method");
					// 访问action时是否指定相应方法,默认执行execute
					if ("".equals(method) || null == method) {
						action.setMethod("execute");
					} else {
						action.setMethod(method);
					}
					// 创建一个results,一个action会包含多个result
					List<ResultConfig> resultList = iterationResult(actionElmt);
					webworkConfig.setResultConfigs(resultList);
					webworkConfig.setActionConfig(action);
					actionMapping.put(action.getActionName(), webworkConfig);
				}
			} else
				throw new Exception("没有找到webwork标签!");
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return actionMapping;
	}

	/**
	 * 迭代action元素下的所有result
	 * 
	 * @param actionElmt
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static List<ResultConfig> iterationResult(Element actionElmt) {
		List<ResultConfig> resultList = new ArrayList<ResultConfig>();
		for (Iterator<Element> results = actionElmt.elementIterator("result"); results.hasNext();) {
			Element resultElmt = results.next();
			ResultConfig result = new ResultConfig();
			result.setResultName(resultElmt.attributeValue("name"));
			result.setResultType(resultElmt.attributeValue("type"));
			// 判断result下是否还有元素,如果还有元素,继续扫描
			if ("".equals(resultElmt.getTextTrim())) {
				// 创建一个params,一个result会包含多个param
				List<ParamConfig> paramList = iterationParam(resultElmt);
				result.setParamConfigs(paramList);
			} else {
				result.setToUrl(resultElmt.getTextTrim());
			}
			resultList.add(result);
		}
		return resultList;
	}

	/**
	 * 迭代result元素下的所有param
	 * 
	 * @param resultElmt
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static List<ParamConfig> iterationParam(Element resultElmt) {
		List<ParamConfig> paramList = new ArrayList<ParamConfig>();
		// 迭代result下的每个param
		for (Iterator<Element> params = resultElmt.elementIterator("param"); params.hasNext();) {
			Element paramElmt = params.next();
			ParamConfig param = new ParamConfig();
			param.setParamName(paramElmt.attributeValue("name"));
			param.setParamVarible(paramElmt.getTextTrim());
			paramList.add(param);
		}
		return paramList;
	}
 /**
	 * 创建一个实例
	 * 
	 * @param clazz
	 * @return
	 */
	private static Object newInstance(String clazz) {
		Object handler = null;
		try {
			handler = Class.forName(clazz).newInstance();
		} catch (InstantiationException e) {
			logger.fatal("对象无法被实例化!", e);
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			logger.error("该实例无法访问!", e);
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			logger.error("没有找到具有指定名称的类的定义!", e);
			e.printStackTrace();
		}
		return handler;
	}
}

这里将配置文件中的所有信息都注入到了WebworkXmlConfig这个实体中,以后要在servlet中访问action以及跳转到相应的jsp页面或者是使用json来响应客户端都要经过WebworkXmlConfig这个类来控制,这一节就到这,下一节将会涉及到servlet中如何使用此类来做访问响应工作。
5
1
分享到:
评论
5 楼 z276356445t 2011-06-02  
sarin 写道

呵呵,大家都是热爱技术的人。
4 楼 sarin 2011-06-02  
3 楼 lan861698789 2011-06-02  
我也有写过,呵呵
2 楼 z276356445t 2011-06-01  
sunliao_first 写道
你这个是超级迷你型,struts2很多重要的功能还需要实现

当然,我只是简单的模拟了一下struts2解析URL,访问Action以及返回客户端的工作过程,帮助理解MVC模式.
1 楼 sunliao_first 2011-06-01  
你这个是超级迷你型,struts2很多重要的功能还需要实现

相关推荐

Global site tag (gtag.js) - Google Analytics