主程序:

package com.xuyu;

import java.net.ServerSocket;
import java.net.Socket;

public class httpServer implements Runnable{

    private static Boolean isRun = true;

    private static Boolean isPush = true;

    public static String resourcePath = "";

    //监听端口
    private int port ;

    public httpServer(int port){
        this.port = port;
    }

    @Override
    public void run() {
        //线程的主程序
        //声明serverSocket对象
        ServerSocket serverSocket = null;
        try {
            //创建ServerSocket对象
            serverSocket = new ServerSocket(port);
            //开始监听
            System.out.println("开始监听...");
            while(httpServer.this.isRun) {
                //socket里面有双向管道,输入输出流
                Socket socket = serverSocket.accept();  //阻塞状态,等待访问
                System.out.println("接受到请求...");
                //将socket交给RequestExecute处理
                RequestExecute re = new RequestExecute(socket);
                //创建线程处理请求
                re.start();
            }
            //运行到这里程序结束
            serverSocket.close();
            serverSocket=null;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("port"+port+"listen fail..."+e.getMessage());
        }
    }

    public static void main(String[] args) {
        httpServer httpServer = new httpServer(8088);
        new Thread(httpServer).start();
    }


}

多线程处理请求:

package com.xuyu;

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

//成员变量不用初始化,具部变量要初始化

//请求处理线程类
public class RequestExecute extends Thread{

    //将Socket定义为成员变量,利用构造方法初始化
    private Socket socket;

    public RequestExecute(Socket socket){
        this.socket=socket;
    }

    @Override
    public void run(){
        //从Socket中取出输入流,然后从输入流中取出数据
        InputStream in = null;//将字节输入流转换为缓冲字符输入流
        InputStreamReader reader = null;//转换流
        BufferedReader bufferedReader = null;//字符缓冲流

        //声明输出流,输出流是指向客户端的
        OutputStream out = null;
        PrintWriter pw = null; //包裹成字符输出流
        try {
            //从Socket中获取字节输出流
            out = socket.getOutputStream();
            //将字节输出流包装成字符流
            pw = new PrintWriter(out);

            //从Socket中获取字节输入流
            in = socket.getInputStream();
            //转换和包装
            reader = new InputStreamReader(in);
            bufferedReader = new BufferedReader(reader);
            //循环的从字符流中获取字符
            String line = null;
            int lineNum =1;
            //存储请求路劲
            String reqPath = "";
            String host = "";
            //每次从中读取一行
            while((line = bufferedReader.readLine())!=null){
                System.out.println(line);
                //解析请求行
                if(lineNum == 1){
                    //使用空格分割字符串
                    String[] infos = line.split("");
                    if(infos!=null || infos.length>2){
                        reqPath = infos[1];//请求路径
                    }else {
                        throw new RuntimeException("请求行解析失败:"+line);
                    }
                }else{
                    //解析其他行,取出Host的内容
                    String[] infos = line.split(": ");
                    if(infos!=null || infos.length==2){
                        if(infos[0].equals("Host")) {
                            host = infos[1];//取出host
                        }
                    }
                }
                lineNum++;
                //读取到空行就结束,因为HTTP请求是长连接,无法读取到文件的末尾
                if(line.equals("")) {
                    break;
                }
            }
            //输出请求信息
            System.out.println(host + reqPath);

            //根据请求响应客户端 /直接返回欢迎页面 /index.html返回文件内容
            if(reqPath.equals("/")){
                pw.write("HTTP/1.1 200 OK \r\n");  //输出响应行
                pw.write("Content-Type: text/html;charset = utf-8");
                pw.println();//输出空行  表示响应头结束,开始响应内容
                pw.write("<h2>Welcome search this</h2>");
                pw.flush();
            }else {
                //查找对应的资源  /index.html
                String ext = reqPath.substring(reqPath.lastIndexOf(".")+1); //取出后缀不包括.
                reqPath = reqPath.substring(1); //去掉前面的/
                //判断是在根目录下还是在其他的子目录下
                if(reqPath.contains("/")){  //子目录
                    //判断文件是否存在
                    File file = new File(httpServer.resourcePath + reqPath);  //C:/xuyu/app/resource.jpg
                    if(file.exists() &&file.isFile()){
                        response200(out,file.getAbsolutePath(),ext);
                    }else {
                        response404(out);
                    }
                }else{  //根目录
                    //判断这个资源是否存在
                    //获取根目录下的所有的文件的名称
                    File root = new File(httpServer.resourcePath);
                    if(root.isDirectory()){
                        File[] list = root.listFiles();
                        boolean isExist = false;  //标记访问的资源是否存在
                        for(File file : list){
                            if(file.isFile() && file.getName().equals(reqPath)){
                                //文件存在
                                isExist = true;
                                break;
                            }
                        }
                        if(isExist){//文件存在
                            response200(out,httpServer.resourcePath+reqPath,ext);
                        }else {  //文件不存在
                            response404(out);
                        }
                    }else{
                        throw new RuntimeException("静态资源目录不存在:"+httpServer.resourcePath);
                    }
                }
            }
        }catch (IOException e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            try {
                if(in!=null){
                    in.close();
                }
                if(reader!=null){
                    reader.close();
                }
                if(bufferedReader!=null){
                    bufferedReader.close();
                }
                if(pw!=null)
                    pw.close();
                if(out!=null)
                    out.close();
            }catch (IOException ex){
                ex.printStackTrace();
            }
        }
    }

    //将指定的文件输出到输出流中
    private void response200(OutputStream outputStream,String filePath,String ext){
        PrintWriter pw = null;
        //准备输入流读取磁盘上的文件
        InputStream in = null;
        InputStreamReader reader = null;
        BufferedReader bufferedReader = null;
        try{
            if(ext.equals("jpg") || ext.equals("png") || ext.equals("gif")){  //图片用字节流输出
                outputStream.write("HTTP/1.1 200 OK \r\n".getBytes());  //输出响应行
                if(ext.equals("jpg"))
                    outputStream.write("Content-Type: image/jpg\r\n".getBytes());
                else if(ext.equals("png"))
                    outputStream.write("Content-Type: image/png\r\n".getBytes());
                else if(ext.equals("gif"))
                    outputStream.write("Content-Type: image/gif\r\n".getBytes());
                //输出一个空行,表示响应头结束
                outputStream.write("\r\n".getBytes());
                //利用字节输入流读取文件内容,并且输出到输入流中
                //创建输入流
                in = new FileInputStream(filePath);
                int len = -1;
                byte[] buff = new byte[1024];
                while((len = in.read(buff))!= -1){
                    outputStream.write(buff,0,len);
                    outputStream.flush();
                }
            }else if(ext.equals("html") || ext.equals("js") || ext.equals("css") || ext.equals("json")){
                pw = new PrintWriter(outputStream);
                pw.write("HTTP/1.1 200 OK \r\n");  //输出响应行
                if(ext.equals("html"))
                    pw.println("Content-Type: text/html;charset=utf-8");
                else if(ext.equals("js"))
                    pw.println("Content-Type: application/x-javascript");
                else if(ext.equals("css"))
                    pw.println("Content-Type: text/css");
                else if(ext.equals("json"))
                    pw.println("Content-Type: application/json;charset=utf-8");
                //输出一个空行,表示响应头结束
                outputStream.write("\r\n".getBytes());
                //初始化输流
                in = new FileInputStream(filePath);
                reader = new InputStreamReader(in);
                bufferedReader = new BufferedReader(reader);

                //写出数据
                String line = null;
                while ((line = bufferedReader.readLine())!=null){
                    pw.println(line);
                    pw.flush();
                }
            }else{
                response404(outputStream);
            }
            pw.write("Content-Type: text/html;charset = utf-8");

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(pw!=null)
                    pw.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    //响应404页面
    private void response404(OutputStream outputStream){
        PrintWriter pw = null;
        try{
            pw = new PrintWriter(outputStream);

            pw.write("HTTP/1.1 404 \r\n");  //输出响应行
            pw.write("Content-Type: text/html;charset = utf-8");
            pw.println();//输出空行  表示响应头结束,开始响应内容
            pw.write("<h2>resource is not exist!</h2>");
            pw.flush();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(pw!=null)
                    pw.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}