• java基础--手写服务器httpserver


    (1)    open system interconnect

      OSI是Open System Interconnection的缩写,意为开放式系统互联 。OSI是一个开放性的通信系统互连参考模型,他是一个定义得非常好的协议规范。OSI模型有7层结构,每层都可以有几个子层。 OSI的7层从上到下分别是 7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层 ;其中高层(即7、6、5、4层)定义了应用程序的功能,下面3层(即3、2、1层)主要面向通过网络的端到端的数据流

    各层功能

    应用层

    与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作的程序员也不关心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协议

        一、

          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连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
      二、
            当浏览器向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方法。
     
         三、 从编程的角度来讲,如果用户通过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("
    ");
                    
                }
                //接收客户端的请求信息
                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;
    
    /**
     * 创建服务器,并启动
     * 
     * 1、请求
     * 2、响应
     * @author Administrator
     *
     */
    public class Server3 {
        private ServerSocket server;
        //换行控制符号
        public static final String CRLF="
    ";
        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="
    ";
        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;
    
    /**
     * 创建服务器,并启动
     * 
     * 1、请求
     * 2、响应
     * @author Administrator
     *
     */
    public class Server4 {
        private ServerSocket server;
        public static final String CRLF="
    ";
        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="
    ";
        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 =""; //接收请求参数 
            
            //1、获取请求方式
            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 ;
            }
            //2、将请求参数封装到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="
    ";
        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;
    
    
    /**
     * 创建服务器,并启动
     * 
     * 1、请求
     * 2、响应
     * @author Administrator
     *
     */
    public class Server7 {
        private ServerSocket server;
        public static final String CRLF="
    ";
        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 {
            //1、获取解析工厂
            SAXParserFactory factory=SAXParserFactory.newInstance();
            //2、从解析工厂获取解析器
            SAXParser parse =factory.newSAXParser();
            //3、加载文档 Document 注册处理器
            //4、编写处理器
            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="
    ";
        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 =""; //接收请求参数 
            
            //1、获取请求方式
            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 ;
            }
            //2、将请求参数封装到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="
    ";
        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;
    
    
    
    
    /**
     * 创建服务器,并启动
     * 
     * 1、请求
     * 2、响应
     * @author Administrator
     *  java 世界里可以不手写的尽量用配置,能用约定的就不用配置, 约定>配置>手写
     */
    public class Server {
        private ServerSocket server;
        public static final String CRLF="
    ";
        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
     
     
     
     
  • 相关阅读:
    POJ 1721 CARDS(置换群)
    HDU 4609 3-idiots(FFT)
    BZOJ 4259 残缺的字符串(FFT)
    HDU 5763 Another Meaning(FFT)
    BZOJ 4503 两个串(FFT)
    hihoCoder 1388 Periodic Signal(FFT)
    HDU 5823 color II(FWT)
    HDU 5768 Lucky7(CRT+容斥原理)
    HDU 5446 Unknown Treasure(Lucas定理+CRT)
    HDU 5741 Helter Skelter(构造法)
  • 原文地址:https://www.cnblogs.com/ou-pc/p/7833172.html
Copyright © 2020-2023  润新知