1、初识tomcat整体脉络

首先我们知道tomcat是用java实现的Servlet规范的优秀的Servlet容器。

 从上图来看,tomcat对下接收了一个Http的网络请求,对上调用了Web应用实现的其中一个Servlet接口。

tomcat调用应用的Servlet提供给应用一个ServletRequest和一个ServletResponse。

这就是tomcat实现的核心功能,这样处理有什么好处?

优点:容器与应用解耦。

缺点:接口固定了,扩展性变弱。

大致了解了tomcat容器与web应用之间的关系,接下来我们宏观地认识下tomcat。

根据上面描述的这条数据线来讲解一下tomcat的脉络(下面内容是建立在对tomcat容器有基本了解的前提)

首先我们看看tomcat各个容器的包含关系

上面这张图是tomcat的总体框架图,我们对各组件做各简单的说明:

server是管理service的,service是用来管理连接器(connector)和容器(engine)的

connector:连接器,监听端口,读取数据,解析数据并调用容器。

容器:根据请求路径,映射到对应的servlet,加载对应的servlet,并调用service。

我写了个简单的应用,来模拟connector和容器间数据处理的,将这个应用弄明白,tomcat整体数据脉络也就能弄清楚。

public interface Request {
    String getUri();
    void setInputStream(InputStream inputStream);
    InputStream getInputStream();
}

public interface Response {
    void setOutputStream(OutputStream outputStream);

    OutputStream getOutputStream();
    PrintWriter getPrintWriter();
}

public interface Servlet {
    void service(Request request, Response response);
}

上面是模拟javax.servlet定义的Servlet,Request,Response接口,这个就是连接容器和应用的桥梁了,之所以没有采用官方的,是因为我们这里主要目的是处理的脉络,精简的信息能确保我们不分散注意力到其他不相关的方面去,并且简单的东西更方便大家理解。

public class Connector implements Runnable {

    Container container;

    public Container getContainer() {
        return container;
    }

    public void setContainer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(8080,
                    20,
                    InetAddress.getByName("localhost"));

            while (true) {
                Socket socket = serverSocket.accept();
                Request request = new ServletRequest();
                request.setInputStream(socket.getInputStream());
                Response response = new ServletResponse();
                response.setOutputStream(socket.getOutputStream());

                ((ServletRequest) request).parseRequest(request);

                container.invoke(request, response);
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        Thread t = new Thread(this);
        t.start();
    }
}

public class ServletRequest implements Request {

    protected InputStream inputStream;
    protected String uri;
    protected String method;
    protected String protocol;

    void parseRequest(Request request) {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()));

        try {
            String firstLine = bufferedReader.readLine();

            String[] firstLineContent = firstLine.split(" ");
            this.method = firstLineContent[0];
            this.uri=firstLineContent[1];
            this.protocol=firstLineContent[2];
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getUri() {
        return uri;
    }

    @Override
    public void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    @Override
    public InputStream getInputStream() {
        return inputStream;
    }
}

public class ServletResponse implements Response {
    OutputStream outputStream;

    @Override
    public void setOutputStream(OutputStream outputStream) {
        this.outputStream = outputStream;
    }

    @Override
    public OutputStream getOutputStream() {
        return outputStream;
    }

    @Override
    public PrintWriter getPrintWriter() {
        PrintWriter pw = new PrintWriter(outputStream);
        return pw;
    }
}

这里我们先说一下ServletRequest与ServletResponse,这两个分别实现了Request,Response接口,可直接作为servlet的service的参数。

Connector,这个类里面创建了一个线程,负责接收连接,创建ServletRequest,ServletResponse,解析请求数据,填充创建的对象,

我们再看看,connector与一个container关联,处理完之后,调用了关联的容器的invoke(Request,Response)。

public interface Pipeline {
    Valve getBasic();
    void setBasic(Valve valve);
    Valve[] getValves();
    void addValve(Valve valve);
    void invoke(Request request, Response response);
}

public interface Valve {
    void invoke(Request request, Response response, ValveContext valveContext);
}

public interface ValveContext {
    void invokeNext(Request request, Response response);
}

public abstract class ValveBase implements Valve, Contained {
    private Container container;

    @Override
    public Container getContainer() {
        return container;
    }

    @Override
    public void setContainer(Container container) {
        this.container = container;
    }
}

public class StandardPipeline implements Pipeline, Contained {
    protected Valve basic;
    protected Valve[] valves = new Valve[0];
    protected Container container;

    public StandardPipeline(Container container) {
        this.container = container;
    }

    @Override
    public Valve getBasic() {
        return basic;
    }

    @Override
    public void setBasic(Valve valve) {
        this.basic = valve;
        if (valve instanceof Contained) {
            ((Contained) valve).setContainer(this.container);
        }
    }

    @Override
    public Valve[] getValves() {
        return null;
    }

    @Override
    public void addValve(Valve valve) {
        Valve[] t = new Valve[valves.length+1];
        System.arraycopy(valves, 0, t, 0, valves.length);
        t[t.length] = valve;
        valves = t;
    }

    @Override
    public void invoke(Request request, Response response) {
        new StandardPipelineValveContext().invokeNext(request, response);
    }

