【JAVA并发】一个基于线程池技术的简单Web服务器

import java基础.Test718.DefaultThreadPool;
import java基础.Test718.ThreadPool;

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

public class SimpleHttpServer {
    //处理HttpRequest的线程池
    static ThreadPool<HttpRequestHandler> threadPool = new DefaultThreadPool<>();
    //SimpleHttpServer
    static String basePath;
    static ServerSocket serverSocket;
    //服务监听端口
    static int port = 8080;

    // 设置服务端口
    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;
        }
    }

    // 启动HTTP服务器
    public static void start() throws IOException {
        serverSocket = new ServerSocket(port);
        Socket socket = null;
        while ((socket = serverSocket.accept())!=null){
            // 接收一个客户端Socket,生成一个HttpRequestHandler,放入线程池执行
            threadPool.execute(new HttpRequestHandler(socket));
        }
        serverSocket.close();
    }

    // 处理HTTP请求的线程类
    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;
            PrintWriter out = null;
            InputStream in = null;
            try {
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String header = reader.readLine();
                // 由相对路径计算出绝对路径
                String filePath = basePath + header.split(" ")[1];
                out = new PrintWriter(socket.getOutputStream());

                // 如果请求资源的后缀为jpg或者ico,则先读取资源并输出
                if (filePath.endsWith("jpg") || filePath.endsWith("ico")) {
                    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) {
                // 出现异常时返回500错误
                out.println("HTTP/1.1 500");
                out.println("");
                out.flush();
            } finally {
                // 关闭流或者Socket
                close(br, in, reader, out, socket);
            }
        }
    }

    // 关闭流或者Socket
    private static void close(Closeable... closeables){
        if(closeables != null){
            for (Closeable closeable : closeables){
                try {
                    closeable.close();
                } catch (Exception e) {
                    // 异常处理
                }
            }
        }
    }
}

注释和思路解释:

  1. 导入相关包:导入所需的Java核心和网络编程相关的类库。

  2. 定义类和静态成员变量

    • SimpleHttpServer类包含了静态线程池 threadPool,用于处理HTTP请求。
    • basePath用于存储服务器的根路径。
    • serverSocket用于监听客户端连接的服务端Socket。
    • port定义了服务监听的端口,默认为8080。
  3. 设置端口和基本路径

    • setPort(int port)方法用于设置服务端口。
    • setBasePath(String basePath)方法用于设置服务器的根路径。
  4. 启动服务器

    • start()方法通过创建一个ServerSocket监听指定端口,并在接收到客户端连接时,将连接交由HttpRequestHandler处理,并放入线程池执行。
  5. HttpRequestHandler类

    • 内部类,实现了Runnable接口,用于处理单个HTTP请求。
    • 构造函数接收一个Socket对象,表示与客户端的连接。
  6. run方法

    • run()方法中,处理HTTP请求的具体逻辑。
    • 使用BufferedReader从Socket获取输入流,读取HTTP请求的头部信息。
    • 根据请求的URL路径(通过HTTP头部获取),拼接出请求的文件路径filePath
  7. 处理不同类型的资源

    • 如果请求的资源是jpg或ico类型的,读取对应的文件并返回给客户端。
    • 其他类型(默认为HTML文本),读取文件内容并返回。
  8. 异常处理

    • 如果出现异常,在响应中返回500状态码。
  9. 关闭资源

    • close()方法用于关闭所有的流和Socket,确保资源正确释放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值