java基礎--手寫服務器httpserver

(1)    open system interconnecthtml

  OSI是Open System Interconnection的縮寫,意爲開放式系統互聯 。OSI是一個開放性的通訊系統互連參考模型,他是一個定義得很是好的協議規範。OSI模型有7層結構,每層均可以有幾個子層。 OSI的7層從上到下分別是 7 應用層 6 表示層 5 會話層 4 傳輸層 3 網絡層 2 數據鏈路層 1 物理層 ;其中高層(即七、六、五、4層)定義了應用程序的功能,下面3層(即三、二、1層)主要面向經過網絡的端到端的數據流java

各層功能

應用層

與其它計算機進行通信的一個應用,它是對應應用程序的通訊服務的。例如,一個沒有通訊功能的字處理程序就不能執行通訊的 代碼,從事字 處理工做的程序員也不關心OSI的第7層。可是,若是添加了一個傳輸文件的選項,那麼字 處理器的程序員就須要實現OSI的第7層。示例:TELNET,HTTP,FTP,NFS,SMTP等。

表示層

這一層的主要功能是定義數據格式及加密。例如,FTP容許你選擇以二進制或ASCII格式傳輸。若是選擇二進制,那麼發送方和接收方不改變文件的內容。若是選擇ASCII格式,發送方將把文本從發送方的 字符集轉換成標準的ASCII後發送數據。在接收方將標準的ASCII轉換成接收方計算機的字符集。示例:加密,ASCII等。

會話層

它定義瞭如何開始、控制和結束一個會話,包括對多個雙向消息的控制和管理,以便在只完成連續消息的一部分時能夠通知應用,從而使表示層看到的數據是連續的,在某些狀況下,若是表示層收到了全部的 數據,則用數據表明表示層。示例:RPC,SQL等。

傳輸層

這層的功能包括是否選擇差錯恢復協議仍是無差錯恢復協議,及在同一 主機上對不一樣應用的 數據流的輸入進行復用,還包括對收到的順序不對的 數據包的從新排序功能。示例:TCP,UDP,SPX。

網絡層

這層對端到端的包傳輸進行定義,它定義了可以標識全部結點的 邏輯地址,還定義了 路由實現的方式和學習的方式。爲了適應 最大傳輸單元長度小於包長度的 傳輸介質,網絡層還定義瞭如何將一個包分解成更小的包的分段方法。示例:IP,IPX等。

數據鏈路層

它定義了在單個鏈路上如何傳輸數據。這些協議與被討論的各類介質有關。示例:ATM,FDDI等。

物理層

OSI的物理層規範是有關 傳輸介質的特這些規範一般也參考了其餘組織制定的標準。鏈接頭、幀、幀的使用、電流、編碼及光調製等都屬於各類物理層規範中的內容。物理層經常使用多個規範完成對全部細節的定義。示例:Rj45,802.3等。

 

分層優勢

   1)人們能夠很容易的討論和學習協議的規範細節。
(2)層間的標準接口方便了工程模塊化。
(3)建立了一個更好的互連環境。
(4)下降了複雜度,使程序更容易修改,產品開發的速度更快。
(5)每層利用緊鄰的下層服務,更容易記住各層的功能。

 

(2)   http協議程序員

    1、web

      HTTP(HyperText Transfer Protocol)是一套計算機經過網絡進行通訊的規則。計算機專家設計出HTTP,使HTTP客戶(如Web瀏覽器)可以從HTTP服務器(Web服務器)請求信息和服務,HTTP目前協議的版本是1.1.HTTP是一種無狀態的協議,無狀態是指Web瀏覽器和Web服務器之間不須要創建持久的鏈接,這意味着當一個客戶端向服務器端發出請求,而後Web服務器返回響應(response),鏈接就被關閉了,在服務器端不保留鏈接的有關信息.HTTP遵循請求(Request)/應答(Response)模型。Web瀏覽器向Web服務器發送請求,Web服務器處理請求並返回適當的應答。全部HTTP鏈接都被構形成一套請求和應答。 編程

       HTTP使用內容類型,是指Web服務器向Web瀏覽器返回的文件都有與之相關的類型。全部這些類型在MIME Internet郵件協議上模型化,即Web服務器告訴Web瀏覽器該文件所具備的種類,是HTML文檔、GIF格式圖像、聲音文件仍是獨立的應用程序。大多數Web瀏覽器都擁有一系列的可配置的輔助應用程序,它們告訴瀏覽器應該如何處理Web服務器發送過來的各類內容類型。數組

      HTTP通訊機制是在一次完整的HTTP通訊過程當中,Web瀏覽器與Web服務器之間將完成下列7個步驟:瀏覽器

(1)    創建TCP鏈接
      在HTTP工做開始以前,Web瀏覽器首先要經過網絡與Web服務器創建鏈接,該鏈接是經過TCP來完成的,該協議與IP協議共同構建Internet,即著名的TCP/IP協議族,所以Internet又被稱做是TCP/IP網       絡。HTTP是比TCP更高層次的應用層協議,根據規則,只有低層協議創建以後才能,才能進行更層協議的鏈接,所以,首先要創建TCP鏈接,通常TCP鏈接的端口號是80
(2)   Web瀏覽器向Web服務器發送請求命令
      一旦創建了TCP鏈接,Web瀏覽器就會向Web服務器發送請求命令
      例如:GET/sample/hello.jsp HTTP/1.1
(3)    Web瀏覽器發送請求頭信息
       瀏覽器發送其請求命令以後,還要以頭信息的形式向Web服務器發送一些別的信息,以後瀏覽器發送了一空白行來通知服務器,它已經結束了該頭信息的發送。
(4)    Web服務器應答
      客戶機向服務器發出請求後,服務器會客戶機回送應答,
       HTTP/1.1 200 OK
      應答的第一部分是協議的版本號和應答狀態碼
(5)    Web服務器發送應答頭信息
       正如客戶端會隨同請求發送關於自身的信息同樣,服務器也會隨同應答向用戶發送關於它本身的數據及被請求的文檔。
(6)    Web服務器向瀏覽器發送數據
      Web服務器向瀏覽器發送頭信息後,它會發送一個空白行來表示頭信息的發送到此爲結束,接着,它就以Content-Type應答頭信息所描述的格式發送用戶所請求的實際數據