    @Override
    public Container getContainer() {
        return container;
    }

    @Override
    public void setContainer(Container container) {
        this.container = container;
    }

    class StandardPipelineValveContext implements ValveContext {

        private int stage=0;

        @Override
        public void invokeNext(Request request, Response response) {
            int curr = stage;
            stage++;
            if (curr < valves.length) {
                valves[curr].invoke(request, response, this);
            } else {
                basic.invoke(request, response, null);
            }
        }
    }
}

 每个容器都关联着一个管道pipeline,上面代码就是管道的一个简单代码模型。

管道运用到了责任链模式,位于链上的类均会调用。整个过程类似链表的遍历从第一个节点逐个访问到最后一个。

这样做的好处,避免了调用与被调用,上层容器与下层容器之间的耦合,各自业务独立处理,另外方便扩展。

public interface Contained {
    Container getContainer();
    void setContainer(Container container);
}

public interface Container {
    String getName();
    void setName(String name);

    Container getChild(String name);
    void addChild(Container container);
    Container map(Request request);

    void invoke(Request request, Response response);
}

public abstract class ContainerBase implements Container, Pipeline {
    protected HashMap<String, Container> children = new HashMap();
    protected Pipeline pipeline;

    public ContainerBase() {
    }

    private String name;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public Container getChild(String name) {
        return children.get(name);
    }

    @Override
    public void addChild(Container container) {
        children.put(container.getName(), container);
    }

    @Override
    public void invoke(Request request, Response response) {
        pipeline.invoke(request, response);
    }

    @Override
    public Valve getBasic() {
        return pipeline.getBasic();
    }

    @Override
    public void setBasic(Valve valve) {
        pipeline.setBasic(valve);
    }

    @Override
    public Valve[] getValves() {
        return pipeline.getValves();
    }

    @Override
    public void addValve(Valve valve) {
        pipeline.addValve(valve);
    }
}

public class Wrapper extends ContainerBase {
    private String servletClass;

    public Wrapper() {
        this.pipeline = new StandardPipeline(this);
        setBasic(new StandardWrapperValve());
    }

    @Override
    public Container map(Request request) {
        return null;
    }

    public String getServletClass() {
        return servletClass;
    }

    public void setServletClass(String servletClass) {
        this.servletClass = servletClass;
    }
}

public class StandardWrapperValve extends ValveBase {

    @Override
    public void invoke(Request request, Response response, ValveContext valveContext) {
        Wrapper wrapper = (Wrapper) getContainer();
        String servletClassName = wrapper.getServletClass();

        System.out.println("wrapper 处理");
        try {
            // 这里为了简便,直接用了系统的加载器,实际情况是需要定义自己的加载器的
            Class servletClass = getClass().getClassLoader().loadClass(servletClassName);
            Servlet servlet = (Servlet) servletClass.newInstance();
            servlet.service(request, response);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

public class Context extends ContainerBase {

    public Context() {

        this.pipeline = new StandardPipeline(this);
        setBasic(new StandardContextValve());
    }

    @Override
    public Container map(Request request) {

        // 因为匹配规则比较多,我们这里仅使用uri的最后一个/之后的内容匹配
        String uri = request.getUri();
        String pattern = uri.substring(uri.lastIndexOf('/'));
        return getChild(pattern);
    }
}

public class StandardContextValve extends ValveBase {
    @Override
    public void invoke(Request request, Response response, ValveContext valveContext) {
        Context context = (Context) getContainer();

        System.out.println("context处理");
        Wrapper wrapper = (Wrapper) context.map(request);
        wrapper.invoke(request, response);
    }
}

public class Host extends ContainerBase {
    public Host() {

        this.pipeline = new StandardPipeline(this);
        setBasic(new StandardHostValve());
    }
    @Override
    public Container map(Request request) {
        return getChild("/mytmct");
    }
}

public class StandardHostValve extends ValveBase {
    @Override
    public void invoke(Request request, Response response, ValveContext valveContext) {
        Host host = (Host) getContainer();

        System.out.println("host 处理");
        Context context = (Context) host.map(request);
        context.invoke(request, response);
    }
}

public class Engine extends ContainerBase {

    public Engine() {
        this.pipeline = new StandardPipeline(this);
        setBasic(new StandardEngineValve());
    }

    @Override
    public Container map(Request request) {
        return getChild("localhost");
    }
}

public class StandardEngineValve extends ValveBase {
    
    @Override
    public void invoke(Request request, Response response, ValveContext valveContext) {
        Engine engine = (Engine) getContainer();

        System.out.println("engine 处理");
        Host host = (Host) engine.map(request);
        host.invoke(request, response);
    }
}

整个结构关系,容器间通过组合方式建立关系,通过管道衔接调用,每个容器有一个管道,每个管道有一个基础阀,而基础阀基本上就是处理找到对应的子容器,并调用子容器的invoke方法。

直至调用了wrapper容器,该容器的管道的基础阀加载servlet实现类,并调用service,获取response,至此,tomcat数据脉络我们大概弄明白了,接下来根据这个脉络逐个阅读对应组件的源码,深层次学习各个组件。

源码下载地址://download.csdn.net/download/cygodwg/11985475

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值