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

本文介绍了一种HTTP响应头的重构方案,使HttpResponse能够动态发送多种响应头,包括Content-Type、Content-Length等,根据客户端请求的资源类型自动调整响应头内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本版本要对响应中发送响应头的工作做两个重构:

  • 首要解决的问题是,不能让HttpResponse发送响应头的工作中只固定发送两个头,因为随着后期的扩展,服务端可以发送更多响应头,因此响应头内容应当是可扩展的。
  • 发送响应头Content-Type时的值应当随着客户端请求的资源类型不同而产生变化,让浏览器理解其请求的资源。

问题一的解决:

要想让response发送响应头的内容可以扩展,我们可以在响应对象HttpResponse中定义一个响应头相关信息的属性:private Map<String, String> headers = new Hash<>();其中key:响应头的名字,value对应的值。代码如下:

用这个Map保存要给客户端发送的所有响应头,然后修改为发送响应头的方法sendHeaders().将原有的发送两个固定响应头的工作改为通过遍历headers这个Map,将所有的响应头信息得到后拼成一个响应头的字符串后(响应头的格式为: 名字: 值)发送给客户端(注意冒号+空格)。代码如下:

/**
     * 发送响应头
     */
    private void sendHeaders() {
        try {
            System.out.println("HttpResponse:开始发送响应头...");
            //通过遍历headers将所有响应头发送
            Set<Entry<String, String>> set = headers.entrySet();
            for (Entry<String,String> s : set) {
                String name = s.getKey();
                String value = s.getValue();
                String line = name + ": " + value;
                System.out.println("响应头:"+line);
                println(line);
            }
            //单独发送CRLF表示响应头发送完毕
            println("");
            System.out.println("HttpResponse:响应头发送完毕!");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

问题二的解决: 

这样将来我们可以根据处理请求的实际结果视情况而定发送若干的响应头给客户端。因此,HttpResponse中我们再添加一个方法:putHeader(String name, String value)用于让外界可以设置要发送的一个响应头。代码如下:

/**
     * 向当前请求对象中添加一个要发送的响应头信息
     * @param name     响应头名字
     * @param value    响应头对应的值
     */
    public void putHeader(String name, String value) {
        this.headers.put(name,value);
    }

有了上述操作后,可以再ClientHandler处理请求的环节中,设置response时添加要发送的响应头,这里暂时还是只发送Content-Type和Content-Length并测试原有功能是否正常。代码如下:

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("资源已找到!");
                Map<String, String> map = new HashMap<>();
                map.put("html","text/html");
                map.put("css","text/css");
                map.put("js","application/javascript");
                map.put("png","image/png");
                map.put("gif","image/gif");
                map.put("jpg","image/jpeg");
                String ext = file.getName().substring(file.getName().lastIndexOf(".")+1);

                response.putHeader("Content-Type",map.get(ext));
                response.putHeader("Content-Length",file.length()+"");
                response.putHeader("Server","WebServer");
                response.setEntity(file);
            } else {
                System.out.println("资源不存在!");
                file = new File("webapps/root/404.html");
                response.setStatusCode(404);
                response.setStatusReason("NotFound");
                response.putHeader("Content-Type","text/html");
                response.putHeader("Content-Length",file.length()+"");
                response.setEntity(file);
            }

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

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

        } catch (EmptyRequestException e) {
            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、付费专栏及课程。

余额充值