xml建模

这篇博客介绍了如何基于XML配置文件创建实体模型,包括ConfigModel、ActionModel和ForwardModel三个实体类,用于表示配置文件中的层级关系。通过单例模式的ConfigModelFactory,实现了XML文件的一次性解析并存储数据。此外,还定义了自定义异常来处理重复定义的情况,并提供了查找操作。整个过程展示了Java中XML解析和数据结构的应用。

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模型就差不多完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值