(7)    Web服務器關閉TCP鏈接
      通常狀況下,一旦Web服務器向瀏覽器發送了請求數據,它就要關閉TCP鏈接,而後若是瀏覽器或者服務器在其頭信息加入了這行代碼
      Connection:keep-alive
     TCP鏈接在發送後將仍然保持打開狀態,因而,瀏覽器能夠繼續經過相同的鏈接發送請求。保持鏈接節省了爲每一個請求創建新鏈接所需的時間,還節約了網絡帶寬。
  2、
        當瀏覽器向Web服務器發出請求時,它向服務器傳遞了一個數據塊,也就是請求信息,HTTP請求信息由3部分組成:
          l   請求方法  URI  協議/版本
          l   請求頭(Request Header)
          l   請求正文
       for example :

   GET /index.html?name=123&pwd=5456 HTTP/1.1
   Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
  Accept-Language: en-US,zh-CN;q=0.5
  User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2)
  Accept-Encoding: gzip, deflate
  Host: localhost:8888
   Connection: Keep-Alive安全

POST /index.html HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US,zh-CN;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8888
Content-Length: 17
Connection: Keep-Alive
Cache-Control: no-cache服務器

uname=123&pwd=213&fav=0&fav=1&fav=2網絡

 

(1)       請求方法URI協議/版本
   請求的第一行是「方法URL議/版本」:GET/sample.jsp HTTP/1.1
  以上代碼中「GET」表明請求方法,「/sample.jsp」表示URI,「HTTP/1.1表明協議和協議的版本。
  根據HTTP標準,HTTP請求可使用多種請求方法。例如:HTTP1.1支持7種請求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet應用中,最經常使用的方法是GET和POST。
 
(2) 請求頭(Request Header)
請求頭包含許多有關的客戶端環境和請求正文的有用信息。例如,請求頭能夠聲明瀏覽器所用的語言,請求正文的長度等。
 
(3) 請求正文
請求頭和請求正文之間是一個空行,這個行很是重要,它表示請求頭已經結束,接下來的是請求正文。請求正文中能夠包含客戶提交的查詢字符串信息:
name=123&pwd=5456
在以上的例子的HTTP請求中,請求的正文只有一行內容。固然,在實際應用中,HTTP請求正文能夠包含更多的內容。
HTTP請求方法我這裏只討論GET方法與POST方法
      l         GET方法
GET方法是默認的HTTP請求方法,咱們平常用GET方法來提交表單數據,然而用GET方法提交的表單數據只通過了簡單的編碼,同時它將做爲URL的一部分向Web服務器發送,所以,若是使用GET方法來提交表單數據就存在着安全隱患上。例如
從上面的URL請求中,很容易就能夠辯認出表單提交的內容。(?以後的內容)另外因爲GET方法提交的數據是做爲URL請求的一部分因此提交的數據量不能太大
      l         POST方法
POST方法是GET方法的一個替代方法,它主要是向Web服務器提交表單數據,尤爲是大批量的數據。POST方法克服了GET方法的一些缺點。經過POST方法提交表單數據時,數據不是做爲URL請求的一部分而是做爲標準數據傳送給Web服務器,這就克服了GET方法中的信息沒法保密和數據量過小的缺點。所以,出於安全的考慮以及對用戶隱私的尊重,一般表單提交時採用POST方法。
 
     3、 從編程的角度來說,若是用戶經過GET方法提交數據,則數據存放在QUERY_STRING環境變量中,而POST方法提交的數據則能夠從標準輸入流中獲取。
HTTP應答與HTTP請求類似,HTTP響應也由3個部分構成,分別是:
l 協議狀態版本代碼描述
l 響應頭(Response Header)
l 響應正文
    下面是一個HTTP響應的例子:
   HTTP/1.1 200 OK
 Server:Apache Tomcat/5.0.12
  Date:Mon,6Oct2003 13:13:33 GMT
  Content-Type:text/html
  Last-Moified:Mon,6 Oct 2003 13:23:42 GMT
  Content-Length:112
 
  <html>
  <head>
 <title>HTTP響應示例<title>
 </head>
 <body>
 Hello HTTP!
 </body>
 </html>
 協議狀態代碼描述HTTP響應的第一行相似於HTTP請求的第一行,它表示通訊所用的協議是HTTP1.1服務器已經成功的處理了客戶端發出的請求(200表示成功):
          HTTP/1.1 200 Ok
 響應頭(Response Header)響應頭也和請求頭同樣包含許多有用的信息,例如服務器類型、日期時間、內容類型和長度等
 
   響應正文響應正文就是服務器返回的HTML頁面,響應頭和正文之間也必須用空行分隔。
四 
          HTTP應答碼
   HTTP應答碼也稱爲狀態碼,它反映了Web服務器處理HTTP請求狀態。HTTP應答碼由3位數字構成,其中首位數字定義了應答碼的類型:
   1XX-信息類(Information),表示收到Web瀏覽器請求,正在進一步的處理中
   2XX-成功類(Successful),表示用戶請求被正確接收,理解和處理例如:200 OK
      3XX-重定向類(Redirection),表示請求沒有成功,客戶必須採起進一步的動做。
      4XX-客戶端錯誤(Client Error),表示客戶端提交的請求有錯誤 例如:404 NOT
                                    Found,意味着請求中所引用的文檔不存在。
      5XX-服務器錯誤(Server Error)表示服務器不能完成對請求的處理:如 500
       對於咱們Web開發人員來講掌握HTTP應答碼有助於提升Web應用程序調試的效率和準確性。
(3)
package com.zwj.demo01;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 建立服務器,並啓動
 * @author Administrator
 *
 */
public class Server {
    private ServerSocket server;
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        Server server = new Server();
        server.start();
        
        
    }
    /**
     * 啓動方法
     */
    public void start(){        
        try {
            server = new ServerSocket(8888);
            this.receive();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    /**
     * 接收客戶端
     */
    private void receive(){
        try {
            Socket client =server.accept();
            StringBuilder sb =new StringBuilder();
            String msg =null;
            
            BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
            
            while((msg=br.readLine()).length()>0){
                sb.append(msg);
                sb.append("\r\n");
                
            }
            //接收客戶端的請求信息
            String requestInfo =sb.toString().trim();        
            System.out.println(requestInfo);
            
        } catch (IOException e) {
            //e.printStackTrace();
        }
    }
    
    /**
     * 聽着服務器
     */
    public void stop(){
        
    }
    
    
}
Server
package com.zwj.demo01;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 建立服務器,並啓動
 * @author Administrator
 *
 */
public class Server2 {
    private ServerSocket server;
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        Server2 server = new Server2();
        server.start();
        
        
    }
    /**
     * 啓動方法
     */
    public void start(){        
        try {
            server = new ServerSocket(8888);
            this.receive();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    /**
     * 接收客戶端
     */
    private void receive(){
        try {
            Socket client =server.accept();            
            byte[] data=new byte[20480];
            int len =client.getInputStream().read(data);                
            //接收客戶端的請求信息
            String requestInfo=new String(data,0,len).trim();
            System.out.println(requestInfo);
            
        } catch (IOException e) {
            //e.printStackTrace();
        }
    }
    
    /**
     * 聽着服務器
     */
    public void stop(){
        
    }
    
    
}
/*
 POST /log HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Content-Length: 17
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*  ;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
uname=123&pwd=123
 */
Server2
<html>
    <head>
        <title>登陸</title>
    </head>
    <body>
        
        <form method="post" action="http://localhost:8888/index.html">
            用戶名:<input type="text" name="uname" id="uname"/>
            密碼:<input type="password" name="pwd" id="pwd"/>            
            <input type="submit" value="登陸"/>
        </form>
    </body>
</html>
登陸server2HTML頁面

 帶有響應的服務器名稱

package com.zwj.demo01;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/**
 * 建立服務器,並啓動
 * 
 * 一、請求
 * 二、響應
 * @author Administrator
 *
 */
public class Server3 {
    private ServerSocket server;
    //換行控制符號
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        Server3 server = new Server3();
        server.start();
        
        
    }
    /**
     * 啓動方法
     */
    public void start(){        
        try {
            server = new ServerSocket(8888);
            this.receive();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    /**
     * 接收客戶端
     */
    private void receive(){
        try {
            Socket client =server.accept();            
            byte[] data=new byte[20480];
            int len =client.getInputStream().read(data);                
            //接收客戶端的請求信息
            String requestInfo=new String(data,0,len).trim();    
            System.out.println(requestInfo);
            
            
            //響應
            StringBuilder responseContext =new StringBuilder();
            responseContext.append("<html><head><title>HTTP響應示例</title>" +
                    "</head><body>Hello bjsxt!</body></html>");
            
            
            StringBuilder response =new StringBuilder();
            //1)  HTTP協議版本、狀態代碼、描述
            response.append("HTTP/1.1").append(BLANK).append("200").append(BLANK).append("OK").append(CRLF);
            //2)  響應頭(Response Head)
            response.append("Server:bjsxt Server/0.0.1").append(CRLF);
            response.append("Date:").append(new Date()).append(CRLF);
            response.append("Content-type:text/html;charset=GBK").append(CRLF);
            //正文長度 :字節長度
            response.append("Content-Length:").append(responseContext.toString().getBytes().length).append(CRLF);
            //3)正文以前
            response.append(CRLF);
            //4)正文
            response.append(responseContext);
            
            System.out.println(responseContext);
            
            
            //輸出流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
            bw.write(response.toString());
            bw.flush();
            bw.close();
            
        } catch (IOException e) {
        }
    }
    
    /**
     * 聽着服務器
     */
    public void stop(){
        
    }
    
    
}
/*
POST /index.html HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Content-Length: 22
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

uname=zhouwuji&pwd=123
<html><head><title>HTTP響應示例</title></head><body>Hello bjsxt!</body></html>
 */
Server3

 分離response、server

package com.zwj.demo01;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;


/**
 * 封裝響應信息
 * @author Administrator
 *
 */
public class Response {
    //兩個常量
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    //
    private BufferedWriter bw ;
    
    //正文
    private StringBuilder content;
    
    
    //存儲頭信息
    private StringBuilder headInfo;
    //存儲正文長度
    private int len =0;
    public Response(){
        headInfo =new StringBuilder();
        content =new StringBuilder();
        len =0;
    }
    public Response(Socket client){
        this();
        try {
            bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
        } catch (IOException e) {
            headInfo=null;
        }
    }
    public Response(OutputStream os){
        this();
        bw= new BufferedWriter(new OutputStreamWriter(os));
    }
    /**
     * 構建正文
     */
    public Response print(String info){
        content.append(info);
        len+=info.getBytes().length;
        return this;
    }
    
    /**
     * 構建正文+回車
     */
    public Response println(String info){
        content.append(info).append(CRLF);
        len+=(info+CRLF).getBytes().length;
        return this;
    }
    
    /**
     * 構建響應頭
     */
    private void createHeadInfo(int code){
        //1)  HTTP協議版本、狀態代碼、描述
        headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
        switch(code){
            case 200:
                headInfo.append("OK");
                break;
            case 404:
                headInfo.append("NOT FOUND");
                break;
            case 505:
                headInfo.append("SEVER ERROR");
                break;    
        }
        headInfo.append(CRLF);
        //2)  響應頭(Response Head)
        headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF);
        headInfo.append("Date:").append(new Date()).append(CRLF);
        headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
        //正文長度 :字節長度
        headInfo.append("Content-Length:").append(len).append(CRLF);
        headInfo.append(CRLF); //分隔符
    } 
    //推送到客戶端
    void pushToClient(int code) throws IOException{
        if(null==headInfo){
            code =500;
        }
        createHeadInfo(code);
        //頭信息+分割符
        bw.append(headInfo.toString());
        //正文
        bw.append(content.toString());
        bw.flush();
    }
    public void close(){
        CloseUtil.closeIO(bw);
    }
    
    
}
Response
package com.zwj.demo01;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/**
 * 建立服務器,並啓動
 * 
 * 一、請求
 * 二、響應
 * @author Administrator
 *
 */
public class Server4 {
    private ServerSocket server;
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        Server4 server = new Server4();
        server.start();
        
        
    }
    /**
     * 啓動方法
     */
    public void start(){        
        try {
            server = new ServerSocket(8888);
            this.receive();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    /**
     * 接收客戶端
     */
    private void receive(){
        try {
            Socket client =server.accept();            
            byte[] data=new byte[20480];
            int len =client.getInputStream().read(data);                
            //接收客戶端的請求信息
            String requestInfo=new String(data,0,len).trim();    
            System.out.println(requestInfo);
            
            
            //響應
                    
            Response rep=new Response(client.getOutputStream());
            rep.println("<html><head><title>HTTP響應示例</title>");
            rep.println("</head><body>Hello server!</body></html>");
            rep.pushToClient(200);
            
        
            
        } catch (IOException e) {
        }
    }
    
    /**
     * 聽着服務器
     */
    public void stop(){
        
    }
    
    
}
Server4
package com.zwj.demo01;
import java.io.Closeable;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;

public class CloseUtil {
    /**
     * 關閉IO流
     */
    /*
    public static void closeIO(Closeable... io){
        for(Closeable temp:io){
            try {
                if (null != temp) {
                    temp.close();
                }
            } catch (Exception e) {
            }
        }
    }*/
    /**
     * 使用泛型方法實現關閉IO流
     * @param io
     */
    public static <T extends Closeable> void closeIO(T... io){
        for(Closeable temp:io){
            try {
                if (null != temp) {
                    temp.close();
                }
            } catch (Exception e) {
            }
        }
    }
    public static  void closeSocket(ServerSocket socket){
        try {
            if (null != socket) {
                socket.close();
            }
        } catch (Exception e) {
        }
    }
    public static  void closeSocket(Socket socket){
        try {
            if (null != socket) {
                socket.close();
            }
        } catch (Exception e) {
        }
}
    public static  void closeSocket(DatagramSocket socket){
            try {
                if (null != socket) {
                    socket.close();
                }
            } catch (Exception e) {
            }
    }
}
CloseUtil
分離成request、response、servlet、dispatch加入多線程的服務器
package com.zwj.demo01;
import java.io.IOException;
import java.net.Socket;



/**
 * 一個請求與響應 就一個此對象
 * @author Administrator
 *
 */
public class Dispatcher implements Runnable{
    private Socket client;
    private Request req;
    private Response rep;
    private int code=200;
    Dispatcher(Socket client){
        this.client=client;
        try {
            req =new Request(client.getInputStream());
            rep =new Response(client.getOutputStream());
        } catch (IOException e) {
            //e.printStackTrace();
            code =500;
            return ;
        }
    }
    
    
    
    
    
    @Override
    public void run() {
        Servlet serv =new Servlet();
        serv.service(req,rep);                 
        try {
            rep.pushToClient(code); //推送到客戶端
        } catch (IOException e) {
            //e.printStackTrace();
            
        }    
        try {
            rep.pushToClient(500);
        } catch (IOException e) {
            e.printStackTrace();
        }
        CloseUtil.closeSocket(client);
    }

}
Dispatcher
package com.zwj.demo01;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * 封裝request
 * @author Administrator
 *
 */
public class Request {
    //請求方式
    private String method;
    //請求資源
    private String url;
    //請求參數
    private Map<String,List<String>> parameterMapValues;
    //內部
    public static final String CRLF="\r\n";
    private InputStream is;
    //請求的信息
    private String requestInfo;
    
    public Request(){
        method ="";
        url ="";
        parameterMapValues=new HashMap<String,List<String>>();
        requestInfo="";
    }
    public Request(InputStream is){
        this();
        this.is=is;
        try {
            byte[] data = new byte[20480];
            int len = is.read(data);
            requestInfo = new String(data, 0, len);
        } catch (Exception e) {
            return ;
        }
        //分析請求信息
        parseRequestInfo();
    }
    /**
     * 分析請求信息
     */
    private void parseRequestInfo(){
        if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){
            return ;
        }        
        /**
         * =====================================
         * 從信息的首行分解出 :請求方式    請求路徑   請求參數(get可能存在)
         *   如:GET /index.html?name=123&pwd=5456 HTTP/1.1
         * 
         * 若是爲post方式,請求參數可能在 最後正文中
         * 
         * 思路:
         * 1)請求方式 :找出第一個/  截取便可
         * 2)請求資源:找出第一個/   HTTP/ 
         * =====================================
         */
        String paramString =""; //接收請求參數 
        
        //一、獲取請求方式
        String firstLine =requestInfo.substring(0,requestInfo.indexOf(CRLF));
        int idx =requestInfo.indexOf("/"); // /的位置
        this.method=firstLine.substring(0, idx).trim();
        String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
        if(this.method.equalsIgnoreCase("post")){
            this.url=urlStr;        
            paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
            
        }else if(this.method.equalsIgnoreCase("get")){
            if(urlStr.contains("?")){ //是否存在參數
                String[] urlArray=urlStr.split("\\?");
                this.url=urlArray[0];
                paramString=urlArray[1];//接收請求參數 
            }else{
                this.url=urlStr;            
            }
        }
        
    
        //不存在請求參數
        if(paramString.equals("")){
            return ;
        }
        //二、將請求參數封裝到Map中    
        parseParams(paramString);
    }
    private void parseParams(String paramString){
        //分割 將字符串轉成數組
        StringTokenizer token=new StringTokenizer(paramString,"&");
        while(token.hasMoreTokens()){
            String keyValue =token.nextToken();
            String[] keyValues=keyValue.split("=");
            if(keyValues.length==1){
                //Arrays.copyOf 擴容
                keyValues =Arrays.copyOf(keyValues, 2);
                keyValues[1] =null;
            }
            
            String key = keyValues[0].trim();
            
            String value = null==keyValues[1]?null:decode(keyValues[1].trim(),"gbk");
            //轉換成Map 分揀
            if(!parameterMapValues.containsKey(key)){
                parameterMapValues.put(key,new ArrayList<String>());
            }
            
            List<String> values =parameterMapValues.get(key);
            values.add(value);            
        }        
        
    }
    /**
     * 解決中文
     * @param value
     * @param code
     * @return
     */
    private String decode(String value,String code){
        try {
            return java.net.URLDecoder.decode(value, code);
        } catch (UnsupportedEncodingException e) {
            //e.printStackTrace();
        }
        return null;
    }
    /**
     * 根據頁面的name 獲取對應的多個值
     * @param args
     */
    public String[] getParameterValues(String name){
        List<String> values=null;
        if((values=parameterMapValues.get(name))==null){
            return null;
        }else{
            return values.toArray(new String[0]);
        }
    }
    /**
     * 根據頁面的name 獲取對應的單個值
     * @param args
     */
    public String getParameter(String name){
        String[] values =getParameterValues(name);
        if(null==values){
            return null;
        }
        return values[0];
    }
    public String getUrl() {
        return url;
    }
    
    
}
Request
package com.zwj.demo01;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;


/**
 * 封裝響應信息
 * @author Administrator
 *
 */
public class Response {
    //兩個常量
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    //
    private BufferedWriter bw ;
    
    //正文
    private StringBuilder content;
    
    
    //存儲頭信息
    private StringBuilder headInfo;
    //存儲正文長度
    private int len =0;
    public Response(){
        headInfo =new StringBuilder();
        content =new StringBuilder();
        len =0;
    }
    public Response(Socket client){
        this();
        try {
            bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
        } catch (IOException e) {
            headInfo=null;
        }
    }
    public Response(OutputStream os){
        this();
        bw= new BufferedWriter(new OutputStreamWriter(os));
    }
    /**
     * 構建正文
     */
    public Response print(String info){
        content.append(info);
        len+=info.getBytes().length;
        return this;
    }
    
    /**
     * 構建正文+回車
     */
    public Response println(String info){
        content.append(info).append(CRLF);
        len+=(info+CRLF).getBytes().length;
        return this;
    }
    
    /**
     * 構建響應頭
     */
    private void createHeadInfo(int code){
        //1)  HTTP協議版本、狀態代碼、描述
        headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
        switch(code){
            case 200:
                headInfo.append("OK");
                break;
            case 404:
                headInfo.append("NOT FOUND");
                break;
            case 505:
                headInfo.append("SEVER ERROR");
                break;    
        }
        headInfo.append(CRLF);
        //2)  響應頭(Response Head)
        headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF);
        headInfo.append("Date:").append(new Date()).append(CRLF);
        headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
        //正文長度 :字節長度
        headInfo.append("Content-Length:").append(len).append(CRLF);
        headInfo.append(CRLF); //分隔符
    } 
    //推送到客戶端
    void pushToClient(int code) throws IOException{
        if(null==headInfo){
            code =500;
        }
        createHeadInfo(code);
        //頭信息+分割符
        bw.append(headInfo.toString());
        //正文
        bw.append(content.toString());
        bw.flush();
    }
    public void close(){
        CloseUtil.closeIO(bw);
    }
    
    
}
Response
package com.zwj.demo01;

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


/**
 * 建立服務器,並啓動
 * 
 * 一、請求
 * 二、響應
 * @author Administrator
 *
 */
public class Server7 {
    private ServerSocket server;
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    
    private boolean isShutDown= false;
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        Server7 server = new Server7();
        server.start();
        
        
    }
    /**
     * 啓動方法
     */
    public void start(){        
        start(8888);
    
    }
    /**
     * 指定端口的啓動方法
     */
    public void start(int port){        
        try {
            server = new ServerSocket(port);
            this.receive();
        } catch (IOException e) {
            //e.printStackTrace();
            stop();
        }
    
    }
    /**
     * 接收客戶端
     */
    private void receive(){
        try {
            while(!isShutDown){
                new Thread(new Dispatcher(server.accept())).start();
            }
        } catch (IOException e) {
            //e.printStackTrace();
            stop();
        }
        
    }
    
    /**
     * 中止服務器
     */
    public void stop(){
        isShutDown=true;
        CloseUtil.closeSocket(server);
    }
    
    
}
Server7
package com.zwj.demo01;


public class Servlet {
    public void service(Request req,Response rep){
        rep.println("<html><head><title>HTTP響應示例</title>");
        rep.println("</head><body>");
        rep.println("歡迎:").println(req.getParameter("uname")).println("回來");
        rep.println("</body></html>");
    }
}
Servlet
package com.zwj.demo01;
import java.io.Closeable;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;

public class CloseUtil {
    /**
     * 關閉IO流
     */
    /*
    public static void closeIO(Closeable... io){
        for(Closeable temp:io){
            try {
                if (null != temp) {
                    temp.close();
                }
            } catch (Exception e) {
            }
        }
    }*/
    /**
     * 使用泛型方法實現關閉IO流
     * @param io
     */
    public static <T extends Closeable> void closeIO(T... io){
        for(Closeable temp:io){
            try {
                if (null != temp) {
                    temp.close();
                }
            } catch (Exception e) {
            }
        }
    }
    public static  void closeSocket(ServerSocket socket){
        try {
            if (null != socket) {
                socket.close();
            }
        } catch (Exception e) {
        }
    }
    public static  void closeSocket(Socket socket){
        try {
            if (null != socket) {
                socket.close();
            }
        } catch (Exception e) {
        }
}
    public static  void closeSocket(DatagramSocket socket){
            try {
                if (null != socket) {
                    socket.close();
                }
            } catch (Exception e) {
            }
    }
}
CloseUtil

 sax解析xml文件   注:要繼承defaulthandle類 裏面有5個方法 startdocument() 、startelentment()獲得元素名稱 、charcter()獲得values值、endelement()、enddocument()  解析式一行一行解析,

