why需要xml建模?
1.1代码封装,提高了代码的复用性.
1.2 还可以放入静态代码块static{}
提高性能,xml解析的过程只会有一次了.
1.3 xml建模主要针对它的第二解析变得高效开发,减少代码量,并且可以针对不同的需求.
就是将指定的xml字符串当作对象来操作如果说当对一个指定的xml格式字符 串完成了建模操作,
好处在于,只需要调用指定的方法就可以完成预定的字符串获取;
建模的思路
1、分析需要被建模的文件中有那几个对象
2、每个对象拥有的行为以及属性
3、定义对象从小到大(从里到外)从小到大:forward>action>config
4、通过23种的设计模式中的工厂模式,解析xml生产出指定对象
建模案列
3.1 分析.xml文件的标签节点属性对象
3.2 图为config.xml
文件
3.3 分析:
config对象->config类 它没有属性,其下的action对象标签 通过path属性找到action对象的行为
action类 它的属性有path属性和type属性,通过Forward对象的name属性找到Forward对象的行为
最后还有个Forward类 它的属性有name,path,redirect属性,没有行为
3. 分析后需要建的类. (ConfigModel)( ActionModel) (ForwardModel)(ConfigModelFactory)
3.4 建模分两步:
1、以面向对象的编程思想,描述xml资源文件
2、将xml文件中内容封装进model实体对象。
3.5 建模的过程?
- 获取到资源文件进行加载
- 分析xml标签,将其看成对象,分析该对象的属性及行为
- 解析出xml资源文件中的所有类容
- 建模的核心部分(将xml资源文件中的内容填充到各个标签对应的模型 对象ActionModel)
- 注意将子模型对象填充到父模型中
6.如果属性为String类型,子元素标签则是map的值,子元素标签的唯一标识则为map的值
3.6 建模需要的两个jar包
3.7、然后接下来就将xml文件中内容封装进model实体对象。
ForwardModel类
:
package com.houzhihong.model;
/**
*
* @author houzhihong
*
* 2020年5月23日
*/
public class ForwardModel {
private String name;
private String path;
private boolean redirect;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public boolean getRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
}
ActionModel类
:
package com.houzhihong.model;
/**
*
* @author houzhihong
*
* 2020年5月23日
*/
import java.util.HashMap;
import java.util.Map;
public class ActionModel {
private String path;
private String type;
private Map<String, ForwardModel> foMap = new HashMap<>();
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
// 两个行为.
/**
* 将指定的forwardModel压入当前actionModel对象中 把<forward/>放入<action/>标签里面去
*
* @param forwardModel
*/
public void push(ForwardModel forwardModel) {
foMap.put(forwardModel.getName(), forwardModel);
}
public ForwardModel pop(String name) {
// 通过forward对象name属性找到对象的forward对象的行为
return foMap.get(name);
}
}
ConfigModel类
:
package com.houzhihong.model;
/**
*
* @author houzhihong
*
* 2020年5月23日
*/
import java.util.HashMap;
import java.util.Map;
public class ConfigModel {
private Map<String, ActionModel> acMap = new HashMap<String, ActionModel>();
/**
* 将指定的actionModel压入当前ConfigModel对象中 把<action/>放入<config/>标签里面去
*
* @param actionModel
*/
public void push(ActionModel actionModel) {
acMap.put(actionModel.getPath(), actionModel);
}
public ActionModel pop(String path) {
// 通过action对象path属性找到对象的action对象的行为
return acMap.get(path);
}
}
然后在建立一个工厂类来自动解析xml文件:
工厂模式解决问题,将代码封装,提高代码的复用性
ConfigModelFactory类
:
package com.houzhihong.model;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 23种设计模式之工厂模式
*
* 工厂模式解决问题,将代码封装,提高代码的复用性 类比去零食的获取方式(一种是去商场直接购买,第二种是自己用原材料制作)
*
* @author houzhihong
*
* 2020年5月23日 一般工厂类一定会有一个方法,就是生产指定模型对象的方法, build newInstance 开源框架常见的方法
*
* 注意点:一般在工厂类中会有两个以上的构建方法, 一个是默认框架路径的模型对象构建方法, 还有一个是动态读取任意位置下的框架配置文件
*/
public class ConfigModelFactory {
/**
* 通过资源文件构建对应的模型对象
*
* @param path
* 具体的资源文件路径
* @return
* @throws Exception
*/
public static ConfigModel build(String path) throws Exception {
// path=/config.xml
InputStream in = ConfigModelFactory.class.getResourceAsStream(path);
SAXReader reader = new SAXReader();
// config.xml里面的内容
Document doc = reader.read(in);
// 然后把内容填充到configModel对象中(doc.asXML填充到configModel)
// 放在循环外边减少对jvm虚拟机内存空间资源
ConfigModel configModel = new ConfigModel();
ActionModel actionModel = null;
ForwardModel forwardModel = null;
List<Element> actionEles = doc.selectNodes("/config/action");
for (Element actionEle : actionEles) {
actionModel = new ActionModel();
actionModel.setPath(actionEle.attributeValue("path"));
actionModel.setType(actionEle.attributeValue("type"));
// 给actionModel中放入ForwardModel对象
// 拿到Forward标签内容
List<Element> forwardEles = actionEle.selectNodes("forward");
for (Element forwardEle : forwardEles) {
forwardModel = new ForwardModel();
forwardModel.setName(forwardEle.attributeValue("name"));
forwardModel.setPath(forwardEle.attributeValue("path"));
// redirect属性是boolean类型的
// 只有config.xml中redirect属性值填写了false,它才代表转发
forwardModel.setRedirect(!"false".equals(forwardEle.attributeValue("redirect")));
actionModel.push(forwardModel);
}
configModel.push(actionModel);
}
return configModel;
}
// 默认框架路径的模型对象构建方法,
public static ConfigModel build() throws Exception {
return build("/config.xml");
}
public static void main(String[] args) throws Exception {
ConfigModel model = ConfigModelFactory.build();
ActionModel actionModel = model.pop("/loginAction");
System.out.println(actionModel.getType());
// ActionModel actionModel = model.pop("/regAction");
// System.out.println(actionModel.getType());
// 获取loginAction下的success结果码对应的页面/main.jsp
// ActionModel actionModel = model.pop("/loginAction");
// ForwardModel forwardModel = actionModel.pop("success");
// System.out.println(forwardModel.getPath());
}
}
3.8 最后附上运行效果图:
<action path="/loginAction" type="test.LoginAction">
通过action对象的path拿到对应的type对象test.loginAction