实现简易的Struts.xml解析[内含反射的理解]
来源:互联网 发布:高校网络舆情工作方案 编辑:程序博客网 时间:2024/06/04 22:12
大道为简,我们直接上需求和代码。
首先我们有两个文件一个是View:
private String jsp;
}
}
里面有两个属性,最重要的是那个parameters是一个Map,我们后期需要传值进入。
第二个就是需要我们解析的Struts.xml:
</struts>
好了,现在我们上需求:
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字段中。
于是我们创建了StrutsTest类来写代码:
public class Struts {
public static View runAction(String actionName, Map<String,String> parameters){
View v = new View();//定义一个view对象,用于对象的返回
//1.创建一个DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//2.创建一个DocumentBuilder对象
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
//3.通过documentBuilder对象加载xml文件
Document document = null;
try {
document = db.parse("src/com/basic/litestruts/struts.xml");//parse去解析struts文件
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
NodeList nodeList = document.getElementsByTagName("action");//获取为action的节点集合
for(int i = 0;i<nodeList.getLength();i++){
Node item = nodeList.item(i);//获取每一个action节点
NamedNodeMap attrs = item.getAttributes();//获取action节点下的所有属性
Node currentAction = item;//存放当前action节点
//根据需求在name为login时获得到他的class名
if(attrs.getNamedItem("name").getNodeValue().equals(actionName)){
String className = attrs.getNamedItem("class").getNodeValue();//获得login对应的类路径
try {
//开始反射
Class<?> fn = Class.forName(className);
Object obj = fn.newInstance();//反射出来new的对象
Method methodSetName = fn.getMethod("setName", String.class);//获得当前对象的方法,参数传的是方法名和参数类型
Method methodSetPwd = fn.getMethod("setPassword", String.class);
for(Map.Entry<String, String> m :parameters.entrySet()){
if(m.getKey().equals("name")){
methodSetName.invoke(obj, m.getValue());//触发方法,参数是当前反射出来的对象,需要set方法的值
}
if(m.getKey().equals("password")){
methodSetPwd.invoke(obj, m.getValue());
}
}
/**
* 调用excute方法返回success
*/
Object returnValue = fn.getMethod("execute", null).invoke(obj, null);
System.out.println(returnValue.toString());//打印返回值
/**
* 通过反射找到所有getter方法
*/
//先获得所有属性
Field[] fd = fn.getDeclaredFields();
Map newMap = new HashMap();
for(int m = 0;m<fd.length;m++){
String fieldName = fd[m].getName();
String methodName = "get"+init(fieldName);//将所有属性名装饰城get+属性名形式[init方法在下面]
Method method = fn.getMethod(methodName, null);
System.out.println(method);//遍历出的每一个getter方法
String invoke = (String)method.invoke(obj, null);
newMap.put(fieldName, invoke);
}
v.setParameters(newMap);
System.out.println(v.getParameters());
//fn.getMethod("get"+, parameterTypes)
/**
* 根据struts.xml中的 <result> 配置,
* 以及execute的返回值, 确定哪一个jsp,
放到View对象的jsp字段中
*/
NodeList childNodes = currentAction.getChildNodes();//将action节点下的所有子节点获取出来
for(int q = 0;q<childNodes.getLength();q++){
NamedNodeMap attributes = childNodes.item(q).getAttributes();//每个子节点所有属性
if(attributes!=null){//两个result节点的属性
for(int e = 0;e<attributes.getLength();e++){
if(attributes.item(e).getNodeValue().equals(returnValue)){
v.setJsp(childNodes.item(q).getTextContent());//在view中塞入success对应的文章内容
}
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
return v;
}
/**
* 将首字母大写,用于组成getter方法的方法名
* @param name
* @return
*/
private static String init(String name){
name = name.substring(0,1).toUpperCase()+name.substring(1);
return name;
}
}
好了,这里用的解析struts.xml主要是用的dom解析树。用到了documentBuilderFactory,创建一个DocumentBuilder,调用它的parse方法解析一个xml文件,返回一个document树形对象。后面就可以document.getElementsByTagName(填入你需要寻找的树形节点名称)。
基于用到了反射,我这里还是要给大家复习一下反射的原理:
我们正常开发状态中用反射的情况是少之又少,主要是那些框架中都给我们封装好了,我们直接照着在xml文件中写对应的格式就行了。为什么用到反射。【注:截取知乎上的一张图】
当我们用到一个对象时,比如person p = new Person();这时我们程序先跑起来,jvm飞起来,这段代码会被编译成.class文件
当我们这个Person类加载到方法区里面的时候,于是乎会创出person类的class对象到堆中。所以在jvm创建对象会先先检查类是否加载,再寻找类对应的class对象,如果加载完毕。开始分配内存进行初始化。代码走完之后jvm就关闭了。
但是我们经常在需求中会遇到,用不到的类不会加载到jvm中,比如说当我们person用完时突然又要用到monkey类,但是jvm已经在跑了,你不会和他说,兄弟,你先停一下让我new 一个猴子吧!所有反射的好处就是可以再运行期间根据包.类名来动态加载这个类然后为所欲为,想干嘛干嘛!
复习一下反射的基本调用方法【天地万物相反相成,反射既是通过对象找到类】:
首先获取类的三种方法:
//第一种方式:
Classc1 = Class.forName("Person");
//第二种方式:
Classc2 = Person.class;
//第三种方式:
Person= new Person();
Classc3 = e.getClass();
创建对象:
Classc1.newInstance();调用无参构造器
获取属性:
Field[] fs = Classc1.getDeclaredFields();
之后遍历它就可以获得各个属性名,然后调用他的getName和getType方法来获得类型和名称
这里有一点要注意:
使用.setAccessible(true); //使用反射机制可以打破封装性,意思是原来的是私有属性,我们可以获得到他的默认值并且可以修改,即使是final属性也可以!
- 实现简易的Struts.xml解析[内含反射的理解]
- XmlParser: 简易的 Xml 解析器的实现(一)
- XmlParser: 简易的 Xml 解析器的实现(二)
- XmlParser: 简易的 Xml 解析器的实现(三)
- 解析Xml的理解
- struts2--(4)---深入解析struts.xml配置的实现原理
- 深入解析struts.xml配置的实现原理
- 深入解析struts.xml配置的实现原理
- ajax的理解,xml解析
- struts 的digester类解析xml文件
- struts.xml文件的常用配置解析
- Tomcat服务器的模拟实现学习解析Http协议、反射、xml解析等
- 35-002-1 struts前期之 通过JAVA反射机制及XML配置文件解析自定义一个MVC的简单框架
- struts+SmartUpload实现的一个简易上传下载系统
- maven中使用dom4j解析、生成XML的简易方法
- 以SpringIoc的模拟实现来学习反射和xml解析
- SSH的简易理解
- antlr的简易理解
- php-fpm源码分析
- ajax传值到ASP.NET的aspx文件后台代码实现(VB)
- Top 10 Open Source Bug Tracking System系统
- Differences Between the NDB and InnoDB Storage Engines
- 《大型数据库作业2》客户端的配置与应用
- 实现简易的Struts.xml解析[内含反射的理解]
- mysql建立索引时中的length什么用
- 查询mysql中重复数据的方法
- Java解析Excel并把数据保存到数据库中
- EnumResourceNames枚举资源
- caffe学习笔记14-caffe可视化特征与权重
- linux cfs调度器_理论模型
- hiho一下 第140周-清理海报(DAG+dfs)
- IP头、TCP头、UDP头