手写简单版Tomcat(二)——XML解析配置

上节写到读取静态文件,接下来仿一个读取web.xml配置文件的功能。

首先,读取XML我参考的是这篇文章:https://www.cnblogs.com/hongwz/p/5514786.html

但是这篇文章里的读取XML是远远不够的,内容中的读取XML方法是读取写死固定的XML,而且只能读取到第一、二层节点,web.xml中可不远远不止一两层,于是得重新写个可以读取不限深度的XML的方法。

第一次修改的XML方法如下:

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XmlUtil {

    /*
    *   用Map封装XML实体
    *   一个标准的XML节点有3个参数:节点名String,参数名List<Map<String,Object>>,子节点List<Map>
    *
    *
    * */

    public static Object read(String path) throws Exception {
        //SAXReader就是一个管道,用一个流的方式,把xml文件读出来
        SAXReader reader = new SAXReader();
        File file = new File(path);
        Map result = new HashMap();
        Document document = reader.read(file);
        Element root = document.getRootElement();
        List<Element> childElements = root.elements();
        result.put("firstElement", root.getName());
        result.put("Attribute", root.attributes());
        for (Element child : childElements) {

            //未知属性名情况下

            List<Attribute> attributeList = child.attributes();

            for (Attribute attr : attributeList) {

                System.out.println(attr.getName() + ": " + attr.getValue());

            }


            //未知子元素名情况下

            List<Element> elementList = child.elements();

            for (Element ele : elementList) {

                System.out.println(ele.getName() + ": " + ele.getText());

            }

            System.out.println();

            //这行是为了格式化美观而存在

            System.out.println();

        }
        return null;
    }

}

该方法能读取到 第二层节点的内容

需要注意的是,web.xml是在tomcat启动的时候读取的,所以我在监听8080端口的时候读取的web.xml,web.xml文件我规定放在resource目录下

root就是第一层节点,也就是<web></web> 

root.elements是读取<web></web>的子节点

然后对<web></web>的子节点和属性进行循环输出,最终输出成

xml从结构上还是比较简单的,

但是上面的这个方法只能读取到第二层节点<title></title>,<author></author>,如果在title节点中再加个子节点,那么就读取不到了,

如图,确实读取不到,

OK,那么接下来就是对xml的读取方法进行修改,让他可以无限深度的读取xml。

 我们先不要那么快就敲代码,先分析下XML结构

就像上面说的一样,XML结构上比较简单,

就只有节点、属性、内容这三个东西

是滴。。。。。。

============================================================这是分隔符,代表有重大改变

刚刚突然想到,貌似我不用一下子读取全部的节点,只需要读取到第一个就行了,用到了再读取他的子节点,所以就不用改成无限深度的读取xml,只要改成返回第一个节点的方法就行了。

所以代码改成如下:

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XmlUtil {

    /*
    *   用Map封装XML实体
    *   一个标准的XML节点有3个参数:节点名String,参数名List<Map<String,Object>>,子节点List<Map>
    * */

    public static Object read(String path) throws Exception {
        //SAXReader就是一个管道,用一个流的方式,把xml文件读出来
        SAXReader reader = new SAXReader();
        File file = new File(path);
        Document document = reader.read(file);
        Element root = document.getRootElement();
        return root;

    }

}

读取到了第一个节点,然后再写一个方法解析,因为只是简单版tomcat,所以web.xml中的内容就不做太多解析

web.xml中的配置我是参照以下博客改的:

https://www.cnblogs.com/hxsyl/p/3435412.html

https://www.cnblogs.com/vanl/p/5737656.html

https://www.cnblogs.com/hafiz/p/5715523.html

下面是摘抄上面链接的一些原文,作为对web.xml的一些介绍:

xml必须有且只有一个根节点,大小写敏感,标签不嵌套,必须配对。

web.xml是不是必须的呢?不是的,只要你不用到里面的配置信息就好了,不过在大型web工程下使用该文件是很方便的,若是没有也会很复杂。

那么web.xml能做的所有事情都有那些?其实,web.xml的模式(Schema)文件中定义了多少种标签元素,web.xml中就可以出现它的模式文件所定义的标签元素,它就能拥有定义出来的那些功能。web.xml的模式文件是由Sun公司定义的,每个web.xml文件的根元素<web-app>中,都必须标明这个web.xml使用的是哪个模式文件。

在这里我就只写几个主要标签的解析:

Servlet配置(Servlet放后面写)

  <servlet>
     <servlet-name>servlet名称</servlet-name>
     <servlet-class>servlet类全路径</servlet-class>
     <init-param>
         <param-name>参数名</param-name>
         <param-value>参数值</param-value>
     </init-param>
         <run-as>
             <description>Security role for anonymous access</description>
         <role-name>tomcat</role-name>
     </run-as>
    <load-on-startup>指定当Web应用启动时,装载Servlet的次序</load-on-startup>
 </servlet>
 <servlet-mapping>
     <servlet-name>servlet名称</servlet-name>
     <url-pattern>映射路径</url-pattern>
 </servlet-mapping>
指定欢迎文件页配置

  <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
      <welcome-file>index.html</welcome-file>
      <welcome-file>index.htm</welcome-file>
  </welcome-file-list>
配置错误页面

  (1).通过错误码来配置error-page
 <!--配置了当系统发生404错误时,跳转到错误处理页面NotFound.jsp-->
 <error-page>
       <error-code>404</error-code>
       <location>/NotFound.jsp</location>
 </error-page>

