Tomcat的运行机制
Tomcat 的运行机制
一、Tomcat运行原理分析
1.Tomcat 是运行在 JVM 中的一个进程。它定义为【中间件】,顾名思义,是一个在Java项目与JVM之间的中间容器。
2.Web 项目的本质,是一大堆的资源文件和方法。Web 项目没有入口方法 ( main 方法),,意味着 Web 项目中的方法不会自动运行起来。
3.Web 项目部署进 Tomcat 的 webapp 中的目的是很明确的,那就是希望 Tomcat 去调用写好的方法去为客户端返回需要的资源和数据。
4. Tomcat 可以运行起来,并调用写好的方法。那么,Tomcat 一定有一个 main 方法。
5. 对于Tomcat 而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进 webapp下后才确定的,由此分析,必然用到了 Java 的反射来实现类的动态加载、实例化、获取方法、调用方法。但是我们部署到 Tomcat 的中的Web项目必须是按照规定好的接口来进行编写,以便进行调用
6.Tomcat 如何确定调用什么方法呢。这取决于客户端的请求,http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show 这样的一个请求,通过 http 协议,在浏览器发往本机的 8080 端口,携带的参数 show 方法,包含此方法的路径为 JayKing.Tomcat.Study,文件名为:index.java。
二、模拟Tomcat运行
1.客户端类
package JayKing.Tomcat.Study;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
private static int port = 5228;
private static String host = "127.0.0.1";
//http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show
public static void main(String[] args) {
try {
Socket con=new Socket(host,port);
System.out.println("请输入URL地址:");
Scanner scanner=new Scanner(System.in);
String info=scanner.nextLine().trim();
Writer writer = new OutputStreamWriter(con.getOutputStream());
writer.write(info);
writer.flush();
writer.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.服务器类
package JayKing.Tomcat.Study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
public class TomcatTest {
private static int post = 5228;
private static UrlUtil urlutil = new UrlUtil();
public static void main(String[] args) {
System.out.println(" My Tomcat is Running");
try {
ServerSocket server = new ServerSocket(post);
while (true) {
Socket socket = server.accept();// 服务器每接受一次请求,就创建一个socket对象
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String info = null;
String infoline = br.readLine();
while (infoline != null) {
info =info+infoline;
infoline = br.readLine();
}
UrlBean url = urlutil.readString(info);
if (url != null) {
String path=url.getPath();
String className = url.getFileName();
String methodName = url.getParameter().trim();
ClassLoader classloader=ClassLoader.getSystemClassLoader();
try {
classloader.loadClass(path+"."+className);
Class<?> getclass=Class.forName(path+"."+className);
Method method=getclass.getMethod(methodName, null);
method.invoke(getclass.newInstance(), null);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.工具类
package JayKing.Tomcat.Study;
//格式:协议://主机号:端口号/目录路径/文件名
//例如: http://127.0.0.1:8080/Test/Manage/index.jsp
public class UrlUtil {
public UrlBean readString(String info) {
UrlBean url = null;
int tag1 = info.indexOf(":");
int tag2 = info.lastIndexOf(":");
int tag3 = info.indexOf("/", tag2);
int tag4 = info.lastIndexOf("/");
int tag5 = info.indexOf("?");
int tag6=info.lastIndexOf(".");
String Protocol = info.substring(0, tag1);
String Host = info.substring(tag1 + 3, tag2);
String Port = info.substring(tag2 + 1, tag3);
String Path = info.substring(tag3 + 1, tag4);
String FileName = info.substring(tag4 + 1, tag6);
String Parameter = info.substring(tag5 + 1, info.trim().length());
if (Host != null && Path != null && FileName != null) {
if (Protocol == null) {
Protocol = "http";
}
if (Port == null) {
Port = "8080";
}
url = new UrlBean(Protocol, Host, Port, Path, FileName, Parameter);
return url;
}
return url;
}
}
4.Model类
package JayKing.Tomcat.Study;
//格式:协议://主机号:端口号/目录路径/文件名
//例如: http://127.0.0.1:8080/Test/Manage/index.jsp?a=1&b=2
public class UrlBean {
private String Protocol;
private String Host;
private String Port;
private String Path;
private String FileName;
private String Parameter;
public UrlBean(String protocol, String host, String port, String path,
String fileName, String parameter) {
super();
Protocol = protocol;
Host = host;
Port = port;
Path = path;
FileName = fileName;
Parameter = parameter;
}
public UrlBean() {
}
public String getProtocol() {
return Protocol;
}
public void setProtocol(String protocol) {
Protocol = protocol;
}
public String getHost() {
return Host;
}
public void setHost(String host) {
Host = host;
}
public String getPort() {
return Port;
}
public void setPort(String port) {
Port = port;
}
public String getPath() {
return Path;
}
public void setPath(String path) {
Path = path;
}
public String getFileName() {
return FileName;
}
public void setFileName(String fileName) {
FileName = fileName;
}
public String getParameter() {
return Parameter;
}
public void setParameter(String parameter) {
Parameter = parameter;
}
}
5.测试方法类
package JayKing.Tomcat.Study;
public class index {
public void show() {
System.out.println("方法已经被执行!");
}
}
6.运行结果
三、Tomcat 原理总结
1. Tomcat 需要 main 方法启动。
2. Tomcat 需要监听本机上的某个端口。
3. Tomcat 需要抓取此端口上来自客户端的链接并获得请求调用的方法与参数。
4. Tomcat 需要根据请求调用的方法,动态地加载方法所在的类,完成类的实例化并通过该实例获得需要的方法最终将请求传入方法执行。
5. 将结果返回给客户端( jsp/html 页面、 json/xml 字符串)。