和dom4j是把xml變成dom樹進行解析

package com.bjsxt.xml;

import java.io.IOException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class ParseDemo01 {

    /**
     * @param args
     * @throws SAXException 
     * @throws ParserConfigurationException 
     * @throws IOException 
     */
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        //一、獲取解析工廠
        SAXParserFactory factory=SAXParserFactory.newInstance();
        //二、從解析工廠獲取解析器
        SAXParser parse =factory.newSAXParser();
        //三、加載文檔 Document 註冊處理器
        //四、編寫處理器
        PersonHandler handler=new PersonHandler();
        parse.parse(Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/bjsxt/xml/person.xml")
                ,handler );
        
        List<Person> persons =handler.getPersons();
        for(Person p:persons){
            System.out.println(p.getName()+"-->"+p.getAge());
        }
        
    }

}
ParseDemo01
package com.bjsxt.xml;

public class Person {
    private String name;
    private int age;

    public Person() {
        // TODO Auto-generated constructor stub
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}
Person
<?xml version="1.0" encoding="UTF-8" ?>
<persons>
    <person>
        <name>至尊寶</name>
        <age>9000</age>
    </person>
    <person>
        <name>白晶晶</name>
        <age>7000</age>
    </person>
</persons>
person.xml
package com.bjsxt.xml;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
 * 存儲對象
 * @author Administrator
 *
 */
public class PersonHandler extends DefaultHandler {
    private List<Person> persons;
    private Person person;
    private String tag;//記錄標籤名
    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        //System.out.println("處理文檔開始");
        persons =new ArrayList<Person>();
    }
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        System.out.println("開始一個元素" +qName);
        if(null!=qName){
            tag=qName;
        }
        if(null!=qName &&qName.equals("person")){
            person =new Person();
        }
    }

    
    
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        String str =new String(ch,start,length);
        if(null!=tag &&tag.equals("name")){
            //System.out.println(new String(ch,start,length));
            person.setName(str);
        }else if(null!=tag &&tag.equals("age")){
            Integer age = Integer.valueOf(str);
            person.setAge(age);
        }
    }
    
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        //System.out.println("結束一個元素" +qName);
        if(qName.equals("person")){
            this.persons.add(person);
        }
        tag =null;
    }
    
    @Override
    public void endDocument() throws SAXException {
        System.out.println("文檔處理結束");
    }
    public List<Person> getPersons() {
        return persons;
    }
    public void setPersons(List<Person> persons) {
        this.persons = persons;
    }

    
    

    
    

}
PersonHandler

