我们在上一篇文章中已经将我们自己的MyServlet写好了,但是当我们启动程序后,我们写的tomcat并不知道我们的MyServlet在哪里,我们就像tomcat那样通过web.xml的方式来进行配置。
我们首先先来看一下我们的项目结构。
我们建立了一个webapp目录,webapp里面我们就放静态资源,webapp下的WEB-INF下面放置我们的web.xml配置文件。我们在web.xml中编写自己的MyServlet映射关系。
下面对上一篇文章中的2个Servlet进行配置,代码如下
<?xml version="1.0" encoding="utf-8" ?>
<myXml>
<myServlet>
<myServlet-name>cat</myServlet-name>
<myServlet-class>com.clucky.myTomcat.myServlet.MyCatServlet</myServlet-class>
</myServlet>
<myServlet-mapping>
<myServlet-name>cat</myServlet-name>
<myUrl-pattern>/cat</myUrl-pattern>
</myServlet-mapping>
<myServlet>
<myServlet-name>dog</myServlet-name>
<myServlet-class>com.clucky.myTomcat.myServlet.MyDogServlet</myServlet-class>
</myServlet>
<myServlet-mapping>
<myServlet-name>dog</myServlet-name>
<myUrl-pattern>/dog</myUrl-pattern>
</myServlet-mapping>
</myXml>
这个xml中的元素名字都是我自定义的。下面我们来写一个类来对web.xml文件读取并进行初始化。
我们建立了一个MyServletHandler类来对web.xml进行读取,并且将对应关系保存在map中。当然,这个map是public static的,其他类也可以访问,这就相对于一个配置类,在我们的程序启动时就会加载。
//这个map用于存放名字和类的全路径的对应关系
public static final ConcurrentHashMap<String, String> NAME_CLASS = new ConcurrentHashMap<>();
//这个map用于存放对外访问路径和名字的关系
public static final ConcurrentHashMap<String, String> PATTERN_NAME = new ConcurrentHashMap<>();
//这个map用于存放对外访问路径和MyServlet的关系
public static final ConcurrentHashMap<String, MyServlet> PATTERN_CLASS = new ConcurrentHashMap<>();
然后我们创建一个init方法,里面就对web.xml文件进行读取,并将对应的映射关系存储起来。
public static void init() {
try {
//得到项目根路径,并且对路径中的中文进行处理
String path = URLDecoder.decode(Objects.requireNonNull(
MyServletHandler.class.getResource("/")).getPath(), "utf-8");
得到解析器
SAXReader saxReader = new SAXReader();
//指定解析文件
Document document = saxReader.read(new File(path + "/webapp/WEB-INF/web.xml"));
//得到根节点
Element rootElement = document.getRootElement();
//分别得到我们在web.xml文件中的myServlets,myServletMappings元素。
List<Element> myServlets = rootElement.elements("myServlet");
List<Element> myServletMappings = rootElement.elements("myServlet-mapping");
//将name,classPath的对应关系存如map中
for (Element myServlet : myServlets) {
String name = myServlet.element("myServlet-name").getText();
String classPath = myServlet.element("myServlet-class").getText();
NAME_CLASS.put(name,classPath);
}
//将pattern,name的对应关系存如map中
for (Element myServletMapping : myServletMappings) {
String name = myServletMapping.element("myServlet-name").getText();
String pattern = myServletMapping.element("myUrl-pattern").getText();
PATTERN_NAME.put(pattern,name);
}
} catch (Exception e) {
System.out.println("初始化容器发生异常....");
}
}
上面这段代码用到了java读取xml的技术,如果不清楚,请参考java解析xml,拿到xml中的数据后,我们将xml中编写的映射关系存储到map中进行管理。最后,给出完整代码
import com.clucky.myTomcat.myServlet.MyServlet;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.net.URLDecoder;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public class MyServletHandler {
//这个map用于存放名字和类的全路径的对应关系
public static final ConcurrentHashMap<String, String> NAME_CLASS = new ConcurrentHashMap<>();
//这个map用于存放对外访问路径和名字的关系
public static final ConcurrentHashMap<String, String> PATTERN_NAME = new ConcurrentHashMap<>();
//这个map用于存放对外访问路径和MyServlet的关系
public static final ConcurrentHashMap<String, MyServlet> PATTERN_CLASS = new ConcurrentHashMap<>();
public static void init() {
try {
//得到项目根路径,并且对路径中的中文进行处理
String path = URLDecoder.decode(Objects.requireNonNull(
MyServletHandler.class.getResource("/")).getPath(), "utf-8");
得到解析器
SAXReader saxReader = new SAXReader();
//指定解析文件
Document document = saxReader.read(new File(path + "/webapp/WEB-INF/web.xml"));
//得到根节点
Element rootElement = document.getRootElement();
//分别得到我们在web.xml文件中的myServlets,myServletMappings元素。
List<Element> myServlets = rootElement.elements("myServlet");
List<Element> myServletMappings = rootElement.elements("myServlet-mapping");
//将name,classPath的对应关系存如map中
for (Element myServlet : myServlets) {
String name = myServlet.element("myServlet-name").getText();
String classPath = myServlet.element("myServlet-class").getText();
NAME_CLASS.put(name,classPath);
}
//将pattern,name的对应关系存如map中
for (Element myServletMapping : myServletMappings) {
String name = myServletMapping.element("myServlet-name").getText();
String pattern = myServletMapping.element("myUrl-pattern").getText();
PATTERN_NAME.put(pattern,name);
}
} catch (Exception e) {
System.out.println("初始化容器发生异常....");
}
}
@Test
public void test(){
init();
System.out.println(NAME_CLASS);
System.out.println(PATTERN_NAME);
}
}
测试
我们编写一个测试方法进行测试
@Test
public void test(){
init();
System.out.println(NAME_CLASS);
System.out.println(PATTERN_NAME);
}
运行,查看控制台输出,并和我们编写的web.xml进行比较
控制台输出
web.xml文件
发现map中的对应关系和web.xml中一致,说明我们的代码没有问题。