zoukankan      html  css  js  c++  java
  • 自己动手写Web容器之TomJetty之五:包装请求参数

    传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229

            前面我们实现了TomJetty响应无参请求静态页面的功能,但真实情况下,几乎所有请求都得携带参数。不能处理用户参数请求的Web服务器就好比温室里的花朵,始终上不了台面。所以本节我们将为TomJetty加入响应用户参数的功能。此外,前面我们使用的提交请求的方式都是GET方式,但在实际情况下,POST方式使用的更广泛,所以我们也将给TomJetty增加响应POST请求的能力。

    1扩展RequestHeader类

    1.1在RequestHeader类中新增parameter属性,用于标示请求头中客户请求的参数,并提供对应的getter/setter方法

    private String parameter;
    
    public String getParameter() {
        return parameter;
    }
    
    public void setParameter(String parameter) {
        this.parameter = parameter;
    }

    1.2在RequestHeaderParserImpl类的parse()方法中加入如下片段,用于解析在GET和POST两种提交方式下的请求头的参数部分,并将其保存到requestHeader对象中

    String parameter = null;
    try {
        if(method.equalsIgnoreCase("post")) {
            parameter = txt.substring(txt.lastIndexOf("
    ") + 1, txt.length());
        } else if(method.equalsIgnoreCase("get")) {
            parameter = url.substring(url.indexOf("?") + 1, url.length());
            url = url.substring(0, url.indexOf("?"));
        }
    } catch (Exception e) {
    }
    
    header.setParameter(parameter);

    2自定义请求参数类

            创建一个Parameter类,采用键值对的方式存储请求携带的参数。如果直接使用HashMap数据结构进行存储,由于其底层的设计原则,将无法避免客户端浏览器重复提交的问题。

    package cn.lynn.tomjetty;
    
    public class Parameter {
    
        private String key;
        
        private String value;
    
        public String getKey() {
            return key;
        }
    
        public void setKey(String key) {
            this.key = key;
        }
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((key == null) ? 0 : key.hashCode());
            result = prime * result + ((value == null) ? 0 : value.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            final Parameter other = (Parameter) obj;
            if (key == null) {
                if (other.key != null)
                    return false;
            } else if (!key.equals(other.key))
                return false;
            if (value == null) {
                if (other.value != null)
                    return false;
            } else if (!value.equals(other.value))
                return false;
            return true;
        }
        
    }
    

    3封装请求对象

            前面我们讲过,为Java语言服务的Web容器,实际上装载的是Servlet(Java服务端应用程序)。打开Java EE帮助文档,检索Servlet关键字。可以看到Servlet实际上被设计成一个接口。其设计层次如下:


            它有三个实现子类,分别对应于不同的网络协议,这里我们只关注HttpServlet。此外,它还声明了五个方法,分别是:destroy()、getServletConfig()、getServletInfo()、init()、service(ServletRequest req, ServletResponse res),学过JSP的同学知道,service()方法才是Servlet容器响应请求的核心方法。看到这里,我们将Servlet相关HTTP协议的架构设计思想引入到TomJetty中。

    3.1.新建一个Servlet接口,并声明一个service()方法

    package cn.lynn.tomjetty;
    
    public interface IServlet {
    
        public void service(Request req, Response res);
    
    }

    3.2新增一个IServlet接口的HTTP协议实现类HttpServletImpl,并提供doGet()方法和doPost()方法(方法体暂时为空)分别处理来自客户端浏览器的两种不同的提交方式

    package cn.lynn.tomjetty;
    
    public class HttpServletImpl implements IServlet {
    
        public void service(Request req, Response res) {
        }
    
        public void doGet(Request req, Response res) {
        }
        
        public void doPost(Request req, Response res) {
        }
    }

            那么为什么要添加这两个方法?通过查看Java EE的HttpServlet的设计文档,我们知道HttpServlet也提供了这两个方法。当然提供的不止这两个,还有doDelete()、doPut()等,呵呵,想多了,它们不属于本系列关注的范畴^_^。



            我们发现service()方法中传入参数类型已经不是普通的Request和Response,Servlet对它们进行了封装。所以我们也照猫画虎学着做。

    3.3新建一个Request类,用于封装HTTP请求头和请求参数。并提供对应的存取它们的方法以供外部调用

    package cn.lynn.tomjetty;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Request {
        // 引入请求头
        private RequestHeader header;
        // 设置参数集合
        private List<Parameter> params = new ArrayList<Parameter>();
        // 设置请求参数
        public void setParameter(String param) {
            if(param == null || param.trim().equals("")) {
                return;
            }
            
            String[] result = param.split("&");
            
            for (int i = 0; i < result.length; i++) {
                Parameter parameter = new Parameter();
                parameter.setKey(result[i].split("=")[0]);
                parameter.setValue((result[i].split("=").length <= 1) ? "" : result[i].split("=")[1]);
                params.add(parameter);
            }
        }
        // 获取请求参数的值
        public String getParameterValue(String key) {
            String result = null;
            for(Parameter parameter : params) {
                if(parameter.getKey().equals(key)) {
                    result =  parameter.getValue();
                }
            }
            return result;
        }
    
        public RequestHeader getHeader() {
            return header;
        }
    
        public void setHeader(RequestHeader header) {
            this.header = header;
        }
    }
    

    3.4在TomJetty类的run()方法中加入如下片段,将请求头和请求参数存放到Request对象中进行统一管理

    // 封装请求头
    Request request = new Request();
    request.setParameter(header.getParameter());
    request.setHeader(header);

    4响应请求参数效果展示

    4.1GET方式提交


            在IE浏览器输入上述地址后回车,控制台打印如下:

    RequestHeader [
    GET /index.htm HTTP/1.1
    Accept: */*
    Accept-Language: zh-cn
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; KB974488)
    Accept-Encoding: gzip, deflate
    Host: 127.0.0.1:9527
    Connection: Keep-Alive
    Cookie: null
    parameter: username=lynnli1229&password=123456
    ]

    4.2POST方式提交

            新建一个input.htm文件,在其<body>标签内编写一个表单用于POST提交用户信息。

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form action="http://127.0.0.1:9527/index.htm" name="form" id="form" method="post">
        用户名:<input name="username" type="text"></br>
        密    码:<input name="password" type="password"></br>
            <input name="submit" value="提交" type="submit">
            <input name="reset" value="重置" type="reset">
        </form>
    </body>
    </html>

            在IE浏览器输入上述地址后回车,接着填写表单项,点击提交按钮,页面会导航到index.htm,控制台打印如下:

    RequestHeader [
    GET /input.htm HTTP/1.1
    Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/QVOD, application/QVOD, */*
    Accept-Language: zh-cn
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; KB974488)
    Accept-Encoding: gzip, deflate
    Host: 127.0.0.1:9527
    Connection: Keep-Alive
    Cookie: null
    parameter: /input.htm
    ]
    RequestHeader [
    POST /index.htm HTTP/1.1
    Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/QVOD, application/QVOD, */*
    Accept-Language: zh-cn
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; KB974488)
    Accept-Encoding: gzip, deflate
    Host: 127.0.0.1:9527
    Connection: Keep-Alive
    Cookie: null
    parameter: username=lynnli1229&password=123456&submit=%E6%8F%90%E4%BA%A4
    ]

            至此,TomJetty服务器已经能够在POST和GET两种请求提交方式下,都可以为携带参数的静态页面请求提供服务。然而只能处理静态页面请求的服务器还是远远不够的,毕竟现阶段动态网页才是主流。所以下一节我们将赋予TomJetty服务器处理动态网页的能力。

  • 相关阅读:
    strcpy的实现
    使用Highcharts生成柱状图
    使用Highcharts结合PHP与Mysql生成饼状图
    shopnc 学习笔记
    php中关于mysqli和mysql区别的一些知识点分析
    jquery捕获enter键 按enter键执行提交
    php在IE浏览器中保存SESSION
    ShopNC 商城系统开发经验分享第五篇: 缓存设计
    ShopNC 商城系统开发经验分享第二篇:ShopNC商城系统初步分析
    SHOPEX于SHOP++比较哪款更适合做二次开发,为什么?
  • 原文地址:https://www.cnblogs.com/innosight/p/3271172.html
Copyright © 2011-2022 走看看