上一篇,我们讲解了如果开发一个简单的Http服务器,这一篇,我们扩展一下,让我们的服务器具备servlet的解析功能。

简单介绍下Servlet接口
如果我们想要自定义一个Servlet,那么我们必须继承Servlet,并且实现下面几个重要的方法

public void init(ServletConfig config) throws ServletException
public void service(ServletRequest request,ServletResponse response) throws ServletException,java.io.IOException
public void destroy()
public ServletConfig getServletConfig()
public String getServletInfo() 

五个方法中,init,destroy,service都是和servlet的生命周期相关的方法。当实例化某个servlet类之后,servlet会调用init进行初始化,当servlet的请求到达之后,就会调用service方法,并将servletRequest和servletResponse对象作为参数传入,前者包含客户端的Http请求的信息,后者包含服务器的响应信息。

这个简单的Servlet容器的流程如下

  • 等待http请求
  • 对应的servletRequest对象和servletResponse对象,
  • 判断请求的类型,如果是请求静态资源,则找到静态资源的文件,返回给客户端
  • 如果是Servlet请求,载入servlet类,调用service()方法,传入servletRequest对象和servletResponse对象

涉及到的主要的类

  • SimpleServletContainerServer
  • Request
  • Response
  • Servlet
  • PrimitiveServlet
  • StaticProcessor
  • ServletProcessor

关于Request和Response的定义在上一篇幅有定义,这里我们稍微扩展了一下,碍于篇幅,不在这里展示。

PrimitiveServlet类,继承自Servlet,Servlet请求的处理类
类定义:

package servletContainer;

import java.io.IOException;

import base.Request;
import base.Response;
import base.ServletConfig;
import interf.Servlet;

public class PrimitiveServlet implements Servlet {

    @Override
    public void init(ServletConfig config) {
        System.out.println("PrimitiveServlet init");
    }

    @Override
    public void service(Request request, Response response) throws IOException {
        response.getOutput().write("Primitive Servlet".getBytes());
    }

    @Override
    public void destroy() {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public String getServletInfo() {
        return null;
    }

}

SimpleServletContainerServer 类
功能:程序入口,监听Http请求,并且负责创建Request和Response
类定义

package servletContainer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import base.Request;
import base.Response;
import servletContainer.processor.ServletProcessor;
import servletContainer.processor.StaticProcessor;

public class SimpleServletContainerServer {
    private static final String SHUT_DOWN = "/SHUTDOWN";

    private boolean shutdown = false;

    private ServletProcessor servletProcessor = new ServletProcessor();

    private StaticProcessor staticProcessor = new StaticProcessor();

    public static void main(String args[]){
        SimpleServletContainerServer server = new SimpleServletContainerServer();
        server.init();
        server.await();
    }

    public void init(){
        servletProcessor.init();
        staticProcessor.init();
    }

    public void await(){

        ServerSocket serverSocket = null;
        int port = 8080;

        try{
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        }
        catch (IOException e){
            e.printStackTrace();
            System.exit(-1);
        }

        while(!shutdown){
            Socket socket = null;
            InputStream input = null;
            OutputStream output = null;

            try{

                socket = serverSocket.accept();
                input = socket.getInputStream();
                output = socket.getOutputStream();

                Request request = new Request(input);
                request.parse();

                Response response = new Response(output);
                response.setRequest(request);

                if(request.getUri().startsWith("/servlet/")){
                    servletProcessor.process(request, response);
                }
                else{
                    staticProcessor.process(request, response);
                }

                socket.close();
                shutdown = request.getUri().equals(SHUT_DOWN);

            }
            catch (Exception e){
                e.printStackTrace();
                System.exit(1);
            }
        }

    }

}

我们引入了StaticProcessor和ServletProcessor进行逻辑的处理,我们看下这两个类的定义
首先这两个类都继承自IProcessor接口

package servletContainer.processor;

import base.Request;
import base.Response;

public interface IProcessor {

    public void init();

    public void process(Request request,
            Response response);
}

StaticProcessor类主要是处理静态资源请求
类定义

package servletContainer.processor;

import base.Request;
import base.Response;

public class StaticProcessor implements IProcessor {

