package com.danny.hw2; import java.io.File; import java.lang.invoke.CallSite; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.jaxen.*; public class Struts { private static Document file = null; private static String file_path = new File("").getAbsolutePath()+".\\xmlFolder\\struts.xml"; private static String viewPath="com.danny.hw2.View"; //0. 读取配置文件struts.xml private static Document parse(String path){ SAXReader reader = new SAXReader(); Document document = null; try { document = reader.read(path); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } return document; } private static Element getAction(Document document,String name){ List<Element> lElement = (List<Element>) file.selectObject("/struts/action"); Element actionElement = null; for(Element e:lElement){ if(e.attributeValue("name").equals(name)){ actionElement = e; break; } } return actionElement; } public static View runAction(String actionName, Map<String,String> parameters) { file = parse(file_path); //返回的class View; Object viewClass = null; //0 Get Action Element Element actionElement = getAction(file, actionName); String actionClassPath = actionElement.attributeValue("class"); System.out.println(actionClassPath); Object action = null; try { /* 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" , "password"="1234") , 那就应该调用 setName和setPassword方法 */ action = Class.forName(actionClassPath).newInstance(); Method setName = action.getClass().getMethod("setName",String.class); setName.invoke(action, parameters.get("name")); Method setPassword = action.getClass().getMethod("setPassword",String.class); setPassword.invoke(action, parameters.get("password")); //2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" Method execute = action.getClass().getMethod("execute", null); Object status = execute.invoke(action); System.out.println(status.toString()); //3获得所有的Getter字段 Field[] files = action.getClass().getDeclaredFields(); HashMap<String,String> save = new HashMap<>(); //找到需要的数据,线存到save中 for (int i = 0; i < files.length; i++) { String name = files[i].getName(); name = "get" + name.substring(0,1).toUpperCase() + name.substring(1); Method getter = action.getClass().getMethod(name,null); save.put(files[i].getName(), (String) getter.invoke(action)); } //塞进viewClass里面 viewClass = Class.forName(viewPath).newInstance(); Method setParameters = viewClass.getClass().getMethod("setParameters", Map.class); setParameters.invoke(viewClass, save); //4将jsp放进去 List<Element> resultElement = actionElement.selectNodes("result"); for(Element e:resultElement){ if(e.attributeValue("name").equals(status.toString())){ String jspFields= e.getStringValue(); viewClass.getClass().getMethod("setJsp", String.class). invoke(viewClass, jspFields); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException(e.getMessage()); } /* 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字段中。 */ return (View) viewClass; } }