簡單的服務器最終版本

 

 
package com.zwj.server;
import java.io.IOException;
import java.net.Socket;

import com.zwj.servlet.Servlet;
import com.zwj.util.CloseUtil;


/**
 * 一個請求與響應 就一個此對象
 * @author Administrator
 *
 */
public class Dispatcher implements Runnable{
    private Socket client;
    private Request req;
    private Response rep;
    private int code=200;
    Dispatcher(Socket client){
        this.client=client;
        try {
            req =new Request(client.getInputStream());
            rep =new Response(client.getOutputStream());
        } catch (IOException e) {
            //e.printStackTrace();
            code =500;
            return ;
        }
    }
    
    
    
    
    
    @Override
    public void run() {
        try {
            Servlet serv =WebApp.getServlet(req.getUrl());
            if(null==serv){
                this.code=404; //找不處處理
            }else{
                serv.service(req, rep);
            }
            rep.pushToClient(code); //推送到客戶端
        }catch (Exception e) {
            e.printStackTrace();
            this.code=500;
        }    
        try {
            rep.pushToClient(500);
        } catch (IOException e) {
            e.printStackTrace();
        }
        req.close();
        rep.close();        
        CloseUtil.closeSocket(client);
    }

}
Dispatcher
package com.zwj.server;

/*  
 <servlet>
         <servlet-name>login</servlet-name>
         <servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class>
     </servlet> 
 */


public class Entity {
    private String name;
    private String clz;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getClz() {
        return clz;
    }
    public void setClz(String clz) {
        this.clz = clz;
    }
    
}
Entity
package com.zwj.server;
import java.util.ArrayList;
import java.util.List;

/*
 <servlet-mapping>
         <servlet-name>login</servlet-name>
         <url-pattern>/login</url-pattern> 
     </servlet-mapping>
      <servlet-mapping>
         <servlet-name>login</servlet-name>
         <url-pattern>/log</url-pattern> 
     </servlet-mapping>
 
  
 */
public class Mapping {
    private String name;
    private List<String> urlPattern;
    
    public Mapping(){
        urlPattern =new ArrayList<String>();
    }
    
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<String> getUrlPattern() {
        return urlPattern;
    }
    public void setUrlPattern(List<String> urlPattern) {
        this.urlPattern = urlPattern;
    }
    
    
    
}
Mapping
package com.zwj.server;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import com.zwj.util.CloseUtil;



/**
 * 封裝request
 * @author Administrator
 *
 */
public class Request {
    //請求方式
    private String method;
    //請求資源
    private String url;
    //請求參數
    private Map<String,List<String>> parameterMapValues;
    
    //內部
    public static final String CRLF="\r\n";
    private InputStream is;
    private String requestInfo;
    
    public Request(){
        method ="";
        url ="";
        parameterMapValues=new HashMap<String,List<String>>();
        requestInfo="";
    }
    public Request(InputStream is){
        this();
        this.is=is;
        try {
            byte[] data = new byte[20480];
            int len = is.read(data);
            requestInfo = new String(data, 0, len);
        } catch (Exception e) {
            return ;
        }
        //分析請求信息
        parseRequestInfo();
    }
    /**
     * 分析請求信息
     */
    private void parseRequestInfo(){
        if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){
            return ;
        }        
        /**
         * =====================================
         * 從信息的首行分解出 :請求方式    請求路徑   請求參數(get可能存在)
         *   如:GET /index.html?name=123&pwd=5456 HTTP/1.1
         * 
         * 若是爲post方式,請求參數可能在 最後正文中
         * 
         * 思路:
         * 1)請求方式 :找出第一個/  截取便可
         * 2)請求資源:找出第一個/   HTTP/ 
         * =====================================
         */
        String paramString =""; //接收請求參數 
        
