练习:http的请求与响应协议(RESTer插件下载)

  使用RESTer插件可以模拟post和get请求:

在这里插入图片描述

将得到请求协议与返回响应协议封装:

/*目标:使用ServerSocket建立与浏览器连接,获得请求协议*/
public class Server01 {
    private ServerSocket serverSocket;

    public static void main(String[] args) {
        Server01 s = new Server01();
        s.start();
    }

    public void start() {
        try {
            serverSocket = new ServerSocket(8888);
            receive();//建立连接
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器启动失败");
        }
    }


    public void receive() {
        try {
            Socket client = serverSocket.accept();
            System.out.println("一个客户端建立了连接");
            Request r1=new Request(client);
          //  System.out.println("===============================");
          //  System.out.println(  r1.getParameterSingleValues("name1"));
            Response r2 = new Response(client);//文件正文
            r2.print("<html>");
            r2.print("<head>");
            r2.print("<title>");
            r2.print("服务器响应成功");
            r2.print("</title>");
            r2.print("</head>");
            r2.print("<body>");
            r2.print("requerst name1:"+r1.getParameterSingleValues("name1"));
            r2.print("</body>");
            r2.print("</html>");
            r2.pushToBrowser(200);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("客户端连接失败");
        }
    }
}

封装响应协议:

public class Response {
    private BufferedWriter bw;
    private StringBuilder headInfo;
    private final String BLANK=" ";//空行
    private final String CRLF="\r\n";//跳到下一行的头
    private long size=0;//协议正文大小
    private StringBuilder content;//协议正文
    private Response(){
        headInfo=new StringBuilder();
        content=new StringBuilder();
    }
    public Response(Socket client)  {
        this();//重载无参构造函数
        try {
           bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

public void createHeadInfo(int code){//构造响应协议头
    //响应协议的状态行:HTTP/1.1 200 OK
    headInfo.append("HTTP/1.1").append(BLANK);
    headInfo.append(code).append(BLANK);
    switch (code){
        case 200: headInfo.append("OK").append(CRLF);
        break;
        case 404: headInfo.append("NOT FOUND").append(CRLF);
        break;
        case 505: headInfo.append("SERVER ERROR").append(CRLF);
        break;
    }

    //响应头(最后一行有空行)
    headInfo.append("Date:").append(new Date()).append(CRLF);
    headInfo.append("Server:").append("WebServer02/0.0.1;charset=UTF8").append(CRLF);
    headInfo.append("Content-type:text/html").append(CRLF);
    headInfo.append("Content-length:").append(size).append(CRLF);
    headInfo.append(CRLF);//与正文直接有个空行

}


    public Response print(String info){//传入响应协议正文,流操作,返回自身则可以 print.print反复依次调用
        content.append(info);
        size+=info.getBytes().length;//必须获得字节的长度,而不是字符的长度
        return this;//返回本身实例
}
    public Response println(String info){//换行的传入正文操作
        content.append(info).append(CRLF);
        size+=(info+CRLF).getBytes().length;
        return this;//返回本身实例
    }

    public void pushToBrowser(int code) throws IOException {
        createHeadInfo(code);//传入状态码,生产响应协议头
        bw.append(headInfo);//Writer内的方法
        bw.append(content);
        bw.flush();
    }
}

封装请求协议:
(新增了对请求参数的分析方法)

/*获取 方法(GET/POST等),URL以及请求参数*/
public class Request {
    private String requestinfo;
    private String method;//方法
    private String Url;
    private String queryStr;//请求参数
    private Map<String, List<String>> parameterMap;//封装请求参数,因为可能一个key值要有不同的value值,所有value是个容器

    public Request(InputStream is){
        parameterMap=new HashMap<String, List<String>>();
        byte[] datas = new byte[1024 * 10 * 10];
        try {
            is.read(datas);
            this.requestinfo = new String(datas, 0, datas.length);
            System.out.println(requestinfo);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    public Request(Socket client) throws IOException {
     this(client.getInputStream());//构造器相互调用,http协议的底层协议是tcp,所有可以得到浏览器的http协议
        parseRequest();
    }

    private void parseRequest(){
        System.out.println("获取请求方式-----------------------------");
        int idx1=requestinfo.indexOf("/");
        this.method=requestinfo.substring(0,idx1).trim();
        System.out.println(method);

        System.out.println("获取请求URL-----------------------------");
        int idx2=requestinfo.indexOf("HTTP");
        int idx3=requestinfo.indexOf("?");
       if(idx3>0){
        Url=requestinfo.substring(idx1+1,idx3);}else {Url=requestinfo.substring(idx1+1,idx2);}
        System.out.println(Url);
        System.out.println("获取请求参数-----------------------------");
        if(idx3>0){
            queryStr=requestinfo.substring(idx3+1,idx2).trim();}else{queryStr=null;}
        if(method.equals("POST")){
            queryStr=requestinfo.substring(requestinfo.lastIndexOf("\r\n")).trim();
        }
        System.out.println(queryStr);
      if(queryStr!=null)  convertMap();
    }


    private void convertMap(){//处理请求参数,将其转换为Map
        //请求参数格式:name1=curry&name2=Ayesha
        String[] keyValues=this.queryStr.split("&");//以&符号分割为name1=curry
     for(String kv:keyValues){//以=号分割出key与value
        String kv1[]=kv.split("=");
        String key=kv1[0];//等号前面为key
        String value=kv1[1];//等号后为value
         //System.out.println(key+"----"+value);
         if(!parameterMap.containsKey(key)){
             parameterMap.put(key,new ArrayList<String>());//第一次出现当前key值
         }
         parameterMap.get(key).add(value);//get(key)得到容器v,往里面添值

     }
    }

    public String[] getParameterValues(String key){
        List<String> list=parameterMap.get(key);
        if(list==null){return null;}

        return  list.toArray(new String[0]);
    }

    public String getParameterSingleValues(String key){
       String[] s=getParameterValues(key);
        return s==null?null:s[0];
    }

}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值