一、Tomcat運行原理分析
1.Tomcat 是運行在 JVM 中的一個進程。它定義為【中間件】,顧名思義,是一個在Java項目與JVM之間的中間容器。
2.Web 項目的本質(zhì),是一大堆的資源文件和方法。Web 項目沒有入口方法 ( main 方法),,意味著 Web 項目中的方法不會自動運行起來。
3.Web 項目部署進 Tomcat 的 webapp 中的目的是很明確的,那就是希望 Tomcat 去調(diào)用寫好的方法去為客戶端返回需要的資源和數(shù)據(jù)。
4. Tomcat 可以運行起來,并調(diào)用寫好的方法。那么,Tomcat 一定有一個 main 方法。
5. 對于Tomcat 而言,它并不知道我們會有什么樣的方法,這些都只是在項目被部署進 webapp下后才確定的,由此分析,必然用到了 Java 的反射來實現(xiàn)類的動態(tài)加載、實例化、獲取方法、調(diào)用方法。但是我們部署到 Tomcat 的中的Web項目必須是按照規(guī)定好的接口來進行編寫,以便進行調(diào)用
6.Tomcat 如何確定調(diào)用什么方法呢。這取決于客戶端的請求,http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show 這樣的一個請求,通過 http 協(xié)議,在瀏覽器發(fā)往本機的 8080 端口,攜帶的參數(shù) 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.服務(wù)器類
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();// 服務(wù)器每接受一次請求,就創(chuàng)建一個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;
//格式:協(xié)議://主機號:端口號/目錄路徑/文件名
//例如: 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;
//格式:協(xié)議://主機號:端口號/目錄路徑/文件名
//例如: 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("方法已經(jīng)被執(zhí)行!");
}
}
6.運行結(jié)果
三、Tomcat 原理總結(jié)
1. Tomcat 需要 main 方法啟動。
2. Tomcat 需要監(jiān)聽本機上的某個端口。
3. Tomcat 需要抓取此端口上來自客戶端的鏈接并獲得請求調(diào)用的方法與參數(shù)。
4. Tomcat 需要根據(jù)請求調(diào)用的方法,動態(tài)地加載方法所在的類,完成類的實例化并通過該實例獲得需要的方法最終將請求傳入方法執(zhí)行。
5. 將結(jié)果返回給客戶端( jsp/html 頁面、 json/xml 字符串)。
更多建議: