读了两章的 How Tomcat Works

周一发现了一本书.How Tomcat Works 惯例先到豆瓣搜书评.结果书评出奇的好.然后下载了PDF.从简介中看,本书的每个章节都会不断的围绕怎么建造一个Tomcat讲解.我本人比较喜欢这种造轮子的书.原因很简单,比较笨.如果书中没有代码,很难从脑海中构件代码结构.可是万万没想到,看到第三章,就发现,书中的代码不全,完整的代码还要到GitHub下载.无奈只能放下这本好书.(个人觉得看书就是要了解本质,如果书中的源码不全,而是给出片段,剩下的还要到项目中找,我觉得你还不如让我去直接看Tomcat的源码.实名DISS,因为这件事昨晚都没睡好.)不过开卷有益,贴出来两段代码,安慰下自己.

本次代码都有注释,就不一一介绍了.

public class HttpServer {
    //C:workspaceyourTomcatsrc   /webroot
    public static final String WEB_ROOT = System.getProperty("user.dir")+ File.separator+ "webroot";

    //停止语句
    private static final String SHUTDOWN_COMMAND="/SHUTDOWN";
    //停止标识符
    private boolean shutdown = false;

    /*
     * @author 顶风少年
     * @date 2019/9/16 16:57
     * @mail dfsn199703132038@foxmail.com
     * @throws
     * @param
     * @result void
     * @notify 监听请求
     * version 1.0
     */

    public void await(){
        ServerSocket serverSocket = null;
        int port = 8080;
        try{
            //创建服务端
            serverSocket = new ServerSocket(port,1, InetAddress.getByName("127.0.0.1"));
        }catch (IOException e){
            e.printStackTrace();
            System.exit(1);
        }

        //循环监听
        while (!shutdown){
            Socket socket = null;
            InputStream input = null;
            OutputStream output = null;
            try {
                //客户端发送请求这里则会监听到
                socket = serverSocket.accept();
                //获取输入流
                input = socket.getInputStream();
                //获取输出流
                output = socket.getOutputStream();
                //解析请求对象
                Request request = new Request(input);
                request.parse();
                //创建相应对象
                Response response = new Response(output);
                response.setRequest(request);
                response.sendStaticResource();
                //关闭socket通道
                socket.close();
                //如果客户端传递的停止则,更改监听标记
                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
            }catch (Exception e){
                e.printStackTrace();
                continue;
            }

        }
    }
}
public class Request {
    private InputStream input;
    private String uri;

    public Request(InputStream input) {
        this.input = input;
    }


    /*
     * @author 顶风少年
     * @date 2019/9/16 16:57
     * @mail dfsn199703132038@foxmail.com
     * @throws
     * @param
     * @result void
     * @notify 解析请求内容
     * version 1.0
     */
    public void parse() {
        //将字节转换成字符
        StringBuffer request = new StringBuffer(2048);
        //是否读取结束
        int i;
        //将字节读取到此处
        byte[] buffer = new byte[2048];
        try {
            //读取
            i = input.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
            i = -1;
        }
        //循环将字节放到String中
        for (int j = 0; j < i; j++) {
            request.append((char) buffer[j]);
        }
        //解析请求资源路径
        uri = parseUri(request.toString());
    }

    /*
     * @author 顶风少年
     * @date 2019/9/16 16:59
     * @mail dfsn199703132038@foxmail.com
     * @throws
     * @param
     * @param requestString
     * @result java.lang.String
     * @notify 解析请求资源路径
     * version 1.0
     */
    private String parseUri(String requestString) {
        //记录前两个空格,第一个空格和第二个空格之间是 请求路径 GET /SHUTDOWN HTTP/1.1
        int index1, index2;
        //找到第一个空格的位置
        index1 = requestString.indexOf(" ");
        if (index1 != -1) {
            //找到第二个空格的位置
            index2 = requestString.indexOf(" ", index1 + 1);
            if (index2 > index1) {
                //截取请求路径
                return requestString.substring(index1 + 1, index2);
            }
        }
        return null;
    }

    /*
     * @author 顶风少年
     * @date 2019/9/16 17:00
     * @mail dfsn199703132038@foxmail.com
     * @throws
     * @param
     * @result java.lang.String
     * @notify 获取请求路径
     * version 1.0
     */
    public String getUri() {
        return uri;
    }
}
public class Response {
    private static final int BUFFER_SIZE = 1024;
    Request request;
    OutputStream output;

    public Response(OutputStream output) {
        this.output = output;
    }

    /*
     * @author 顶风少年
     * @date 2019/9/16 17:01
     * @mail dfsn199703132038@foxmail.com
     * @throws
     * @param
     * @param request
     * @result void
     * @notify 设置request
     * version 1.0
     */
    public void setRequest(Request request) {
        this.request = request;
    }

    /*
     * @author 顶风少年
     * @date 2019/9/16 17:02
     * @mail dfsn199703132038@foxmail.com
     * @throws
     * @param
     * @result void
     * @notify 相应资源
     * version 1.0
     */
    public void sendStaticResource() throws IOException {
        //存放资源字节
        byte[] bytes = new byte[BUFFER_SIZE];
        //输入流
        FileInputStream fis = null;
        try {
            //尝试创建请求资源文件
            File file = new File(HttpServer.WEB_ROOT, request.getUri());

            //如果请求资源存在
            if (file.exists()) {
                fis = new FileInputStream(file);
                //将文件内容读取到字节数组中
                int ch = fis.read(bytes, 0, BUFFER_SIZE);
                //如果读取到了内容
                output.write("HTTP/1.1 200 OK\r\nContent-Type: text/html

".getBytes());
                while (ch != -1) {
                    //将内容写入到响应体
                    output.write(bytes, 0, ch);
                    //再次读取
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
            } else {
                //每一找到请求资源
                String errorMessage = "HTTP/1.1 404 File Not Found
" +
                        "Content-Type:text/html
" +
                        "Content-Length: 23
" +
                        "
" +
                        "<h1>File Not Found</h1>";
                //写入提示信息
                output.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
           e.printStackTrace();
        } finally {
            //关闭流
            if (fis != null) {
                fis.close();
            }
        }
    }
}

说起来这是我加入博客园一来,第一次写带感情的文章.从16年6月认识java.到18年工作做得微信小程序,以及少量的java工作.再到今年的运维,偏向java.这几年,我一直不断的学习java.java基础的书看了三本.

其他的语言js,html,c++,c#包括sql.这么多语言来讲,我还是最喜欢java,起先写java就是写demo,工作后的一段时间写crud觉得十分无趣.在后来读了几本书,才知道原来在crud的工作中,也可以加入设计模式,编

程思想.以后的工作,我时常将一些模式,和一些设计写到工作中的crud代码中,力图让工作不在那么无趣,也让自己写的代码看上去优雅些.对于java只想说,不忘初心,方得始终.

最后希望明年我能找到一份真正的java开发工作.在这最后的几个月,我也将继续修炼内功.学习更多的招式.晚安!

原文地址:https://www.cnblogs.com/zumengjie/p/11553130.html