编码过程我就不详写了,

最终XML解析类如下:

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XmlUtil {

    /*
    *   用Map封装XML实体
    *   一个标准的XML节点有3个参数:节点名String,参数名List<Map<String,Object>>,子节点List<Map>
    * */

    public static Object read(String path) throws Exception {

        //SAXReader就是一个管道,用一个流的方式,把xml文件读出来
        SAXReader reader = new SAXReader();
        File file = new File(path);
        Document document = reader.read(file);
        Element root = document.getRootElement();
        return root;

    }

    //解析Web.xml   analysis 解析
    public static boolean analysisWeb(){

        File directory = new File("src/main/resources/web.xml");
        try {
            Element root = (Element) read(directory.getAbsolutePath());
            if (!"web-app".equals(root.getName())){
                return false;
            }else{
                List<Element> elements = root.elements();

                for ( Element element : elements ) {

                    //welcome-file-list     欢迎文件页配置
                    if ("welcome-file-list".equals(element.getName())){
                        List<Element> welcome_file_list = element.elements();
                        if (welcome_file_list.size() > 0){
                            for ( Element welcome_file : welcome_file_list ){
                                if ("welcome-file".equals(welcome_file.getName()))
                                    Response.indexPages.add(welcome_file.getText());
                            }
                        }
                    }

                    //error-page   通过错误码来配置error-page
//                    if ("error-page".equals(elements)){
//                        List<Element> welcome_file_list = element.elements();
//                        if (welcome_file_list.size() > 0){
//                            for ( Element welcome_file : welcome_file_list ){
//                                if ("welcome-file".equals(welcome_file.getName()))
//                                    Response.Index.add(welcome_file.getText());
//                            }
//                        }
//                    }

                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }

}

能把欢迎页读取出来,那么错误页也是一样的,

同时,Response.java我也有做修改:

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Response {
  public static final int BUFFER_SIZE = 2048;
  //浏览器访问D盘的文件
  private static final String RESOURCE ="src/main/resources";
  private Request request;
  private OutputStream output;
  public static List<String> indexPages = new ArrayList<String>();

  public Response(OutputStream output) {
    this.output = output;
  }
  public void setRequest(Request request) {
    this.request = request;
  }

  public void sendStaticResource() throws IOException {
    byte[] bytes = new byte[BUFFER_SIZE];
    FileInputStream fis = null;
    try {
      //首页
      if ("/".equals(request.getUrL())){
        if (indexPages.size() > 0) {
          File file = new File(RESOURCE, indexPages.get(0));
          if (null != getFile(file)){
            String retMessage = (String) getFile(file);
            output.write(retMessage.getBytes());
            return;
          }
        }else{
          String retMessage = "<h1> Index not Found</h1>";
          String returnMessage ="HTTP/1.1 404 File Not Found\r\n" +
                  "Content-Type: text/html\r\n" +
                  "Content-Length: "+retMessage.length()+"\r\n" +
                  "\r\n" +
                  retMessage;
          output.write(returnMessage.getBytes());
          return;
        }
      }
      //====================================首页结束

      //拼接本地目录和浏览器端口号后面的目录
      File file = new File(RESOURCE, request.getUrL());
      String retMessage = (String) getFile(file);
      if (null != retMessage){
        output.write(retMessage.getBytes());
      }else{
        //文件不存在,返回给浏览器响应提示,这里可以拼接HTML任何元素
        retMessage = "<h1>"+file.getName()+" file or directory not exists</h1>";
        String returnMessage ="HTTP/1.1 404 File Not Found\r\n" +
                "Content-Type: text/html\r\n" +
                "Content-Length: "+retMessage.length()+"\r\n" +
                "\r\n" +
                retMessage;
        output.write(returnMessage.getBytes());
      }
    }
    catch (Exception e) {
      System.out.println(e.toString() );
    }
    finally {
      if (fis!=null)
        fis.close();
    }
  }

  public Object getFile(File file) throws Exception {
    FileInputStream fis = null;
    String retMessage = null;
    //如果文件存在,且不是个目录
    if (file.exists() && !file.isDirectory()) {
      fis = new FileInputStream(file);
      InputStreamReader reader = new InputStreamReader(fis,"UTF-8"); //最后的"GBK"根据文件属性而定,如果不行,改成"UTF-8"试试
      BufferedReader br = new BufferedReader(reader);
      String line;
      StringBuilder readLine = new StringBuilder();
      while ((line = br.readLine()) != null) {
        readLine.append(line);
      }
      retMessage = "HTTP/1.1 200 OK\r\n" +
              "Content-Type: text/html;charset=utf-8\r\n" +
              "Content-Length: "+ readLine.toString().getBytes().length +"\r\n" +
              "\r\n" +
              readLine;
    }else {
      return null;
    }
    return retMessage;
  }

}

读取File的代码我提取出来了

 这是读取首页的代码

当Url为 "/" 的时候就是http://localhost:8080/默认的这个网址,也就是首页

如果是访问首页,我就会去拿indexPages这个变量

 这个indexPages是在类启动的时候加载进来的,

 解析web.xml是如果有    welcome-file    这个标签我就把这个首页地址存进indexPages中

这是我的index页面

最后,启动服务器,访问localhost:8080

 返回成功!

第二节xml的读取就到此告一段落了,

如果有什么写的不对的地方,欢迎下方评论指出!

接下来的第三节会解析java文件,一个真正意义上的简单版tomcat功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值