package com.coding.basic.homework_02.litestruts;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class Struts {
private static String jspUrl = null;
private static String resultStatic = null;
public static View runAction(String actionName, Map<String, String> params) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, DocumentException{
/*
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字段中。
*/
Element root = getRoot();
Class clazz = getClazz(actionName, root);
Object obj = clazz.newInstance();
View view = new View();
methodInvoke(clazz, obj, params);
String result = getExecuteInfo(clazz, obj);
setParams(clazz, obj, view);
getJsp(result, root, actionName);
view.setJsp(jspUrl);
return view;
}
/**
* 读取xml文件获得根节点
* @return
* @throws DocumentException
*/
private static Element getRoot() throws DocumentException{
//step1:创建SAXReader对象
SAXReader reader = new SAXReader();
//step2:读取文件 转换成Document
Document document = reader.read("src/com/coding/basic/homework_02/litestruts/struts.xml");
return document.getRootElement();
}
/**
* 根据给定的actionName找到对应的Class
* @return
* @throws ClassNotFoundException
*/
@SuppressWarnings("rawtypes")
private static Class getClazz(String actionName, Element node) throws ClassNotFoundException{
findClassNameByAttr(node, actionName);
if(resultStatic != null)
return Class.forName(resultStatic);
throw new ClassNotFoundException();
}
/**
* 根据resultName找到对应的jsp路径
* @param resultName
* @param node
* @return
*/
@SuppressWarnings("unchecked")
private static void getJsp(String resultName, Element node, String actionName){
if(node.attributes() != null)
forEachAttr(node.attributes(), actionName, node, resultName);
List<Element> listElement = node.elements();
for(Element e : listElement)
getJsp(resultName, e, actionName);
if(jspUrl != null)
return;
}
/**
* 遍历当前结点的属性
* @param list
* @param actionName
* @param node
* @param resultName
*/
private static void forEachAttr(List<Attribute> list, String actionName, Element node, String resultName){
List<Attribute> attrs = node.attributes();
for(Attribute attr : attrs){
if(resultName.equals(attr.getValue()) && !"".equals(node.getTextTrim()))
findJspByParentNode(actionName, node);
}
}
/**
* 根据跟定的action找到对应的jspUrl
* @param actionName
* @param node
*/
private static void findJspByParentNode(String actionName, Element node){
Element parent = node.getParent();
if(parent.attributes() != null){
for(Attribute pattr : (List<Attribute>)parent.attributes()){
if(actionName.equals(pattr.getValue()))
jspUrl = node.getTextTrim();
}
}
}
/**
* 获取execute()方法运行后的信息
* @param clazz
* @param obj
* @return
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private static String getExecuteInfo(Class clazz, Object obj) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Method executeMethod = clazz.getMethod("execute", null);
return (String)executeMethod.invoke(obj, null);
}
/**
* 将类中的getter信息放入View
* @return
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static View setParams(Class clazz, Object obj, View view) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Map<String, String> viewMap = getterAttr(clazz, obj);
view.setParameters(viewMap);
return view;
}
/**
* 找出当前对象的所有getter方法,将信息放入map中
* @param clazz
* @return
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
private static Map<String, String> getterAttr(Class clazz, Object obj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Map<String, String> viewMap = new HashMap<String, String>();
//获取所有的getter方法
Method[] methods = clazz.getDeclaredMethods();
for(Method me : methods){
if("get".equals(me.getName().substring(0, 3)))
viewMap.put(method2Attr(me), (String) me.invoke(obj, null));
}
return viewMap;
}
/**
* 将方法名转换为属性名
* @param method
* @return
*/
private static String method2Attr(Method method){
StringBuilder builder = new StringBuilder();
return builder.append(new Character(method.getName().charAt(3)).toString().toLowerCase())
.append(method.getName().substring(4)).toString();
}
/**
* 调用setXXX给属性设置值
* @param params
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
private static void methodInvoke(Class clazz, Object obj,Map<String, String> params) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//将参数名转换为方法名
Map<String, String> methodMap = methodMap(params);
//将数据set到属性中
Iterator<Map.Entry<String, String>> it = methodMap.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = it.next();
Method method = clazz.getMethod(entry.getKey(), String.class);
method.invoke(obj, entry.getValue());
}
}
/**
* 将属性名转换为方法名之后放入到map中
* @param params
* @return
*/
@SuppressWarnings("rawtypes")
private static Map methodMap(Map<String, String> params){
Map<String, String> methodMap = new HashMap<String, String>();
Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = it.next();
String attrName = entry.getKey();
StringBuilder builder = new StringBuilder();
builder.append("set").append(new Character(attrName.charAt(0)).toString().toUpperCase()).append(attrName.substring(1));
methodMap.put(builder.toString(), entry.getValue());
}
return methodMap;
}
/**
* 遍历结点的属性找到类名
* @param attrList
* @return List<Attribute> attrList
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
private static void findClassNameByAttr(Element node,String actionName) throws ClassNotFoundException{
if(!node.attributes().isEmpty())
For2attr(actionName, node);
List<Element> listElement = node.elements();
for(Element e : listElement)
findClassNameByAttr(e, actionName);
if(resultStatic != null)
return;
}
/**
* 遍历属性找到类名
* @param actionName
* @param findAction
* @param node
*/
private static void For2attr(String actionName, Element node){
boolean findAction = false;
for(Attribute attribute : (List<Attribute>)node.attributes()){
if(actionName.equals(attribute.getValue())){
findAction = true;
break;
}
}
for(Attribute attribute : (List<Attribute>)node.attributes()){
if(findAction == true && "class".equals(attribute.getName())){
resultStatic = attribute.getValue();
return;
}
}
}
}