程式模擬tomcat伺服器執行過程

不設限發表於2011-12-12

WebServer.java類


import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


public class WebServer {
/**伺服器預設使用的埠號**/
public static final int HTTP_PORT=8080;
//定義伺服器的socket
private ServerSocket serverSocket;
/**
* WebServer類的啟動方法,可以通過命令列引數指定當前的Web伺服器所使用的埠號
*/
public static void main(String[] args) {
WebServer webServer=new WebServer();
if(args.length==1){
//使用指定的埠號
webServer.startServer(Integer.parseInt(args[0]));
} else {
//使用預設的埠號
webServer.startServer(HTTP_PORT);
}

}

public void startServer(int port) {
try {
//例項化ServerSocket
serverSocket=new ServerSocket(port);
System.out.println("server start at..."+port);
while(true) {
Socket socket=serverSocket.accept();
//通過執行緒的方式來處理客戶的請求
new Processor(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}

}

}


Processor類



import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
/**
 * 處理一個HTTP使用者請求的執行緒類
 */
public class Processor extends Thread {
/**預設的伺服器存放訪問內容的目錄**/
private static final String WEB_ROOT="C:\\Users\\Administrator\\Workspaces\\MyEclipse 8.5\\webserver_1\\htdocs";
//定義列印流
private PrintStream out;
//定義輸入流
private InputStream in;
/**預設的構造方法**/
public Processor(Socket socket) {
try {
this.in=socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
this.out=new PrintStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}

}

@Override
public void run() {
try {
//獲取檔名
String fileName=getFile(in);
//讀取檔案
readFile(fileName);
} catch (IOException e) {
e.printStackTrace();
}

}

/**
* 解析客戶端傳送過來的所有HTTP請求,如果是符合協議內容的,就分析出客戶機要訪問的檔案的名字,並且返回檔名
*/
public String getFile(InputStream in) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String content=br.readLine();
if(content.length()==0) {
sendError(400, "Client invoke error");
return null;
}

//分析客戶端傳送過來的引數
//傳送過來的請求包括三部分
String[] request=content.split(" ");
if(request.length!=3) {
sendError(400, "Client invoke error");
return null;
}

//第一部分是state code
String stateCode=request[0];
//第二部分是請求的檔案
String fileName=request[1];
//第三部分是版本資訊
String httpVersion=request[2];
System.out.println("state code: "+stateCode+"\tfileName: "+fileName+"\thttpVersion: "+httpVersion);
return fileName;
}

/**
* 處理呼叫一個檔案的請求
*/
public void readFile(String fileName) throws IOException {
File f=new File(WEB_ROOT+fileName);
if(!f.exists()) {
sendError(400, "Client invoke error");
return;
}
FileInputStream in=new FileInputStream(f);
byte[] b=new byte[(int) f.length()];
in.read(b);
out.println("HTTP/1.0 200 sendFile");
out.println("Content-length: " + b.length);
out.println();
out.write(b);
out.flush();
out.close();
in.close();
}

public void sendError(int errNum,String errMsg) {
out.println("HTTP/1.0 " + errNum + " " + errMsg);
out.println("Content-type: text/html");
out.println();
out.println("<html>");
out.println("<head><title>Error " + errNum + "--" + errMsg + "</title></head>");
out.println("<h1>" + errNum + " " + errMsg + "</h1>");
out.println("</html>");
out.println();
out.flush();
out.close();
}

}


web請求的執行過程:客戶端傳送請求->請求以流的方式傳送到伺服器->伺服器接受流->讀取流內容->把內容儲存在String中
->把String按照規則分開為三部分->獲取第二部分(客戶請求的檔名)->查詢資源->把資源以流的讀取出來存入陣列->使用
printStream把流給write()給客戶端;


tomcat執行步驟:通過url-pattern->servlet-name->servlet-class->編譯->返回jsp檔案


路徑的配置:

1.訪問action的時候路徑的配置

action的路徑配置,action的配置原理是這樣的,客戶端在位址列輸入了一個訪問的servlet,這個時候客戶點選

回車瀏覽器就會把你所輸入的路徑給傳送到了伺服器了,這個時候當tomcat接受到了請求之後它就會對請求進行處理,它會先分

離出你要訪問的哪個檔案,之後去web.xml裡面去查詢對應的servlet之後根據影射關係找到檔案所在的地方,然後執行對應的servlet

裡面的方法。

例如:/webproject2_1/login/loginServlet

這裡面"/"代表的是當前工程所在的根根目錄,而webproject2_1就是當前網站所在工程,然後後面的就是我要請求的檔案了,這個時候

因為我請求的是servlet,所以這個時候tomcat會自動的去web.xml中去尋找對應<url-pattern>為/login/loginServlet的servlet對應的

servlet的servlet-name,之後根據servlet-name再去找這個名稱對應的servlet所在的位置去呼叫這個servlet裡面的方法執行,預設的

是get方法

2.訪問jsp和html時的路徑配置

如果是訪問的jsp頁面這個時候因為在web.xml中並沒有對於jsp頁面位置的配置,但是因為你要訪問的任何的東西都會告訴瀏覽器

你要訪問的資源的名字,比如html它是頁面,很顯然,tomcat也還是會去web.xml中去找,看看有沒有相關的配置,如果沒有就直接去tomcat

的根目錄裡面去尋找,總之如果有了web.xml,tomcat總是先去匹配是不是存在這樣的servlet然後再去尋找是不是直接的存在這樣的檔案

如果找到了,就把頁面返回給你,如果找不到對不起就返回錯誤了也許你會說我訪問的檔案不是直接的在web-root下的,而是在web-root下的test

資料夾下的a.html,不論你檔案在哪裡,你要訪問它你都需要給它提供路徑的,沒有路徑它不會自動的去尋找的。就算是它會自動尋找

當出現了兩個檔名一樣的檔案的時候,在不同的目錄下,你說讓它返回誰?

相關文章