手写简单版Tomcat(三)——解析servlet

到目前为止,我们手写的tomcat已经具备了基本的读取静态资源文件、读取web.xml文件来进行配置的功能,接下来就是对servlet的解析。

<web-app>

      <welcome-file-list>
          <welcome-file>../index.html</welcome-file>
          <welcome-file>index.html</welcome-file>
          <welcome-file>index.html</welcome-file>
      </welcome-file-list>

    <servlet>
        <servlet-name>helllo</servlet-name>
        <servlet-class>Server.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>helllo</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

在web.xml中,把servlet的配置写进去,同时,我也对整个项目的路径进行了一些修改:

我把这几个目录,都统统改在了servlet的目录下

在Server下建一个Servlet父类,定义post和get方法

package Server;

public abstract class Servlet {

    public abstract  void doGet(Request request, Response response);

    public abstract  void doPost(Request request, Response response);

    public void service (Request request, Response response){

        if ("GET".equals(request.getMethod())){
            doGet(request,response);
        }else if ("POST".equals(request.getMethod())){
            doPost(request,response);
        }else{
            throw new RuntimeException();
        }

    }

}

接着写一个 HelloServlet 继承于Servlet

package Server.servlet;

import Server.Request;
import Server.Response;
import Server.Servlet;

public class HelloServlet extends Servlet {

    @Override
    public void doGet(Request request, Response response) {

        System.out.println("doGet");

    }

    @Override
    public void doPost(Request request, Response response) {

        System.out.println("doPost");

    }
}

然后在Resonse中用一个变量存放在web.xml中读取到的servlet,

public static List<Map> servletList = new ArrayList<Map>();

这在tomcat中对应的是Web Application,每个Web Application 由一个或多个Servlet 组成。当一个Web Application 被初始化的时候,它将用自己的ClassLoader 对象载入部署配置文件web.xml 中定义的每个Servlet 类。

之后,在xmlUtil中把servlet的相关配置加载进来

package Server;

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());
                            }
                        }
                    }

                    if ("servlet".equals(element.getName())){
                        List<Element> servlet = element.elements();
                        if (servlet.size() > 0){
                            for ( Element servlet_children : servlet ){
                                if ("servlet-name".equals(servlet_children.getName())) {
                                    //如果servletName不存在,则新建,否则直接put对应的值
                                    List<Map> servletList = Response.servletList;
                                    if (servletList.size() > 0) {
                                        for (int i = 0; i < servletList.size(); i++) {
                                            Map servletMap = servletList.get(i);
                                            if (!servlet_children.getText().equals(servletMap.get("name"))) {
                                                Map map = new HashMap();
                                                map.put("name", servlet_children.getText());
                                                map.put("class", null);
                                                for (Element servlet_children2 : servlet) {
                                                    if ("servlet-class".equals(servlet_children2.getName())) {
                                                        map.put("class", servlet_children2.getText());
                                                    }
                                                }
                                                Response.servletList.add(map);
                                            } else {
                                                servletMap.put("class", null);
                                                for (Element servlet_children2 : servlet) {
                                                    if ("servlet-class".equals(servlet_children2.getName())) {
                                                        servletMap.put("class", servlet_children2.getText());
                                                    }
                                                }
                                                Response.servletList.set(i, servletMap);
                                            }
                                        }
                                    }else {
                                        Map map = new HashMap();
                                        map.put("name", servlet_children.getText());
                                        map.put("class", null);
                                        for (Element servlet_children2 : servlet) {
                                            if ("servlet-class".equals(servlet_children2.getName())) {
                                                map.put("class", servlet_children2.getText());
                                            }
                                        }
                                        Response.servletList.add(map);
                                    }
                                }
                            }
                        }
                    }

                    if ("servlet-mapping".equals(element.getName())){
                        List<Element> servletMapping = element.elements();
                        if (servletMapping.size() > 0){
                            for ( Element servletMapping_children : servletMapping ){
                                if ("servlet-name".equals(servletMapping_children.getName())) {
                                    //如果servletName不存在,则新建
                                    List<Map> servletList = Response.servletList;
                                    if (servletList.size() > 0) {
                                        for (int i = 0; i < servletList.size(); i++) {
                                            Map servletMap = servletList.get(i);
                                            if (!servletMapping_children.getText().equals(servletMap.get("name"))) {
                                                Map map = new HashMap();
                                                map.put("name", servletMapping_children.getText());
                                                map.put("url", null);
                                                for (Element servlet_children2 : servletMapping) {
                                                    if ("url-pattern".equals(servlet_children2.getName())) {
                                                        map.put("url", servlet_children2.getText());
                                                    }
                                                }
                                                Response.servletList.add(map);
                                            } else {
                                                servletMap.put("url", null);
                                                for (Element servlet_children2 : servletMapping) {
                                                    if ("url-pattern".equals(servlet_children2.getName())) {
                                                        servletMap.put("url", servlet_children2.getText());
                                                    }
                                                }
                                                Response.servletList.set(i, servletMap);
                                            }
                                        }
                                    }else {
                                        Map map = new HashMap();
                                        map.put("name", servletMapping_children.getText());
                                        map.put("url", null);
                                        for (Element servlet_children2 : servletMapping) {
                                            if ("url-pattern".equals(servlet_children2.getName())) {
                                                map.put("url", servlet_children2.getText());
                                            }
                                        }
                                        Response.servletList.add(map);
                                    }
                                }
                            }
                        }
                    }

                    //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()))