        //一、獲取請求方式
        String firstLine =requestInfo.substring(0,requestInfo.indexOf(CRLF));
        int idx =requestInfo.indexOf("/"); // /的位置
        this.method=firstLine.substring(0, idx).trim();
        String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
        if(this.method.equalsIgnoreCase("post")){
            this.url=urlStr;        
            paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
            
        }else if(this.method.equalsIgnoreCase("get")){
            if(urlStr.contains("?")){ //是否存在參數
                String[] urlArray=urlStr.split("\\?");
                this.url=urlArray[0];
                paramString=urlArray[1];//接收請求參數 
            }else{
                this.url=urlStr;            
            }
        }
        
    
        //不存在請求參數
        if(paramString.equals("")){
            return ;
        }
        //二、將請求參數封裝到Map中    
        parseParams(paramString);
    }
    private void parseParams(String paramString){
        //分割 將字符串轉成數組
        StringTokenizer token=new StringTokenizer(paramString,"&");
        while(token.hasMoreTokens()){
            String keyValue =token.nextToken();
            String[] keyValues=keyValue.split("=");
            if(keyValues.length==1){
                keyValues =Arrays.copyOf(keyValues, 2);
                keyValues[1] =null;
            }
            
            String key = keyValues[0].trim();
            String value = null==keyValues[1]?null:decode(keyValues[1].trim(),"gbk");
            //轉換成Map 分揀
            if(!parameterMapValues.containsKey(key)){
                parameterMapValues.put(key,new ArrayList<String>());
            }
            
            List<String> values =parameterMapValues.get(key);
            values.add(value);            
        }        
        
    }
    /**
     * 解決中文
     * @param value
     * @param code
     * @return
     */
    private String decode(String value,String code){
        try {
            return java.net.URLDecoder.decode(value, code);
        } catch (UnsupportedEncodingException e) {
            //e.printStackTrace();
        }
        return null;
    }
    /**
     * 根據頁面的name 獲取對應的多個值
     * @param args
     */
    public String[] getParameterValues(String name){
        List<String> values=null;
        if((values=parameterMapValues.get(name))==null){
            return null;
        }else{
            return values.toArray(new String[0]);
        }
    }
    /**
     * 根據頁面的name 獲取對應的單個值
     * @param args
     */
    public String getParameter(String name){
        String[] values =getParameterValues(name);
        if(null==values){
            return null;
        }
        return values[0];
    }
    public String getUrl() {
        return url;
    }
    
    public void close(){
        CloseUtil.closeIO(is);
    }
}
Request
package com.zwj.server;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;

import com.zwj.util.CloseUtil;


/**
 * 封裝響應信息
 * @author Administrator
 *
 */
public class Response {
    //兩個常量
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    //
    private BufferedWriter bw ;
    
    //正文
    private StringBuilder content;
    
    
    //存儲頭信息
    private StringBuilder headInfo;
    //存儲正文長度
    private int len =0;
    public Response(){
        headInfo =new StringBuilder();
        content =new StringBuilder();
        len =0;
    }
    public Response(Socket client){
        this();
        try {
            bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
        } catch (IOException e) {
            headInfo=null;
        }
    }
    public Response(OutputStream os){
        this();
        bw= new BufferedWriter(new OutputStreamWriter(os));
    }
    /**
     * 構建正文
     */
    public Response print(String info){
        content.append(info);
        len+=info.getBytes().length;
        return this;
    }
    
    /**
     * 構建正文+回車
     */
    public Response println(String info){
        content.append(info).append(CRLF);
        len+=(info+CRLF).getBytes().length;
        return this;
    }
    
    /**
     * 構建響應頭
     */
    private void createHeadInfo(int code){
        //1)  HTTP協議版本、狀態代碼、描述
        headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
        switch(code){
            case 200:
                headInfo.append("OK");
                break;
            case 404:
                headInfo.append("NOT FOUND");
                break;
            case 505:
                headInfo.append("SEVER ERROR");
                break;    
        }
        headInfo.append(CRLF);
        //2)  響應頭(Response Head)
        headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF);
        headInfo.append("Date:").append(new Date()).append(CRLF);
        headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
        //正文長度 :字節長度
        headInfo.append("Content-Length:").append(len).append(CRLF);
        headInfo.append(CRLF); //分隔符
    } 
    //推送到客戶端
    void pushToClient(int code) throws IOException{
        if(null==headInfo){
            code =500;
        }
        createHeadInfo(code);
        //頭信息+分割符
        bw.append(headInfo.toString());
        //正文
        bw.append(content.toString());
        bw.flush();
    }
    public void close(){
        CloseUtil.closeIO(bw);
    }
    
    
}
Response
package com.zwj.server;
import java.io.IOException;
import java.net.ServerSocket;
import com.zwj.util.CloseUtil;




/**
 * 建立服務器,並啓動
 * 
 * 一、請求
 * 二、響應
 * @author Administrator
 *  java 世界裏能夠不手寫的儘可能用配置,能用約定的就不用配置, 約定>配置>手寫
 */
public class Server {
    private ServerSocket server;
    public static final String CRLF="\r\n";
    public static final String BLANK=" ";
    private boolean isShutDown= false;
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        Server server = new Server();
        server.start();
        
        
    }
    /**
     * 啓動方法
     */
    public void start(){        
        start(8888);
    
    }
    /**
     * 指定端口的啓動方法
     */
    public void start(int port){        
        try {
            server = new ServerSocket(port);
            this.receive();
        } catch (IOException e) {
            //e.printStackTrace();
            stop();
        }
    
    }
    /**
     * 接收客戶端
     */
    private void receive(){
        try {
            while(!isShutDown){
                new Thread(new Dispatcher(server.accept())).start();
            }
        } catch (IOException e) {
            //e.printStackTrace();
            stop();
        }
        
    }
    
    /**
     * 中止服務器
     */
    public void stop(){
        isShutDown=true;
        CloseUtil.closeSocket(server);
    }
    
    
}
Server
package com.zwj.server;
import java.util.HashMap;
import java.util.Map;

/**
 * 上下文
 * @author Administrator
 *
 */
public class ServletContext {
    //爲每個servlet取個別名  
    // login  -->com.bjsxt.server.demo03.LoginServlet
    private Map<String,String> servlet ;
    //url -->login
    //   /log -->login
    //   /login -->login
    private Map<String,String> mapping;
    
    ServletContext(){
        servlet =new HashMap<String,String>();
        mapping =new HashMap<String,String>();
    }
    
    
    public Map<String, String> getServlet() {
        return servlet;
    }
    public void setServlet(Map<String, String> servlet) {
        this.servlet = servlet;
    }
    public Map<String, String> getMapping() {
        return mapping;
    }
    public void setMapping(Map<String, String> mapping) {
        this.mapping = mapping;
    }
    
    
    
    
}
ServletContext
package com.zwj.server;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import com.zwj.servlet.Servlet;


