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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章