package xdx.homework.second.litestruts;
import org.jcp.xml.dsig.internal.dom.DOMEnvelopedTransform;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class Struts {
private static Map<String, LoginAction> actionMap;
private static Map<String, Map<String, String>> actionResultMap;
private static void init() {
if (actionMap != null) return;
actionMap = new HashMap<>();
actionResultMap = new HashMap<>();
Document strutsDocument = getDocumentFromFile();
if (strutsDocument == null) throw new RuntimeException("xml文件读取错误,请检查文件路径是否正确!");
try {
NodeList nodeList = strutsDocument.getFirstChild().getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
if (nodeList.item(i).getNodeType() != 1) continue;
Element child = (Element) nodeList.item(i);
Class actionClass = Class.forName(child.getAttribute("class"));
actionMap.put(child.getAttribute("name"), (LoginAction) actionClass.newInstance());
NodeList resultList = child.getElementsByTagName("result");
Map<String, String> params = new HashMap<>();
for (int j = 0; j < resultList.getLength(); j++) {
Element result = (Element) resultList.item(j);
params.put(result.getAttribute("name"), result.getTextContent());
}
actionResultMap.put(child.getAttribute("name"), params);
}
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
throw new RuntimeException("xml文件内容有误!");
} catch (InstantiationException | IllegalAccessException e) {
System.out.println(e.getMessage());
throw new RuntimeException("无法创建接口或者抽象类的实例!");
}
}
public static View runAction(String actionName, Map<String, String> parameters) {
/*
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字段中。
*/
// 读取struts文件并初始化相关类
init();
// 根据actionName找到相对应的class
LoginAction loginAction = actionMap.get(actionName);
if (loginAction == null) {
System.out.println("找不到该action: " + actionName);
return null;
}
View view = new View();
// 据parameters中的数据调用相应的方法
Class clazz = loginAction.getClass();
try {
for (String key : parameters.keySet()) {
String value = parameters.get(key);
if (value == null || value.isEmpty()) continue;
PropertyDescriptor descriptor = new PropertyDescriptor(key, clazz);
descriptor.getWriteMethod().invoke(loginAction, value);
}
// 调用对象的exectue方法, 并获得返回值
String executeReturn = loginAction.execute();
// 通过反射找到对象的所有getter方法, 把值和属性形成一个HashMap ,放到View对象的parameters
PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
HashMap<String, String> params = new HashMap<>();
for (PropertyDescriptor pd : pds) {
params.put(pd.getName(), pd.getReadMethod().invoke(loginAction).toString());
}
view.setParameters(params);
// 确定哪一个jsp
view.setJsp(actionResultMap.get(actionName).get(executeReturn));
} catch (IntrospectionException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
return view;
}
private static Document getDocumentFromFile() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document document = null;
try {
URL fileURL = Struts.class.getResource("struts.xml");
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
document = documentBuilder.parse(new File(fileURL.getFile()));
} catch (ParserConfigurationException e) {
System.out.println("配置转化异常: " + e.getMessage());
} catch (SAXException e) {
System.out.println("SAX读取异常: " + e.getMessage());
} catch (IOException e) {
System.out.println("IO异常: " + e.getMessage());
}
return document;
}
}