//                                    Server.Response.Index.add(welcome_file.getText());
//                            }
//                        }
//                    }

                }

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

}

我解析servlet配置的思路是这样的:首先判断“Response.servletList”中是否有值,如果没有,那么直接新建一个map用于保存servlet的name、url、class,如果有,那就先取出来遍历,看看serlvet的name存不存在,如果存在,就直接覆盖对应的class或者url,否则新建一个servlet。

把配置中的servlet加载成功后,就在Response做判断,如果是访问的servlet,就根据访问的Url与servlet中的url做对比,找到就通过反射调用对应的POST、GET方法

package Server;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import Server.Servlet.*;

public class Response {
    public static final int BUFFER_SIZE = 2048;

    //根路径
    private static final String RESOURCE = "";

    private Request request;
    private OutputStream output;
    public static List<String> indexPages = new ArrayList<String>();
    public static List<Map> servletList = new ArrayList<Map>();

    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) {
                    for (int i = 0; i < indexPages.size(); i++) {
                        File file = new File(RESOURCE + "src/main/resources", indexPages.get(i));
                        if (null != getFile(file)) {
                            String retMessage = (String) getFile(file);
                            output.write(retMessage.getBytes());
                            return;
                        } else {
                            continue;
                        }
                    }
                }

                String retMessage = "<h1> 主页被吃了! </h1>";
                String returnMessage = "HTTP/1.1 404 File Not Found\r\n" +
                        "Content-Type: text/html;charset=utf-8\r\n" +
                        "Content-Length: " + retMessage.getBytes().length + "\r\n" +
                        "\r\n" +
                        retMessage;
                output.write(returnMessage.getBytes());
                return;
            }
            //====================================首页结束

            //如果是serlvet
            if (request.getUrL().split("\\.").length == 1){
                for ( Map map : servletList){
                    if (map.get("url").equals(request.getUrL())){
                        if (map.get("class") != null){
                            if ("POST".equals(request.getMethod())){
                                Method aClass = Class.forName((String) map.get("class")).getMethod("doPost", request.getClass(), this.getClass());
                                aClass.invoke(Class.forName((String) map.get("class")).newInstance(), request, this);
                            }else if ("GET".equals(request.getMethod())){
                                Method aClass = Class.forName((String) map.get("class")).getMethod("doGet", request.getClass(), this.getClass());
                                System.out.println(aClass);
                                aClass.invoke(Class.forName((String) map.get("class")).newInstance(), request, this);
                            }
                        }
                    }
                }
            }

            //如果是静态资源
            if (request.getUrL().endsWith(".html") || request.getUrL().endsWith(".css") || request.getUrL().endsWith(".js")) {
                File file = new File(RESOURCE + "src/main/resources", request.getUrL());
                String retMessage = (String) getFile(file);
                if (null != retMessage) {
                    output.write(retMessage.getBytes());
                } else {
                    //文件不存在,返回给浏览器响应提示,这里可以拼接HTML任何元素
                    retMessage = "<h1>" + file.getName() + " Page or directory not exists</h1>";
                    String returnMessage = "HTTP/1.1 404 Page Not Found\r\n" +
                            "Content-Type: text/html\r\n" +
                            "Content-Length: " + retMessage.getBytes().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;
    }

}

最后贴一张图

 

 

 至此,一个简陋版的tomcat就完成了。

如果有问题,可以留言交流。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值