package com.coderising.litestruts;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
@SuppressWarnings("unchecked")
public class Struts {
public static View runAction(String actionName, Map<String,String> parameters) {
if(actionName == null || actionName.trim().equals("")){
throw new RuntimeException("传入的actionName不能为null或者空");
}
// 0. 读取配置文件struts.xml ok
URL resource = Struts.class.getResource("/com/coderising/litestruts");
String path = "";
try {
path = URLDecoder.decode(resource.getPath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Map<String,Map<String, Object>> actionMap = xmlParse(path + File.separator + "struts.xml");
// 找到访问的action通过actionName
Map<String,Object> action = findAction(actionName,actionMap);
//1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
//据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是
//("name"="test" , "password"="1234") ,
//那就应该调用 setName和setPassword方法
// 实例化对象
String className = (String) action.get("class");
Class<?> clazz = getActionClassByClassName(className);
Object actionObject = buildActionObject(clazz,parameters);
//2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success"
// 执行访问的方法
String result = (String) executeAccessMethod(actionObject,clazz,"execute");
//3. 通过反射找到对象的所有getter方法(例如 getMessage),
//通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} ,
//放到View对象的parameters
Map<String,Object> parameterMap = getActionObjectParameters(actionObject,clazz);
//4. 根据struts.xml中的 <result> 配置,以及execute的返回值, 确定哪一个jsp,
//放到View对象的jsp字段中。
String jsp = getViewPath(action,result);
View v = buildView(jsp,parameterMap);
return v;
}
private static Class<?> getActionClassByClassName(String className) {
if(className == null || className.trim().equals("")){
throw new RuntimeException("没有配置action的class属性");
}
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取配置文件中视图的路径
* @param action
* @param result
* @return
*/
private static String getViewPath(Map<String, Object> action, String result) {
if(result != null && !result.trim().equals("")){
List<Map<String,Object>> resultList = (List<Map<String, Object>>) action.get("childElementList");
if(resultList != null && !resultList.isEmpty()){
for (Map<String, Object> map : resultList) {
String readResult = (String) map.get("name");
if(result.equals(readResult)){
Object jsp = map.get("text");
if(jsp == null){
throw new RuntimeException("未找到与返回结果[" + result + "]之对应的视图");
}
return (String) jsp;
}
}
}
}
return null;
}
/**
* 执行访问的方法
* @param actionObject 访问的action实例化的对象
* @param clazz 访问的action Class
* @param methodName 访问的方法名称
* @return 方法的执行结果
*/
private static Object executeAccessMethod(Object actionObject, Class<?> clazz,String methodName) {
try {
Method method = clazz.getMethod(methodName);
return method.invoke(actionObject);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* 执行action对象的getter方法,将执行结果放入map中
* @param actionObject 访问的action实例化的对象
* @param clazz 访问的action Class
* @return
*/
private static Map<String, Object> getActionObjectParameters(Object actionObject, Class<?> clazz) {
Map<String, Object> parameterMap = new HashMap<>();
Object result = null;
Method[] declaredMethods = clazz.getDeclaredMethods();
Class<?>[] parameterTypes = null;
if (declaredMethods != null && declaredMethods.length > 0) {
try {
for (Method method : declaredMethods) {
if (isGetMethod(method)) {
parameterTypes = method.getParameterTypes();
result = method.invoke(actionObject, (Object[])parameterTypes);
String methodName = method.getName();
// getMessage 截取 M(转小写) + 截取essage
String subMethodName = Character.toLowerCase(methodName.charAt(3))
+ methodName.substring(4, methodName.length());
parameterMap.put(subMethodName, result);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return parameterMap;
}
/**
* 建立action对象
* @param clazz
* @param parameters 传过来的参数
* @return
*/
private static Object buildActionObject(@SuppressWarnings("rawtypes") Class clazz, Map<String,String> parameters) {
Object actionObj = null;
try {
actionObj = clazz.newInstance();
// 给action对象的属性设置传过来的参数值
setProperties(clazz, actionObj, parameters);
return actionObj;
} catch (Exception e) {
e.printStackTrace();
}
if(actionObj == null){
throw new RuntimeException("无法实例化action:");
}
return actionObj;
}
/**
* 建立View对象
* @param jsp
* @param parameters
* @return
*/
private static View buildView(String jsp,Map<String,Object> parameters) {
View v = new View();
v.setJsp(jsp);
v.setParameters(parameters);
return v;
}
/**
* 通过actionName在action列表中查找对应的action(map)
* @param actionName
* @param actionMap action列表
* @return
*/
private static Map<String, Object> findAction(String actionName, Map<String, Map<String, Object>> actionMap) {
Map<String, Object> action = (actionMap != null && !actionMap.isEmpty()) ? actionMap.get(actionName) : null;
if(action == null){
throw new RuntimeException("访问的action[" + actionName + "]不存在");
}
return action;
}
/**
* 是否是getter方法
* @param method2
* @return
*/
private static boolean isGetMethod(Method method2) {
if(method2.getName().startsWith("get")){
return true;
}
return false;
}
/**
* 为Action对象设置属性,也就是执行与参数对应的setter方法
* @param clazz
* @param actionObj
* @param parameters 参数
* @throws NoSuchMethodException
* @throws SecurityException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private static void setProperties(@SuppressWarnings("rawtypes") Class clazz, Object actionObj, Map<String, String> parameters) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if(parameters != null && !parameters.isEmpty()){
Set<Entry<String, String>> entrySet = parameters.entrySet();
for (Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
Method method = clazz.getMethod("set" + Character.toUpperCase(key.charAt(0)) + key.substring(1, key.length()),String.class);
method.invoke(actionObj, value);
}
}
}
/**
* 解析xml配置文件
* @param xmlFilePath
* @return
*/
private static Map<String,Map<String, Object>> xmlParse(String xmlFilePath) {
File file = new File(xmlFilePath);
SAXReader saxReader = new SAXReader();
Map<String,Map<String, Object>> actionMap = new HashMap<>();
try {
Document document = saxReader.read(file);
Element rootElement = document.getRootElement();
actionMap = readActionElement(rootElement);
return actionMap;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
/**
* 读取action节点元素
* @param rootElement
* @return
*/
private static Map<String, Map<String, Object>> readActionElement(Element rootElement) {
// 存储所有action的信息
Map<String, Map<String, Object>> actionMap = new HashMap<>();
for (Iterator<Element> i = rootElement.elementIterator();i.hasNext();) {
Element element = i.next();
Map<String, Object> action = readElement(element );
// 设置actionMap key[action的name] value[action map]
actionMap.put((String) action.get("name"), action);
}
return actionMap;
}
/**
* 读取元素信息
* @param element
* @return
*/
private static Map<String, Object> readElement(Element element) {
// 读属性
Map<String, Object> map = readAttribute(element);
String text = readText(element);
map.put("text", text);
List<Map<String, Object>> childElementList = new ArrayList<>();
// 查找子元素
for(Iterator<Element> iterator = element.elementIterator();iterator.hasNext();){
childElementList.add(readElement(iterator.next()));
}
if(childElementList != null && !childElementList.isEmpty()){
map.put("childElementList", childElementList);
}
return map;
}
/**
* 读取节点的text "<e>text</e>"
* @param element
* @return
*/
private static String readText(Element element) {
return element.getText();
}
/**
* 读取节点的属性值
* @param element
* @return map key:属性名称 value:属性值
*/
private static Map<String, Object> readAttribute(Element element) {
Map<String,Object> attrMap = new HashMap<>();
for (Iterator<Attribute> a = element.attributeIterator();a.hasNext();) {
Attribute attr = a.next();
attrMap.put(attr.getName(), attr.getData());
}
return attrMap;
}
}