美文网首页
通过线程池实现一个简单的Web服务器

通过线程池实现一个简单的Web服务器

作者: 全栈未遂工程师 | 来源:发表于2016-07-08 16:36 被阅读140次

    测试步骤:

    • 执行HttpServerMain.java
    • 浏览器访问http://127.0.0.1:8181/test.html

    SimpleHttpServer.java

    该类定义了对端口的监听,对每一个请求的具体处理,和开启服务器。

    package com.httpServerTest;
    
    import java.io.BufferedReader;
    import java.io.ByteArrayOutputStream;
    import java.io.Closeable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import com.threadpooltest.DefaultThreadPool;
    import com.threadpooltest.ThreadPool;
    
    public class SimpleHttpServer {
        //处理HttpRequest的线程池
        static ThreadPool<HttpRequestHandler> threadPool = new DefaultThreadPool<HttpRequestHandler>(1);
        static String basePath;
        static ServerSocket serverSocket;
        //服务监听端口
        static int port = 8181;
        
        public static void setPort(int port){
            if(port>0){
                SimpleHttpServer.port = port;
            }
        }
        public static void setBasePath(String basePath){
            if(basePath != null && new File(basePath).exists() && new File(basePath).isDirectory()){
                SimpleHttpServer.basePath = basePath;
            }
        }
        //启动SimpleHttpServer
        public static void start() throws Exception{
            serverSocket = new ServerSocket(port);
            Socket socket = null;
            while((socket=serverSocket.accept()) != null){
                //接收一个客户端Socket,生成一个HttpRequestHandler,放入线程池中执行
                threadPool.execute(new HttpRequestHandler(socket));
            }
            serverSocket.close();
        }
        
        static class HttpRequestHandler implements Runnable{
            private Socket socket;
            public HttpRequestHandler(Socket socket) {
                this.socket = socket;
            }
            @Override
            public void run() {
                String line = null;
                BufferedReader br = null;
                BufferedReader reader = null;//读socket的输入
                PrintWriter out = null;//读socket的输出
                InputStream in = null;//读图片文件
                try{
                    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String header = reader.readLine();
                    System.out.println("收到header=" + header);
                    //由相对路径计算出绝对路径
                    String filePath = basePath + header.split(" ")[1];
                    out = new PrintWriter(socket.getOutputStream());
                    if(! new File(filePath).exists()){
                        out.flush();
                        return;
                    }
                    //如果有请求资源的后缀是.jpg或者.ico,则读取资源并输出
                    if(filePath.endsWith(".jpg")){
                        in = new FileInputStream(filePath);
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        int i = 0;
                        while((i = in.read()) != -1){
                            baos.write(i);
                        }
                        byte[] array = baos.toByteArray();
                        out.println("HTTP/1.1 200 OK");
                        out.println("Server: Molly");
                        out.println("Content-Type:image/jpeg");
                        out.println("Content-Length:" + array.length);
                        out.println("");
                        socket.getOutputStream().write(array, 0, array.length);
                    }else{
                        br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
                        out.println("HTTP/1.1 200 OK");
                        out.println("Server: Molly");
                        out.println("Content-Type:text/html;charset=UTF-8");
                        out.println("");
                        while((line = br.readLine()) != null){
                            out.println(line);
                        }
                    }
                    out.flush();
                }catch(Exception e){
                    e.printStackTrace();
                    out.println("HTTP/1.1 500");
                    out.println("");
                    out.flush();
                }finally{
                    close(br, in, reader, out, socket);
                }
            }
            //关闭流或者socket
            private static void close(Closeable... closeables){
                if(closeables != null){
                    for(Closeable closeable : closeables){
                        try {
                            if(closeable!=null){
                                closeable.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }           
                }
            }
        }
    }
    

    HttpServerMain.java

    package com.httpServerTest;
    
    public class HttpServerMain {
    
        public static void main(String[] args) {
            SimpleHttpServer shs = new SimpleHttpServer();
            shs.setBasePath("D:/testDir"); //将根目录定义到html所在的目录
            try {
                shs.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    一个简易的html页面test.html

    将该页面和任意三个命名为1.jpg/2.jpg/3.jpg的图片放到d:\testDir文件夹。

    <html>
        <head>
            <title>测试页面</title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        </head>
        <body align="center">
            <h1>第一张图片</h1>
            <img src="1.jpg" alt="" align="middle"/>
            <h1>第二张图片</h1>
            <img src="2.jpg" alt="" align="middle"/>
            <h1>第三张图片</h1>
            <img src="3.jpg" alt="" align="middle"/>
        </body>
    </html>
    

    相关文章

      网友评论

          本文标题:通过线程池实现一个简单的Web服务器

          本文链接:https://www.haomeiwen.com/subject/wqkrjttx.html