分析xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>reg</servlet-name>
<servlet-class>servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/g</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>reg</servlet-name>
<url-pattern>/reg</url-pattern>
</servlet-mapping>
</web-app>
可以看到有servlet 和 servlet-mapping两个部分
servlet
1.servlet-name
2.servlet-class
servlet-mapping
1.servlet-name
2.url-pattern 有多个,所以在解析时应该用容器存储
按照xml内容,建立Servlet类和Mapping类,进行封装
特殊地,Mapping类不使用set方法存储pattern,而是写一个add方法将pattern放进容器当中。
public void addPattern(String pattern){
this.patterns.add(pattern);
}
主要的解析部分
固定套路来一波
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser=factory.newSAXParser();
WebHandler webHandler=new WebHandler();
parser.parse(Thread.currentThread().getContextClassLoader().
getResourceAsStream("servlet/web.xml"),webHandler);
解析
class WebHandler extends DefaultHandler {
private List<Servlet> servlets=null;
private List<Mapping>mappings=null;
private boolean isServlet;
private String tag;
Mapping mapping=null;
Servlet servlet=null;
@Override
public void startDocument() throws SAXException {
servlets=new ArrayList<>();
mappings=new ArrayList<>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equals("servlet")){
servlet=new Servlet();
isServlet=true;
} else if (qName.equals("servlet-mapping")){
mapping=new Mapping();
isServlet=false;
}
tag=qName;
}
@Override
public void characters(char[] ch, int start, int length) throws NullPointerException {
String contents=new String(ch,start,length).trim();
if(tag!=null) {
if (isServlet) {
if (tag.equals("servlet-name")) {
servlet.setName(contents);
} else if (tag.equals("servlet-class")) {
servlet.setClz(contents);
}
} else {
if (tag.equals("servlet-name")) {
mapping.setName(contents);
} else if (tag.equals("url-pattern")) {
mapping.addPattern(contents);
}
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equals("servlet")){
servlets.add(servlet);
}else if(qName.equals("servlet-mapping")){
mappings.add(mapping);
}
tag=null;
}
public List<Mapping> getMappings() {
return mappings;
}
public List<Servlet> getServlets() {
return servlets;
}
}
接收(固定套路下面)
List<Servlet> servlets=webHandler.getServlets();
List<Mapping>mappings=webHandler.getMappings();
以上步骤就已经将xml文件当中的数据提取到两个容器当中,弄个输出跑一下
for (Servlet servlet:servlets
) {
System.out.println(servlet.getName()+"-->"+servlet.getClz());
}
for (Mapping mapping:mappings
) {
for (String pattern:mapping.getPatterns()
) {
System.out.println(mapping.getName()+"-->"+pattern);
}
}
然后这个xml解析有什么特殊之处呢?解析的目的何在?
在地址后面加上/g或者是/login就可以找到login,加上/reg就可以找到reg,
然后reg或者login又可以找到他们对应的class,得到class就可以进行映射,剖析类。
总的来说就是通过url找到类进行映射。
写一个WebContext对两个容器进行数据处理,将两个容器传过去
WebContext context=new WebContext(servlets,mappings);
既然是对应寻找,就要用到Map
servlet
1.servlet-name
2.servlet-class
key servlet-name value servlet-class
servlet-mapping
1.servlet-name
2.url-pattern 有多个,所以在解析时应该用容器存储
key url-pattern value servlet-name
url找name,通过name找到class
处理数据的类是这样的
public class WebContext {
private List<Servlet> servlets;
private List<Mapping> mappings;
private Map<String ,String > servletMap=new HashMap<>();
private Map<String ,String >mappingMap=new HashMap<>();
public WebContext(List<Servlet> servlets, List<Mapping> mappings) {
this.servlets = servlets;
this.mappings = mappings;
for (Servlet servlet:servlets
) {
servletMap.put(servlet.getName(),servlet.getClz());
}
for (Mapping mapping:mappings
) {
for (String pattern:mapping.getPatterns()
) {
mappingMap.put(pattern,mapping.getName());
}
}
}
//这样通过传入url就返回了class
public String getClz(String url){
String name=mappingMap.get(url);
return servletMap.get(name);
}
public WebContext() {
}
}
现在解析的方法已经写出来了,xml文件里面有两个类的地址
(servlet是包名)
servlet.RegisterServlet servlet.LoginServlet
那就实现这两个类,写一个接口,让这两个类继承service方法,
分别输出他们的类名
使用
WebContext context=new WebContext(servlets,mappings);
String className=context.getClz("/g");
Class clz3=Class.forName(className);
LoginServlet loginServlet= (LoginServlet) clz3.getConstructor().newInstance();
loginServlet.service();