public class WebApp {
    private static ServletContext contxt;
    static{
        try {
            //獲取解析工廠
            SAXParserFactory factory = SAXParserFactory.newInstance();
            //獲取解析器
            SAXParser sax = factory.newSAXParser();
            //指定xml+處理器
            WebHandler web = new WebHandler();
            sax.parse(Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("WEB_INFO/web.xml"), web);
            
            
            //將list 轉成Map
            contxt =new ServletContext();            
            Map<String,String> servlet =contxt.getServlet();
            
            //servlet-name  servlet-class 
            for(Entity entity:web.getEntityList()){
                servlet.put(entity.getName(), entity.getClz());
                
            }
            
            //url-pattern servlet-name            
            Map<String,String> mapping =contxt.getMapping();
            for(Mapping mapp:web.getMappingList()){
                List<String> urls =mapp.getUrlPattern();
                for(String url:urls ){
                    mapping.put(url, mapp.getName());
                }
            }
            
        } catch (Exception e) {
            
        }
        
        
    }
    
    public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
        if((null==url)||(url=url.trim()).equals("")){
            return null;
        }
        //根據字符串(完整路徑)建立對象
        //return contxt.getServlet().get(contxt.getMapping().get(url));
        String name=contxt.getServlet().get(contxt.getMapping().get(url));
        return (Servlet)Class.forName(name).newInstance();//確保空構造存在
    }
}
WebApp
package com.zwj.server;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class WebHandler extends DefaultHandler{
    private List<Entity> entityList;
    private List<Mapping> mappingList;
    private Entity entity;
    private Mapping mapping;
    private String beginTag ;    
    private boolean isMap; 
    
    
     @Override
    public void startDocument() throws SAXException {
        //文檔解析開始
         entityList =new ArrayList<Entity>() ;
         mappingList =new ArrayList<Mapping>() ;
         
    }
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        //開始元素
        if(null!=qName){
            beginTag=qName;
            if(qName.equals("servlet")){
                isMap=false;
                entity=new Entity();
            }else if(qName.equals("servlet-mapping")){
                isMap=true;
                mapping=new Mapping();
            }        
            
        }
        
    }
    
    
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //處理內容  
        if(null!=beginTag){
            String str =new String(ch,start,length);
            if(isMap ){
                if(beginTag.equals("servlet-name")){
                    mapping.setName(str);
                }else if(beginTag.equals("url-pattern")){
                    mapping.getUrlPattern().add(str);
                }
            }else{
                if(beginTag.equals("servlet-name")){
                    entity.setName(str);                    
                }else if(beginTag.equals("servlet-class")){
                    entity.setClz(str);
                }
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        //結束元素
        if(null!=qName){
            
            if(qName.equals("servlet")){
                entityList.add(entity);
            }else if(qName.equals("servlet-mapping")){
                mappingList.add(mapping);
            }
            
        }
        beginTag=null;
    }

    
    @Override
    public void endDocument() throws SAXException {
        //文檔解析結束
    }

    
    /*public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        //獲取解析工廠
        SAXParserFactory factory =SAXParserFactory.newInstance();
        //獲取解析器
        SAXParser sax =factory.newSAXParser();
        //指定xml+處理器
        WebHandler web = new WebHandler();
        sax.parse(Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/bjsxt/server/demo4/web.xml")
                ,web);
        
        System.out.println(web.getEntityList());
    }*/
    public List<Entity> getEntityList() {
        return entityList;
    }
    public void setEntityList(List<Entity> entityList) {
        this.entityList = entityList;
    }
    public List<Mapping> getMappingList() {
        return mappingList;
    }
    public void setMappingList(List<Mapping> mappingList) {
        this.mappingList = mappingList;
    }
    
    
    

}
WebHandler
package com.zwj.servlet;

import com.zwj.server.Request;
import com.zwj.server.Response;

public class LoginWeb extends Servlet {

    @Override
    public void doGet(Request req, Response rep) throws Exception {
        rep.println("success.....");
    }

    @Override
    public void doPost(Request req, Response rep) throws Exception {
        // TODO Auto-generated method stub
        
    }

}
LoginWeb
package com.zwj.servlet;

import com.zwj.server.Request;
import com.zwj.server.Response;


/**
 * 抽象爲一個父類
 * @author Administrator
 *
 */
public abstract class Servlet {
    public void service(Request req,Response rep) throws Exception{
        this.doGet(req,rep);
        this.doPost(req,rep);
    }
    
    protected abstract void doGet(Request req,Response rep) throws Exception;
    protected abstract void doPost(Request req,Response rep) throws Exception;
}
Servlet
package com.zwj.util;


import java.io.Closeable;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;

public class CloseUtil {
    /**
     * 關閉IO流
     */
    /*
    public static void closeIO(Closeable... io){
        for(Closeable temp:io){
            try {
                if (null != temp) {
                    temp.close();
                }
            } catch (Exception e) {
            }
        }
    }*/
    /**
     * 使用泛型方法實現關閉IO流
     * @param io
     */
    public static <T extends Closeable> void closeIO(T... io){
        for(Closeable temp:io){
            try {
                if (null != temp) {
                    temp.close();
                }
            } catch (Exception e) {
            }
        }
    }
    public static  void closeSocket(ServerSocket socket){
        try {
            if (null != socket) {
                socket.close();
            }
        } catch (Exception e) {
        }
    }
    public static  void closeSocket(Socket socket){
        try {
            if (null != socket) {
                socket.close();
            }
        } catch (Exception e) {
        }
}
    public static  void closeSocket(DatagramSocket socket){
            try {
                if (null != socket) {
                    socket.close();
                }
            } catch (Exception e) {
            }
    }
}
CloseUtil
<?xml version="1.0" encoding="UTF-8"?>

 <web-app>
     <servlet>
         <servlet-name>login</servlet-name>
         <servlet-class>com.zwj.servlet.LoginWeb</servlet-class>
     </servlet>
      <servlet-mapping>
          <servlet-name>login</servlet-name>
          <url-pattern>/g</url-pattern>
          <url-pattern>/y</url-pattern>
      </servlet-mapping>
 </web-app>
web.xml
相關文章
相關標籤/搜索