三.手写迷你版Tomcat-minicat3.0

minicat 1.0我们实现了返回固定的字符串"Hello minicat"。
minicat 2.0封装Request和Response对象,返回html静态资源文件。
minicat 3.0需求:
请求servlet动态资源
思路分析:
想实现servlet动态资源请求,就需要将Servlet初始化在容器中(Map)。
如何初始化呢?

  • 将配置信息配置在web.xml中
  • 使用dom4j解析web.xml内容
  • 使用反射机制将servlet初始化在Map中

配置web.xml

配置web.xml之前,需要先自定义一个DemoServlet,需要有常见的doGet和doPost方法。
进一步想平时写Servlet都需要继承HttpServlet抽象类,所以先自己定义一个HttpServlet抽象类,以便后续做容器初始化。
先定义Servlet接口

public interface Servlet {

    void init() throws Exception;

    void destroy() throws Exception;

    void service(Request request,Response response) throws Exception;
}

HttpServlet实现Servlet

public abstract class HttpServlet implements Servlet {

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

    @Override
    public void service(Request request, Response response) throws Exception {
        if ("GET".equalsIgnoreCase(request.getMethod())) {
            doGet(request,response);
        }else{
            doPost(request,response);
        }
    }
}

接下来就是常规的DemoServlet编写了

public class DemoServlet extends HttpServlet{
    @Override
    public void doGet(Request request, Response response) {
        String content = "<h1>get request</h1>";
        try {
            response.output(HttpProtocolUtil.getHttpHeader200(content.getBytes().length)+content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doPost(Request request, Response response) {
        String content = "<h1>post request</h1>";
        try {
            response.output(HttpProtocolUtil.getHttpHeader200(content.getBytes().length)+content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void init() throws Exception {

    }

    @Override
    public void destroy() throws Exception {

    }
}

DemoServlet准备完成后,就可以配置web.xml了

<?xml version="1.0" encoding="UTF-8" ?>
<web-app>
    <servlet>
        <servlet-name>demo</servlet-name>
        <servlet-class>server.DemoServlet</servlet-class>
    </servlet>


    <servlet-mapping>
        <servlet-name>demo</servlet-name>
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>
</web-app>

使用dom4j解析web.xml

web.xml已经配置完成,解析来就需要对它进行解析,也就是初始化的过程,所以需要放在上一篇的start()方法中初始化。

public void start() throws Exception {
        // 加载解析相关配置,web.xml
        loadServlet();
		
		// 后面内容暂时省略....
}

/**
  * 加载解析web.xml,初始化servlet
  */
 private void loadServlet() {
     // 将web.xml配置文件读取到input流中
     InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
     SAXReader saxReader = new SAXReader();
     try {
         // 转换成Document对象
         Document document = saxReader.read(resourceAsStream);
         // 获取根对象
         Element rootElement = document.getRootElement();

         // 通过dom4j解析web.xml中的内容,放入到Map中
         List<Element> selectNodes = rootElement.selectNodes("//servlet");
         for (Element element : selectNodes) {
             // <servlet-name>demo</servlet-name>
             Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
             String servletName = servletnameElement.getStringValue();
             // <servlet-class>server.DemoServlet</servlet-class>
             Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
             String servletClass = servletclassElement.getStringValue();


             // 根据servlet-name的值找到url-pattern
             Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
             // /demo
             String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
             // 使用反射初始化servlet加载到map中
             //servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClas).newInstance());
         }
     } catch (DocumentException | ClassNotFoundException e) {
         e.printStackTrace();
     } catch (IllegalAccessException e) {
         e.printStackTrace();
     } catch (InstantiationException e) {
         e.printStackTrace();
     }
 }

使用反射机制将servlet初始化在Map中

眼尖的同学估计看到了,这一步骤其实就是在loadServlet()方法中实现的
在这里插入图片描述
添加map容器

private Map<String,HttpServlet> servletMap = new HashMap<String,HttpServlet>();

// 伪代码
private void loadServlet() {
// doSomething...
servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
// doSomething...
}

演示效果

已经初始化map容器了,那就需要在start方法中引用,start方法完整代码如下

/**
     * minicat启动需要初始化展开的一些操作
     */
    public void start() throws Exception {
        // 加载解析相关配置,web.xml
        loadServlet();

        // 监听端口
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("---->>>minicat start on port:"+port);

        //minicat 1.0 返回固定字符串
//        while (true) {
//            String data = "Hello minicat!";
//            Socket socket = serverSocket.accept();
//            // 有了socket,接收到请求,获取输出流
//            OutputStream outputStream = socket.getOutputStream();
//            String responseText = HttpProtocolUtil.getHttpHeader200(data.getBytes().length)+data;
//            outputStream.write(responseText.getBytes());
//            socket.close();
//        }

        // minicat 2.0 返回静态资源html
//        while (true) {
//            Socket socket = serverSocket.accept();
//            // 获取输入流
//            InputStream inputStream = socket.getInputStream();
//
//            //封装Request和Response
//            Request request = new Request(inputStream);
//            Response response = new Response(socket.getOutputStream());
//
//            response.outputHtml(request.getUrl());
//            socket.close();
//
//        }

        // minicat 3.0 返回动态资源servlet
        while (true) {
            Socket socket = serverSocket.accept();
            // 获取输入流
            InputStream inputStream = socket.getInputStream();

            //封装Request和Response
            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());

            // 静态资源处理
            if(servletMap.get(request.getUrl()) == null) {
                response.outputHtml(request.getUrl());
            }else{
                // 动态资源servlet请求
                HttpServlet httpServlet = servletMap.get(request.getUrl());
                httpServlet.service(request,response);
            }
            socket.close();

        }
    }

效果演示
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值