实现一个简易版的Tomcat(八)

前言

上个版本我们处理了响应404页面,此版本我们将对代码进行重构。

重构思想:

与请求一样,既然响应也是由三部分构成,我们可以设计一个类, 取名:HttpResponse,并用这个类的每一个实例表示客户端发送的 相应内容。将来可以根据实际响应内容不同,对响应的对象中各部分 信息进行设置,最终发送给客户端。


实现:

1.新建类HttpResponse

2.定义结构

定义HttpResponse的结构,以及方法flushflush方法用于将当前响应对象的各部分信息最终以标准的Http响应格式发送给客户端。

代码如下:

public class HttpResponse {
    private Socket socket;
    private OutputStream out;

    //状态行相关信息
    private int statusCode = 200;
    private String statusReason = "OK";
    //响应头相关信息

    //响应正文相关信息
    private File entity; //响应正文对应的实体文件
    public HttpResponse(Socket socket) {
        try {
            this.socket = socket;
            out = socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 将当前响应对象内容以一个标准的HTTP响应格式发送给客户端
     */
    public void flush() {
        try {
            //1.发送状态行
            sendStatusLine();
            //2.发送响应头
            sendHeaders();
            //3.发送响应正文
            sendContent();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送状态行
     */
    private void sendStatusLine() {
        try {
            String line = "HTTP/1.1"+" "+statusCode+" "+statusReason;
            println(line);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送响应头
     */
    private void sendHeaders() {
        try {
            String line = "Content-Type: text/html";
            println(line);

            line = "Content-Length: "+entity.length();
            println(line);

            //单独发送CRLF表示响应头发送完毕
            out.write(13);
            out.write(10);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送响应正文
     */
    private void sendContent() {
        try(
            //利用自动关闭特性,关闭文件流
            FileInputStream fis = new FileInputStream(entity);
        ) {
            int len;
            byte[] data = new byte[1024*8];
            while((len = fis.read(data)) != -1) {
                out.write(data, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向客户端发送一行给定的字符串,发送该字符串后悔自动在
     * 后面发送回车符与换行符。
     * @param line
     * @throws IOException
     */
    private void println(String line) throws IOException {
        out.write(line.getBytes("ISO8859-1"));
        out.write(13);
        out.write(10);

    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public String getStatusReason() {
        return statusReason;
    }

    public void setStatusReason(String statusReason) {
        this.statusReason = statusReason;
    }

    public File getEntity() {
        return entity;
    }

    public void setEntity(File entity) {
        this.entity = entity;
    }
}

3.设置并调用

将ClientHandler处理请求的分支根据处理结果设置HttpResponse对象内容并通过调用flush方法发送响应。代码如下:

public class ClientHandler implements Runnable{
    private Socket socket;
    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            //1.解析请求
            //实例化就是解析过程,得到的对象就表示本次请求的内容
            HttpRequest request = new HttpRequest(socket);
            HttpResponse response = new HttpResponse(socket);
            //2.处理请求
            String path = request.getUri();
            System.out.println("抽象路径:"+path);
            File file = new File("webapps"+path);
            if (file.isFile() && file.exists()) {
                System.out.println("资源已找到!");
                response.setEntity(file);
            } else {
                System.out.println("资源不存在!");
                response.setStatusCode(404);
                response.setStatusReason("NotFound");
                response.setEntity(new File("webapps/root/404.html"));
            }

            //3.响应客户端
            response.flush();

            System.out.println("响应客户端完毕!");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //与客户端断开连接
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 


此版本我们重构了之前在ClientHandler中的代码,并且根据不同的请求设置了不同的响应页面。

下一个版本将进入浏览器与服务端的交互过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值