前言
在上一个寒假,我学会了自定义标签和解析标签,时隔近11个月,我又拿起了他,之前的想法又重新在脑海中浮现--想自己做一个类似于springMVC的框架。虽然没做成,但是这个让我认识到了自己的不足啊!!!
开搞
1.idea中创建一个普通的java项目
2.编写dtd文件
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT users (user*)>
<!ELEMENT user (property*)>
<!ATTLIST user
id ID #REQUIRED
class CDATA #REQUIRED
scope (singlton|prototypr|session|request) "singlton"
>
<!--
CDATA 表示可以放入文本
ID 表示属性的值,不能重复,同时不要用数字开头.
IDREF/IDREFS 当一个元素的属性值,需要去引用另外一个ID ,则使用IDREF,如果希望引用多个,则使用IDREFS,请用空格隔开.
Enumerated 表示属性的值,只能是例举出了-->
<!--id属性值,类型是ID,限制是必须写-->
<!--singlton单例 prototypr原型 session会话 request请求-->
<!ELEMENT property (#PCDATA)>
<!--CDATA是文本类型 , #PCDATA是段落类型-->
<!--
CDATA 的意思是字符数据(character data)
PCDATA 的意思是被解析的字符数据(parsed character data)。
PDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
-->
<!--#IMPLIED可选类型-->
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED
type (int|float|double|string|long) #IMPLIED
>
3.编写对应的.xml文件(引入对应的dtd可以有提示)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users SYSTEM "D:\idea\idea-workspace\springmvc_project\src\main\resources\users.dtd">
<users xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<user id="id1" class="org.lyf.bean.User" scope="singlton">
<property name="id" value="1001" type="int"/>/
<property name="username" value="张三" type="string"/>
<property name="password" value="123456" type="string"/>
<property name="phone" value="15993596768" type="string"/>
<property name="email" value="11111@qq.com" type="string"/>
</user>
<user id="id2" class="org.lyf.bean.User" scope="singlton">
<property name="id" value="1002" type="int"/>/
<property name="username" value="李四" type="string"/>
<property name="password" value="654321" type="string"/>
<property name="phone" value="12589658745" type="string"/>
<property name="email" value="22222@qq.com" type="string"/>
</user>
</users>
4.编写实体类
public class User {
private int id;
private String username;
private String password;
private String phone;
private String email;
//get,set和toString
}
5.编写xml属性对应的实体类,用于实体的封装
public class UserInfo {
private String id;
private String clazz;
private String scope;
private List<PropInfo> propInfos;
//get,set和toString
}
public class PropInfo {
private String name;
private String value;
private String type;
//get,set和toString
}
6.编写xml的解析类
public class Factorys {
private HashMap<String, UserInfo> userInfoHashMap;
private static ArrayList<String> list = new ArrayList<>();//用于存储user标签的id
public Factorys(String xmlPath) {//获取文件路径
try {
if (xmlPath.equals("") || !new File(xmlPath).exists()) {//如果为空或不存在就返回空
return;
}
SAXParserFactory factory = SAXParserFactory.newInstance();//.创建SAXParser解析器对象
SAXParser saxParser = factory.newSAXParser();//.创建SAXParser解析器类对象
saxParser.parse(new FileInputStream(xmlPath), new DefaultHandler() {//DefaultHandler默认的处理器
UserInfo userInfo;
//xml文档开始解析
public void startDocument() {
userInfoHashMap = new HashMap<>();
}
//标签开始解析
public void startElement(String uri, String localName, String qName, Attributes attr) {
if ("user".equals(qName)) {
userInfo = new UserInfo();
userInfo.setId(attr.getValue("id"));
userInfo.setClazz(attr.getValue("class"));
userInfo.setScope(attr.getValue("scope"));
userInfo.setPropInfos(new ArrayList<>());
} else if ("property".equals(qName)) {
userInfo.getPropInfos().add(new PropInfo(attr.getValue("name"), attr.getValue("value"), attr.getValue("type")));
}
}
//标签结束
public void endElement(String uri, String localName, String qName) {
if ("user".equals(qName)) {
userInfoHashMap.put(userInfo.getId(), userInfo);
list.add(userInfo.getId());
userInfo = null;
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public ArrayList<String> getList(){//返回id集合
return list;
}
public Factory newFactory() {//返回一个新创建的类对象
return new Factory();
}
public class Factory {
public Object getUser(String id) {//获取id
UserInfo userInfo = userInfoHashMap.get(id);//通过id获取map集合里的用户对象
if (userInfo == null) {
return null;
}
try {
Class<?> userClass = Class.forName(userInfo.getClazz());//new出来一个动态对象
Object newInstance = userClass.newInstance();
for (PropInfo propInfo : userInfo.getPropInfos()) {
Field declaredField = userClass.getDeclaredField(propInfo.getName());
declaredField.setAccessible(true);
if (propInfo.getType().equals("int")) {
declaredField.set(newInstance, Integer.parseInt(propInfo.getValue()));
} else {
declaredField.set(newInstance, propInfo.getValue());
}
}
return newInstance;//返回对象
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
}
7.编写测试类进行测试
public class FactoryTest {
public static void main(String[] args) {
String file = Objects.requireNonNull(FactoryTest.class.getClassLoader().getResource("user.xml")).getFile();//类加载器
Factorys factorys = new Factorys(file);
Factorys.Factory factory = factorys.newFactory();
factorys.getList().forEach((item) -> {
User id1 = (User) factory.getUser(item);
System.out.println(id1);
});
}
}