package com.coderising.litestruts;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Struts {
public static String strutsPath;
public static String getStrutsPath() {
return strutsPath;
}
public static void setStrutsPath(String strutsPath) {
Struts.strutsPath = strutsPath;
}
public static View runAction(String actionName, Map<String,String> parameters) throws ParserConfigurationException, SAXException, IOException, InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
/*
0. 读取配置文件struts.xml
1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是
("name"="test" , "password"="1234") ,
那就应该调用 setName和setPassword方法
2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success"
4. 根据struts.xml中的 <result> 配置,以及execute的返回值, 确定哪一个jsp,
放到View对象的jsp字段中。
*/
if(strutsPath==null||strutsPath.equals("")){
strutsPath = initStrutsPath();
}
List<Action> actions = parseXml(strutsPath);
Action action = getAction(actions,actionName);
NotBeNull(action);
String actionClassName = action.getClassName();
Class actionClass = Class.forName(actionClassName);
Object actionClassObject = actionClass.newInstance();
doSetterMethod(parameters, actionClass, actionClassObject);
Method excuteMethod = actionClass.getMethod("execute", null);
String result = excuteMethod.invoke(actionClassObject, null).toString();
String viewPath = action.getResultAndViewMap().get(result);
View view = new View();
view.setJsp(viewPath);
Map<String, Object> parametersMap = doGetterMethod(actionClass, actionClassObject);
view.setParameters(parametersMap);
return view;
}
/**
* 3. 通过反射找到对象的所有getter方法(例如 getMessage),
通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} ,
放到View对象的parameters
* @param actionClass
* @param actionClassObject
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private static Map<String, Object> doGetterMethod(Class actionClass, Object actionClassObject)
throws IllegalAccessException, InvocationTargetException {
Map<String,Object> parametersMap = new HashMap<>();
for(Method method :actionClass.getMethods()){
if(method.getName().startsWith("get")){
String getValue = getMethodValue(method.getName());
parametersMap.put(getValue, method.invoke(actionClassObject, null));
}
}
return parametersMap;
}
/**
* 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是
("name"="test" , "password"="1234") ,
那就应该调用 setName和setPassword方法
* @param parameters
* @param actionClass
* @param actionClassObject
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private static void doSetterMethod(Map<String, String> parameters, Class actionClass, Object actionClassObject)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
for( Map.Entry<String, String> entry: parameters.entrySet()){
String param = entry.getKey();
Method methodKeySet = actionClass.getMethod(getMethodSet(param), String.class);
methodKeySet.invoke(actionClassObject, entry.getValue());
}
}
/**
* 初始化strutsPath
* @return
*/
private static String initStrutsPath() {
String path = Struts.class.getClassLoader().getResource("").getPath();
String strutsXmlPath = path+"/com/coderising/litestruts/struts.xml";
return strutsXmlPath;
}
/**
* 通过name构造setName
* @param name
* @return
*/
public static String getMethodSet(String name){
String firstChar = name.substring(0, 1).toUpperCase();
return "set"+firstChar+name.substring(1);
}
/**
* 获取getMessage对应的message
* @param name
* @return
*/
public static String getMethodValue(String name){
if(name.length()>=3){
name = name.substring(3);
}
String firstChar = name.substring(0, 1).toLowerCase();
return firstChar+name.substring(1);
}
/**
* 将xml解析成为Action的List结构
* @param xmlPath
* @return
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
public static List<Action> parseXml(String xmlPath) throws ParserConfigurationException, SAXException, IOException{
List<Action> retActionList = new ArrayList<>();
File xmlFile = new File(xmlPath);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(xmlFile);
NodeList actionLists = doc.getElementsByTagName("action");
for(int i=0;i<actionLists.getLength();i++){
Node currentNode= actionLists.item(i);
Action action = new Action();
String actionName = getAttribute(currentNode,"name");
String actionClass = getAttribute(currentNode,"class");
action.setActioName(actionName);
action.setClassName(actionClass);
HashMap<String, String> resultAndViewMap=getResultAndViewNodeList(currentNode);
action.setResultAndViewMap(resultAndViewMap);
retActionList.add(action);
}
return retActionList;
}
/**
* 获取该Node对应的result和对应的jsppath
* @param currentNode
* @param resultAndViewMap
*/
private static HashMap<String, String> getResultAndViewNodeList(Node currentNode) {
Map<String, String> resultAndViewMap = new HashMap<>();
NodeList resultAndViewNodeList = currentNode.getChildNodes();
for(int j=0;j<resultAndViewNodeList.getLength();j++){
Node resultAndViewNode= resultAndViewNodeList.item(j);
if("result".equals(resultAndViewNode.getNodeName())){
String result = getAttribute(resultAndViewNode,"name");
String viewPath = resultAndViewNode.getTextContent();
NotBeNull(result);
NotBeNull(viewPath);
resultAndViewMap.put(result, viewPath);
}
}
return (HashMap<String, String>) resultAndViewMap;
}
private static void NotBeNull(Object result) {
if(result==null){
throw new IllegalArgumentException();
}
}
public static String getAttribute(Node node ,String name){
NamedNodeMap nameNodeMap = node.getAttributes();
NotBeNull(nameNodeMap);
Node nameNode = nameNodeMap.getNamedItem(name);
NotBeNull(nameNode);
String actionName =nameNode.getNodeValue();
return actionName;
}
public static Action getAction(List<Action> actions ,String actionName){
for(Action action:actions){
if(action.getActioName().equals(actionName)){
return action;
}
}
return null;
}
}