从0开始使用java编写自己的HTTP服务器(二)

HttpRequest对象的封装

摘要:
这篇文章主要为大家介绍一下在本服务器中如何对Request对象进行封装。

第一步:定义一个抽象类HttpRequest

public abstract class HttpRequest {
    private String type ; // 标识这个请求的类型,GET,POST

    public HttpRequest(String type) {
        this.type = type;
    }   //  构造方法
    public String getType() {
        return type;
    }   //  获得类型
    
    // abstract methods
    abstract public void setHeader(String contentPerLine) ;     //  设置请求头
    abstract public Vector<String> getHeader() ;    //  获得请求头
}

解释:
在这里有很多朋友可能会问为什么要定义这样一个抽象类,在这里呢,是为了后续的服务器完善的时候有良好的可拓展性。当我们想添加多一个请求的时候,就可以编写一个新类,继承这个父类,然后编写新的逻辑即可。

设计原则:
里氏代换原则、开闭原则

第二步:定义一个简单工厂RequestFactory,负责生产request。

public class RequestFactory {   // 该类是一个工具类,无需创建对象
    public static HttpRequest parseRequest(InputStream stream) throws Exception {
        // 参数说明:stream是通过客户端的socket获得来自浏览器的输入流
        int b = 0 ;
        StringBuffer requestBuffer = new StringBuffer() ;   //  请求保存
        b = stream.read() ; //  阻塞接受数据
        requestBuffer.append((char)b) ;
        int size = stream.available() ; //  查看请求的总长度
        System.out.println("request:"); // 打印console
        System.out.print((char)b);
        while(size--!=0){           
            b = stream.read() ;
            System.out.print((char)b);
            requestBuffer.append((char)b) ;
        }
        System.out.println();
        // 解析请求
        String request = requestBuffer.toString() ;
        String requestType = request.substring(0,request.indexOf(" ")) ; // 获得请求类型
        StringTokenizer stringTokenizer = new StringTokenizer(request,"\r\n") ; // 切分字符串
        HttpRequest httpRequest = null ;
        // 根据请求类型生成不同的对象,这里用到了迪米特法则
        if (requestType.equalsIgnoreCase("GET")){
            httpRequest = new Get(requestType) ;
        }else if (requestType.equalsIgnoreCase("POST")){
            httpRequest = new Post(requestType) ;
        }
        else if (requestType.equalsIgnoreCase("HEAD")){
            httpRequest = new Head(requestType) ;
        }else{
            System.out.println("暂无该请求的处理方式");
            return null ;
        }
        // 构建请求头
        while(stringTokenizer.hasMoreTokens()){
            String line = stringTokenizer.nextToken() ;
            httpRequest.setHeader(line+"\r\n");
        }
        return httpRequest ;
    }
}

注意:
这里在开发过程中遇到过bug,主要是avaliable获得浏览器的请求的长度为0,这个问题已经得到解决了,至于是为什么可以去看一下我之前的一篇文章。

设计模式:
简单工厂模式。

第三步:构建get请求。

public class Get extends HttpRequest{
    private Vector<String> headers ;    //  保存头信息
    public Get(String type) {
        super(type);
    }

    @Override
    public Vector<String> getHeader() {
        return headers ;
    }   // 获得头信息

    @Override
    public void setHeader(String contentPerLine) {  //  设置头信息
        if (headers==null){
            headers = new Vector<>() ;
        }
        headers.add(contentPerLine) ;
    }

}

解释:
主要封装了设置头和返回头的一些方法。

第四步:构建Post请求。

public class Post extends HttpRequest{
    private Vector<String> headers ;
    public Post(String type) {
        super(type);
    }

    @Override
    public Vector<String> getHeader() {
        return headers;
    }

    @Override
    public void setHeader(String contentPerLine) {
        if (headers==null){
            headers = new Vector<>() ;
        }
        headers.add(contentPerLine) ;
    }

}

第五步:构建Head请求

public class Head extends HttpRequest{
    private Vector<String> headers ;
    private StringBuffer packet ;
    public Head(String type) {
        super(type);
    }

    @Override
    public Vector<String> getHeader() {
        return headers ;
    }

    @Override
    public void setHeader(String contentPerLine) {
        if (headers==null){
            headers = new Vector<>() ;
        }
        headers.add(contentPerLine) ;
    }

}

总结:

来个小总结吧,这一次我们主要实现了各种请求的封装,其主要的用途就是把来自客户端(浏览器)的请求做了解析,方便我们后续构建response。

感谢阅读,欢迎指教。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值