package com.xiaol.study; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.management.RuntimeErrorException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class Struts { // 每一个action的信息存放到一个Map<String, String>里 // 所有的Map<String, String>放到rootMap方便统一管理 private static HashMap<String, Map<String, String>> rootMap = new HashMap<String, Map<String, String>>(); public static View runAction(String actionName, Map<String,String> parameters) { View view = new View(); /* 0. 读取配置文件struts.xml 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" , "password"="1234") , 那就应该调用 setName和setPassword方法 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" 3. 通过反射找到对象的所有getter方法(例如 getMessage), 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , 放到View对象的parameters 4. 根据struts.xml中的 <result> 配置,以及execute的返回值, 确定哪一个jsp, 放到View对象的jsp字段中。 */ try { // 1、初始化读取配置文件 init(); // 2、获取根据参数获取对应的class的名字 Map<String, String> actionMap = rootMap.get(actionName); String className = actionMap.get("class"); // 3、根据名字获取Class对象 Class<?> clazzType = Class.forName(className); // 4、通过无参构造获取一个对象 Object newInstance = clazzType.getConstructor(new Class[] {}).newInstance(new Object[] {}); // 5、调用set方法,把("name"="test" , "password"="1234")值set进去 Set<Entry<String, String>> entrySet = parameters.entrySet(); Iterator<Entry<String, String>> iterator = entrySet.iterator(); while (iterator.hasNext()) { Entry<String, String> next = iterator.next(); String key = next.getKey(); String value = next.getValue(); String setMethodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1); Field declaredField = clazzType.getDeclaredField(key); Method setMehtod = clazzType.getDeclaredMethod(setMethodName, new Class[] { declaredField.getType() }); setMehtod.invoke(newInstance, value); } // 6、执行execute方法 String executeMethodName = "execute"; Method executeMethod = clazzType.getDeclaredMethod(executeMethodName); Object resultString = (String) executeMethod.invoke(newInstance); // 7、通过反射获取message信息 String getMethodName = "getMessage"; Field declaredField = clazzType.getDeclaredField("message"); Method getMehtod = clazzType.getDeclaredMethod(getMethodName); String message = (String) getMehtod.invoke(newInstance); // 8\ String jsp = actionMap.get(resultString); view.setJsp(jsp); Map<String, String> hashMap = new HashMap<>(); hashMap.put("message", message); view.setParameters(hashMap); } catch (Exception e) { e.printStackTrace(); throw new ExceptionInInitializerError(); } return view; } public static void init() throws Exception { // 1、获取工厂实例 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 2、获取dom解析器 DocumentBuilder db = dbf.newDocumentBuilder(); // 3、解析xml文档,获取document对象(根节点) // 也可以获取流使用db.parse(InputStream) // InputStream is = // this.getClass().getResourceAsStream("D:\\GitHub\\coding2017\\group23\\381519422\\litestruts\\src\\main\\resources\\struts.xml"); Document document = db.parse( new File("D:\\GitHub\\coding2017\\group23\\381519422\\litestruts\\src\\main\\resources\\struts.xml")); NodeList list = document.getElementsByTagName("action"); /* * 开始循环list,list中每一个元素结构如下 * <action name="login" class="com.coderising.litestruts.LoginAction"> <result name="success">/jsp/homepage.jsp</result> <result name="fail">/jsp/showLogin.jsp</result> </action> */ for (int i = 0; i < list.getLength(); i++) { Map<String, String> actionMap = new HashMap<String, String>(); // 注意:使用的都是org.w3c.dom包下的 Element element = (Element) list.item(i); // 获取<action name="login">中 name对应的属性值 String actionAttributeName = element.getAttribute("name"); String className = element.getAttribute("class"); actionMap.put("class", className); // 读取第一个action NamedNodeMap nnm = element.getElementsByTagName("result").item(0).getAttributes(); // 获取<result name="success">的属性 name // String nodeName = nnm.item(0).getNodeName(); // element.getElementsByTagName("result").item(0) // 是<result name="success">/jsp/homepage.jsp</result> // getFirstChild().getNodeValue() 是获取上面内容的/jsp/homepage.jsp String context = element.getElementsByTagName("result").item(0).getTextContent(); // 获取<result name="success">的属性 name对应的值success String nodeValue = nnm.item(0).getNodeValue(); actionMap.put(nodeValue, context); // 读取第二个action nnm = element.getElementsByTagName("result").item(1).getAttributes(); // 获取<result name="success">的属性 name // nodeName = nnm.item(0).getNodeName(); context = element.getElementsByTagName("result").item(1).getFirstChild().getNodeValue(); // 获取<result name="success">的属性 name对应的值success nodeValue = nnm.item(0).getNodeValue(); actionMap.put(nodeValue, context); rootMap.put(actionAttributeName, actionMap); } } public static void main(String[] args) { try { init(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 内部类用于存放从配置文件读取的数据 class StrutsMap { private HashMap<String, String> map; public String get(String key) { return map.get(key); } public void set(String key, String value) { map.put(key, value); } } }