package com.leijing.coderising.litestruts;
import java.io.InputStream;
import java.lang.reflect.Field;
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.Element;
import org.dom4j.io.SAXReader;
/**
* @Description: 解析Struts文件、处理action请求
* @author: leijing
* @date: 2017年3月3日 下午3:03:38
*/
public class Struts {
private static String STRUTS_XML = "struts.xml";
private static Map<String,String> actionsMap = new HashMap<String, String>();
private static Map<String,String> resultMap = new HashMap<String, String>();
private Struts(){
try {
init();
} catch (Exception e) {
System.out.println("Struts init error:"+e.getMessage());
}
}
/**
* @Description: 确保配置的是需要的节点
* @param xmlName
* @param name
* @return: void
* @author: leijing
* @date: 2017年3月3日 下午3:20:31
*/
private void checkTag(String xmlName , String name) throws Exception{
if(xmlName == null || name == null || !xmlName.equals(name)){
throw new Exception("xml parse error,"+xmlName+"can not be parsed,"+name+" is required!");
}
}
private void init() throws Exception{
InputStream inputStream = this.getClass().getResourceAsStream(STRUTS_XML);
SAXReader reader = new SAXReader();//创建SAXReader对象
Document document = reader.read(inputStream); //用SAXReader对象加载配置文件得到Document对象
Element struts = document.getRootElement();//得到根节点
checkTag(struts.getName(), "struts");
List<Element> actions = struts.elements();//得到所有action节点
for(Iterator<Element> it = actions.iterator() ; it.hasNext();){//遍历action节点
Element action = (Element) it.next();
checkTag(action.getName(), "action");
Attribute actionName = action.attribute("name");
Attribute actionClazz = action.attribute("class");
actionsMap.put(actionName.getText(), actionClazz.getText());
System.out.println("add to actionsMap:"+actionName.getText()+":"+actionClazz.getText());
List<Element> results = action.elements();//得到配置的result节点
for(Iterator<Element> rit = results.iterator() ; rit.hasNext();){//遍历result节点
Element result = (Element) rit.next();
checkTag(result.getName(), "result");
Attribute resultName = result.attribute("name");
resultMap.put(actionName.getText()+"_"+resultName.getText() , result.getData().toString());
System.out.println("add to resultMap: result:"+resultName.getText()+",url:"+result.getData());
}
}
}
public static View runAction(String actionName, Map<String,String> parameters) throws Exception {
/*
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字段中。
*/
if(!actionsMap.containsKey(actionName)){
throw new Exception("action "+actionName+"not found!");
}
String className = actionsMap.get(actionName);
Class<?> clazz = Class.forName(className);
Object obj = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if(parameters.containsKey(field.getName())){
field.set(obj, parameters.get(field.getName()));
}
}
Method execute = clazz.getDeclaredMethod("execute");
String result = (String) execute.invoke(obj, new Object[]{});
String jsp = resultMap.get(actionName+"_"+result);
if(null == jsp){
throw new Exception("jsp config at action:"+actionName +",result:"+ result+" not found !");
}
Field message = clazz.getDeclaredField("message");
message.setAccessible(true);
View view = new View();
view.setJsp(jsp);
Map<String,Object> params = new HashMap<String,Object>();
params.put("message", message.get(obj));
view.setParameters(params);
return view;
}
public static Struts getInstance(){
return StrutsHoldler.INSTANCE;
}
private static class StrutsHoldler{
private static Struts INSTANCE = new Struts();//struts对象应该是单例的
}
}