1.先建立实体类(实体类属性和xml标签属性一致)
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config[
<!ELEMENT config (action*)>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action
path CDATA #REQUIRED
type CDATA #REQUIRED
>
<!ATTLIST forward
name CDATA #REQUIRED
path CDATA #REQUIRED
redirect (true|false) "false"
>
]>
<config>
<action path="/studentAction" type="org.lisen.mvc.action.StudentAction">
<forward name="students" path="/students/studentList.jsp" redirect="false"/>
</action>
</config>
关系:config>action>forward
根据关系,根元素config拿到action,再通过action拿到forward
可以看出我们需要三个实体类
config实体类:
定义map集合是为了更好的找到值,键和值是对应的
(1)定义一个map集合map<String,下个节点>,这样定义可以满足节点间的关系
(2)定义put方法传入下个节点,判断path不重复,重复则抛异常,再加入map集合
(3)定义find方法传入一个键,获取下一个节点,先判断map集合内是否存在,存在抛异常,通过键找到下一个节点,返回一个action
public class ConfigModel {
private Map<String ,ActionModel> map=new HashMap();
public void put(ActionModel action) {
if(map.containsKey(action.getPath())) {//判断是否包含,因为path属性不能重复
throw new ActionDuplicateDefinitionException("Action path="+action.getPath()+"duplicate definition");//直接抛运行时异常
}
map.put(action.getPath(), action);
}
public ActionModel find(String path) {//通过path找actionmodel
if(!map.containsKey(path)) {
throw new ActionNotFoundException("Action path="+path+"no found");
}
return map.get(path);//get()返回指定键对应的值
}
}
自定义异常
自定义异常类名最重要,名字为抛异常的原因,继承runtimeexception(运行时异常)。
重写三个方法,一个无参继承父类,第二个传一个参(String)继承父类,第三个传两个参(String,Throwable)继承父类
public class ActionDuplicateDefinitionException extends RuntimeException{
public ActionDuplicateDefinitionException() {
super();
}
public ActionDuplicateDefinitionException(String msg) {
super(msg);
}
public ActionDuplicateDefinitionException(String msg,Throwable t) {
super(msg,t);
}
}
Action实体类
public class ActionModel {
private String path;
private String type;
private Map<String, ForwardModel> map=new HashMap();
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getType() {
return type;
}
@Override
public String toString() {
return "ActionModel [path=" + path + ", type=" + type + ", map=" + map + "]";
}
public void setType(String type) {
this.type = type;
}
public void put(ForwardModel forward) {
if(map.containsKey(forward.getName())) {
throw new ForwardDuplicateDefinitionException("forward name"+forward.getName()+"duplicate definition");
}
map.put(forward.getName(),forward);
}
public ForwardModel find(String name) {
if(!map.containsKey(name)) {
throw new ForwardNotFoundException("forward name"+name+"not found");
}
return map.get(name);
}
}
Forward实体类
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;
}
@Override
public String toString() {
return "ForwardModel [name=" + name + ", path=" + path + ", redirect=" + redirect + "]";
}
public boolean isRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
public void setRedirect(String redirect) {
this.redirect = Boolean.valueOf(redirect);
}
}
其他实体类的自定义异常,只需要改类名即可
ConfigModelFactory:相当于一个工厂,在这个工厂里,xml只被解析一次,那么就需要单例模式
给类加上final。
1.一个私有构造
2.生成一个实例(configmodel)
3.需要一个static块(里面内容为xml的解析,前面博客有xml的解析)
public final class ConfigModelFactory{
//单例模式
private ConfigModelFactory() {
}
private static ConfigModel config=new ConfigModel();
//读取config.xml中的数据,填充到模型
static {
try {
InputStream is = ConfigModelFactory.class.getResourceAsStream("/config.xml");//要加/在同一个包下则不需要
SAXReader reader=new SAXReader();//用来读取
Document doc = reader.read(is);//相当于一个文档
Element e = doc.getRootElement();//获得根元素,也就是开头的第一个标签
List<Element> actions = e.selectNodes("action");//获得根路径下的action,element强转为元素,不要加/,加了表示从根路径开始
for (Element e2 : actions) {
String path = e2.attributeValue("path");//拿标签下属性的内容
String type = e2.attributeValue("type");
ActionModel action=new ActionModel();
action.setPath(path);
action.setType(type);
List<Element> forward = e2.selectNodes("forward");//拿e2下面的子节点
for (Element e3 : forward) {
String name = e3.attributeValue("name");
String fpath = e3.attributeValue("path");
String red = e3.attributeValue("redirect");
ForwardModel forward1=new ForwardModel();
forward1.setName(name);
forward1.setPath(fpath);
forward1.setRedirect(red);
action.put(forward1);//建立关系
//Boolean.valueOf(red);类型转换转换成Boolean类型
}
config.put(action);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static ConfigModel getConfig() {
return config;
}
//测试
public static void main(String[] args) {
ConfigModel config2 = ConfigModelFactory.getConfig();//拿到config
ActionModel find = config2.find("/studentAction");//拿到action
System.out.println(find);
ForwardModel forward=find.find("students");//拿到forward
System.out.println(forward);
}
}
一步步下来一个xml模型就差不多完成了。
这篇博客介绍了如何基于XML配置文件创建实体模型,包括ConfigModel、ActionModel和ForwardModel三个实体类,用于表示配置文件中的层级关系。通过单例模式的ConfigModelFactory,实现了XML文件的一次性解析并存储数据。此外,还定义了自定义异常来处理重复定义的情况,并提供了查找操作。整个过程展示了Java中XML解析和数据结构的应用。

676

被折叠的 条评论
为什么被折叠?



