首先我们知道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