项目需求:
*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中的 配置,以及execute的返回值, 确定哪一个jsp,
放到View对象的jsp字段中。*
在项目开始之前,我们先编写xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<struts>
<action name="login" class="com.coderising.litestruts.LoginAction">
<result name="success">/jsp/homepage.jsp</result>
<result name="fail">/jsp/showLogin.jsp</result>
</action>
<action name="logout" class="com.coderising.litestruts.LogoutAction">
<result name="success">/jsp/welcome.jsp</result>
<result name="error">/jsp/error.jsp</result>
</action>
</struts>
得到xml文件,我们需要做的是先解析xml,这样的话,根据TDD思想,我们先编写解析XML的Configuration类,在编写工具类之前,我们可以把测试这个类的类第一个方法编写出来
Configuration cfg = new Configuration("struts.xml");
public void testGetClassName() {
String clzName = cfg.getClassName("login");
Assert.assertEquals("com.coderising.litestruts.LoginAction", clzName);
clzName = cfg.getClassName("logout");
Assert.assertEquals("com.coderising.litestruts.LogoutAction", clzName);
}
编写这个类的方法目的就是判断我们编出的Configuration类是否能帮我们找到对应的类。接下来编写第二个方法,及这个方法是测试能否返回想对应的jsp
public void testGetResultView(){
String jsp = cfg.getResultView("login","success");
Assert.assertEquals("/jsp/homepage.jsp", jsp);
jsp = cfg.getResultView("login","fail");
Assert.assertEquals("/jsp/showLogin.jsp", jsp);
jsp = cfg.getResultView("logout","success");
Assert.assertEquals("/jsp/welcome.jsp", jsp);
jsp = cfg.getResultView("logout","error");
Assert.assertEquals("/jsp/error.jsp", jsp);
}
如果能实现这两个测试用例,那么我们编写方法就能实现我们的要求。我们先编写解析XML文件的方法,通过传入的值,对应XML来确定我们需要那个类。
方法如下:
package com.coderising.litestruts;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
//开始运用到反射的技术
public class Configuration {
//先定义一个集合,用于存放子元素以及子元素下二级元素的构造器(内部有二级元素的信息)
Map<String,ActionConfig> actions = new HashMap<>();
public Configuration(String fileName) {
//获得包名,把包名置换成路径
String packageName = this.getClass().getPackage().getName();
packageName = packageName.replace('.', '/');
//将文件路径传入输入流
InputStream is = this.getClass().getResourceAsStream("/" + packageName + "/" + fileName);
//解析这个文件
parseXML(is);
try {
is.close();
} catch (IOException e) {
throw new ConfigurationException(e);
}
}
private void parseXML(InputStream is){
//表示使用的是默认的解析器
SAXBuilder builder = new SAXBuilder();
try {
//得到Document,我们以后要进行的所有操作都是对这个Document操作的
Document doc = builder.build(is);
//得到根元素
Element root = doc.getRootElement();
//遍历子元素
for(Element actionElement : root.getChildren("action")){
String actionName = actionElement.getAttributeValue("name");
String clzName = actionElement.getAttributeValue("class");
//建立一个构造器,用于存放子元素下二级元素XML的数据
ActionConfig ac = new ActionConfig(actionName, clzName);
//遍历二级子元素
for(Element resultElement : actionElement.getChildren("result")){
String resultName = resultElement.getAttributeValue("name");
String viewName = resultElement.getText().trim();
//在建好的构造器里加入子元素内的数据
ac.addViewResult(resultName, viewName);
}
this.actions.put(actionName, ac);
}
} catch (JDOMException e) {
throw new ConfigurationException(e);
} catch (IOException e) {
throw new ConfigurationException(e);
}
}
public String getClassName(String action) {
ActionConfig ac = this.actions.get(action);
if(ac == null){
return null;
}
return ac.getClassName();
}
public String getResultView(String action, String resultName) {
ActionConfig ac = this.actions.get(action);
if(ac == null){
return null;
}
return ac.getViewName(resultName);
}
//存放XML子元素的构造器,对方堆放内部所有的子节点的信息
//关键就在于建造这个构造器,这个构造器用于封装我们所需要的xml中的所有信息
//所有获取xml的信息都是先实例化这个构造器
private static class ActionConfig{
String name;
String clzName;
Map<String,String> viewResult = new HashMap<>();
public ActionConfig(String actionName, String clzName) {
this.name = actionName;
this.clzName = clzName;
}
public String getClassName(){
return clzName;
}
public void addViewResult(String name, String viewName){
viewResult.put(name, viewName);
}
public String getViewName(String resultName){
//根据key找到对应的value
return viewResult.get(resultName);
}
}
}