Tomcat作為開源的輕量級(jí)WEB服務(wù)器,雖然不是很適合某些大型項(xiàng)目,但是它開源,讀其源代碼可以很好的提高我們的編程功底和設(shè)計(jì)思維。Tomcat中用到了很多比較好的設(shè)計(jì)模式,其中代碼風(fēng)格也很值得我們?nèi)バХ隆G瓣囎涌戳薚omcat源碼分析這本書,特此過來分享分享自己的學(xué)習(xí)過程記錄。說得不好,大神不要噴我。
也不廢話了,直入主題上代碼。Tomcat是什么,Tomcat是一個(gè)web服務(wù)器,能夠接收請(qǐng)求,作出響應(yīng)。接收請(qǐng)求,作出響應(yīng)讓我們聯(lián)想到Socket編程。我們可以起一個(gè)線程服務(wù)ServerSocket來監(jiān)聽本機(jī)的8080端口(可配置),然后就可以在瀏覽器上訪問http://localhost:8080/index.html,這個(gè)時(shí)候就可以通過socket的inputstream獲取到瀏覽器封裝的HTTP請(qǐng)求了,然后就可以針對(duì)這個(gè)請(qǐng)求來大做文章。以下是服務(wù)端的代碼
1 package cn.tim.server.core; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.net.InetAddress; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 11 12 /** 13 * HTTP服務(wù)器,主類 14 * @author TIM 15 * 16 */ 17 public class HttpServer { 18 19 20 /** 21 * 端口 22 */ 23 public int PORT = 8080 ; 24 25 26 /** 27 * 關(guān)閉指令 28 */ 29 public final static String SHUTDOWN = "SHUTDOWN" ; 30 31 32 /** 33 * webroot根目錄 34 */ 35 public static final String WEB_ROOT = 36 System.getProperty("user.dir") + File.separator + "WebRoot" ; 37 38 39 public static void main(String[] args) { 40 41 new HttpServer().await(); 42 43 } 44 45 46 /** 47 * 線程監(jiān)聽 48 */ 49 private void await() { 50 51 ServerSocket server = null ; 52 try { 53 server = new ServerSocket(PORT,1 , 54 InetAddress.getByName("127.0.0.1" )); 55 } catch (Exception e) { 56 e.printStackTrace(); 57 } 58 59 boolean shutdown = false ; 60 while (! shutdown) { 61 Socket client = null ; 62 InputStream in = null ; 63 OutputStream out = null ; 64 try { 65 // 獲取到請(qǐng)求socket 66 client = server.accept(); 67 in = client.getInputStream(); 68 out = client.getOutputStream(); 69 70 // 生成request同時(shí)解析請(qǐng)求 71 Request request = new Request(in); 72 request.parse(); 73 74 // 生成response 75 Response response = new Response(out); 76 response.setRequest(request); 77 // 根據(jù)資源定位符發(fā)送對(duì)應(yīng)資源 78 response.sendStaticResource(); 79 client.close(); 80 81 shutdown = request.getUri().equals(SHUTDOWN); 82 } catch (IOException e) { 83 // TODO Auto-generated catch block 84 e.printStackTrace(); 85 continue ; 86 } 87 88 } 89 90 } 91 92 }
既然服務(wù)端HttpServer都出來了,Request都干些什么,request顧名思義,請(qǐng)求肯定是封裝請(qǐng)求的一個(gè)JAVA類,肯定要能夠解析HTTP請(qǐng)求,例如訪問靜態(tài)資源,就得獲取到靜態(tài)資源的資源定位符uri。
HTTP請(qǐng)求Request類:
1 GET /index.html HTTP/1.1 2 Accept: text/html, application/xhtml+xml, * /* 3 Accept-Language: zh-CN 4 User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; MALCJS) 5 Accept-Encoding: gzip, deflate 6 Host: localhost:8080 7 DNT: 1 8 Connection: Keep-Alive 9 Cookie: principal=user:admin__password:admin
1 package cn.tim.server.core; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 /** 7 * 封裝請(qǐng)求 8 * @author TIM 9 * 10 */ 11 public class Request { 12 13 14 /** 15 * 請(qǐng)求輸入流 16 */ 17 private InputStream in; 18 19 20 /** 21 * 資源定位符 22 */ 23 private String uri; 24 25 26 /** 27 * 初始化request,傳入socket輸入流 28 * @param in 29 */ 30 public Request(InputStream in) { 31 this .in = in; 32 } 33 34 35 /** 36 * 根據(jù)請(qǐng)求字符串解析請(qǐng)求 37 */ 38 public void parse() { 39 40 try { 41 byte [] bytes = new byte [2048 ]; 42 int i = in.read(bytes); 43 44 StringBuffer buffer = new StringBuffer(2048 ); 45 for ( int j=0; j<i; j++ ) { 46 buffer.append(( char )bytes[j]); 47 } 48 System.out.println(buffer.toString()); 49 uri = parseUri(buffer.toString()); 50 System.out.println(uri); 51 } catch (IOException e) { 52 // TODO Auto-generated catch block 53 e.printStackTrace(); 54 } 55 56 } 57 58 59 /** 60 * 解析出資源定位符uri,實(shí)際上就是用字符串分拆獲取到GET /index.html HTTP/1.1中的/index,html 61 * @return 62 */ 63 private String parseUri(String requestString) { 64 65 int index1 = requestString.indexOf(" " ); 66 if (index1 != -1 ) { 67 int index2 = requestString.indexOf(" ", index1+1 ); 68 if (index2> index1) { 69 return requestString.substring(index1+1 , index2); 70 } 71 } 72 return null ; 73 } 74 75 76 public InputStream getIn() { 77 return in; 78 } 79 80 81 public String getUri() { 82 return uri; 83 } 84 85 }
獲取到資源定位符,接下來就是根據(jù)資源定位符來作出相應(yīng),當(dāng)然實(shí)際的Tomcat處理方式肯定是很復(fù)雜的,我們只模仿其中簡單的方式,訪問靜態(tài)資源。
Response類:
1 package cn.tim.server.core; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 9 public class Response { 10 11 12 /** 13 * 輸出 14 */ 15 private OutputStream out; 16 17 18 /** 19 * 緩沖大小 20 */ 21 public final static int BUFFER_SIZE = 2048 ; 22 23 24 /** 25 * 請(qǐng)求,根據(jù)請(qǐng)求作出對(duì)應(yīng)的響應(yīng) 26 */ 27 private Request request; 28 29 30 public Response(OutputStream out) { 31 this .out = out; 32 } 33 34 35 /** 36 * 發(fā)送靜態(tài)資源 37 */ 38 public void sendStaticResource() { 39 40 byte [] bytes = new byte [BUFFER_SIZE]; 41 InputStream in = null ; 42 try { 43 File file = new File(HttpServer.WEB_ROOT, request.getUri()); 44 // 請(qǐng)求的資源存在 45 if (file.exists()) { 46 in = new FileInputStream(file); 47 int ch; 48 if ((ch=in.read(bytes, 0, BUFFER_SIZE))!=-1 ) { 49 out.write(bytes, 0 , ch); 50 } 51 } 52 // 請(qǐng)求資源不存在報(bào)404 53 else { 54 String errorMessage = "HTTP/1.1 404 File Not Found\r\n" + 55 "Content-Type: text/html\r\n" + 56 "Content-Length: 23\r\n" + 57 "\r\n" + 58 "<h1>File Not Found</h1>" ; 59 out.write(errorMessage.getBytes()); 60 } 61 } catch (Exception e) { 62 // TODO Auto-generated catch block 63 e.printStackTrace(); 64 } finally { 65 if (in!= null ) 66 try { 67 in.close(); 68 } catch (IOException e) { 69 // TODO Auto-generated catch block 70 e.printStackTrace(); 71 } 72 } 73 74 } 75 76 77 public void setRequest(Request request) { 78 this .request = request; 79 } 80 81 }
這樣,一個(gè)簡單的Web服務(wù)器就實(shí)現(xiàn)了,可以訪問靜態(tài)資源,直接在瀏覽器上訪問,沒有找到對(duì)應(yīng)的資源還可以報(bào)404錯(cuò)誤。今天就寫到這里,繼續(xù)努力。。。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