    @Override
    public void process(Request request, Response response) {
        try{
            response.sendStaticResource();
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void init() {

    }

}

ServeletProcessor主要负责处理Servlet请求,初始化的时候,初始化所有的Servlet子类,接收到servlet的http请求之后,根据请求名称,调用对应的service函数。
类定义

package servletContainer.processor;

import java.util.HashMap;
import java.util.Map;

import base.Request;
import base.Response;
import interf.Servlet;
import servletContainer.PrimitiveServlet;

public class ServletProcessor implements IProcessor {

    private Map<String,Servlet> map = new HashMap<String,Servlet>();

    public ServletProcessor() {

    }

    public void init(){
        PrimitiveServlet servlet = new PrimitiveServlet();
        servlet.init(null);
        map.put("PrimitiveServlet", servlet);
    }

    @Override
    public void process(Request request, Response response) {
        String uri = request.getUri();
        String servletName = uri.substring(uri.lastIndexOf("/") + 1);

        Servlet servlet = map.get(servletName);
        try{
            if(servlet != null){
                servlet.service(request, response);
            }
            else{
                String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
                        "Content-Type: text/html\r\n" +
                        "Content-Length:23\r\n" +
                        "\r\n" +
                        "<h1>File Not Found</h1>";
                response.getWriter().print(errorMessage.getBytes());
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        catch (Throwable e){
            e.printStackTrace();
        }

    }

}

结果
我们在eclipse里运行结果

深入剖析tomcat之一个简单的servlet容器的更多相关文章

  1. 一个简单的servlet容器

    [0]README 0.1)本文部分文字转自 “深入剖析Tomcat”,旨在学习  一个简单的servlet容器  的基础知识: 0.2)for complete source code, pleas ...

  2. how tomcat works 读书笔记(二)----------一个简单的servlet容器

    app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...

  3. Tomcat学习笔记(二)—— 一个简单的Servlet容器

    1.简介:Servlet编程是通过javax.Servlet和javax.servlet.http这两个包的类和接口实现的,其中javax.servlet.Servlet接口至关重要,所有的Servl ...

  4. 一个简单的Servlet容器实现

    上篇写了一个简单的Java web服务器实现,只能处理一些静态资源的请求,本篇文章实现的Servlet容器基于前面的服务器做了个小改造,增加了Servlet请求的处理. 程序执行步骤 创建一个Serv ...

  5. 深入剖析tomcat之一个简单的web服务器

    这个简单的web服务器包含三个类 HttpServer Request Response 在应用程序的入口点,也就是静态main函数中,创建一个HttpServer实例,然后调用其await()方法. ...

  6. 攻城狮在路上(肆)How tomcat works(二) 一个简单的servlet容器

    该节在上一节的基础上增加了所谓对静态资源和动态资源访问的不同控制流程.示例里面采用的是对路径“/servlet/”进行了特殊处理. 一. 主要还是从HttpServer1中的main方法开始,先解析出 ...

  7. Tomcat剖析(二):一个简单的Servlet服务器

    Tomcat剖析(二):一个简单的Servlet服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三) ...

  8. How tomcat works(深入剖析tomcat)servlet容器

    How tomcat works (5)servlet容器阅读笔记 第四章阅读了tomcat默认连接器的实现,当时connector中的使用的容器是自定义的容器,也是非常之简单奥,一个人就干完了所有的 ...

  9. 《深入剖析Tomcat》阅读(二)

    Tomcat是基于Sun公司标准的开源Servlet容器. Servlet是什么? Servlet(Server Applet),全称Java Servlet,未有中文译文.是用Java编写的服务器端 ...

随机推荐

  1. Opencv算法学习二

    1.直方图:图片中像素值分布情况的坐标图. 直方图均衡化:按一定规律拉伸像素值,提高像素值少的点,增加原图的对比度,使人感觉更清晰的函数. equalizeHist( src, dst ); 2.ha ...

  2. 智能路由器操作系统OpenWrt

    小米路由器的“MiWiFi”又让路由器成了关键词,每台智能路由器的系统是该款产品的亮点之一,其系统肯定有不少“好玩”的地方.为自己的智能路由器量身打造系统,并且纷纷开发了适合智能手机.平板电脑等使用的 ...

  3. ABP理论学习之授权(Authorization)

    返回总目录 本篇目录 介绍 定义权限 检查权限 使用AbpAuthorize特性 使用IPermissionChecker Razor视图 客户端(Javascript) 权限管理者 介绍 几乎所有的 ...

  4. .NET支持多平台后的一点拙见

    我们目前对.NET的理解大部分可以归纳为:起初它是Java平台(注意是平台,不要跟Java语言搞混淆)的一个克隆品,后来慢慢演变,有了自己的特性.由于Java平台最显著的特点就是“平台独立性”(或者说 ...

  5. 为什么google bazel构建工具流行不起来

    作者Jack47 转载请保留作者和原文出处 之前博主写了系列文章Google软件构建工具Bazel原理及使用方法介绍.最近使用了一段时间后,觉得这个东西不是一种通用的构建工具,很难对接到情况复杂的大的 ...

  6. 《Entity Framework 6 Recipes》中文翻译系列 (34) ------ 第六章 继承与建模高级应用之多条件与QueryView

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-10  创建一个多条件过滤 问题 你想使用多个条件为实体过滤表中的行. 解决方案 ...

  7. Rxjava入门

    简介 RxJava是一个开源的Rx框架ReactiveX的java版本. ReactiveX的主要目的是通过一系列Observable组合异步或事件代码.其中使用的是观察者模式. 可以吧Reactiv ...

  8. Js replace() 学习笔记

    最近捣鼓着学习Js,发现replace()真的很有用,替换功能杠杠的棒. 接下来看看我遇到的问题: 有两个随机给出的字符串,字符串1'xxxxxx',字符串2'====T'(这两个用作示例,其他为随机 ...

  9. iOS-Objective-C基础

    一.Foundation框架 概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objective-C开发中经常用到NS ...

  10. Segmentation fault (core dumped)

    问题: 在Linux中实现快速排序时,没有加入终止条件,结果出现Segmentation fault (core dumped)这个问题,Segmentation fault (core dumped ...