• JavaWeb之Servlet:请求 与 响应


    1 引入

    浏览器和服务器的种类都有很多,要在它们之间通讯,必定要遵循一定的准则,而http协议就是这样的一个"准则"。

    Http协议:规定了 浏览器 和 服务器 数据传输的一种格式。

    当浏览器想要获取服务器的服务,就会往服务器发送一个请求,这个请求就会使用Http协议规定的格式发送到服务器,而服务器收到这个请求后,也会按照Http协议规定的格式,把服务器的响应发给浏览器。

    下面我们看一下这种"格式"的一个实例

    请求的格式:

    复制代码
    GET /day09/first HTTP/1.1             -- 请求行
    Host: localhost:8080                  --请求头(多个键值对)
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,zh-cn;q=0.8,zh;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
                                      --空行
    name=eric&password=123456         --实体内容
    复制代码

    响应的格式:

    复制代码
    HTTP/1.1 200 OK                        --响应行
    Server: Apache-Coyote/1.1                --响应头(多个键值对)
    Content-Type: text/html;charset=utf-8
    Content-Length: 46
    Date: Sat, 22 Nov 2014 01:42:06 GMT
                                        --空行
    xxxxxx                                --实体内容(浏览器主体窗口看到的部分)
    复制代码

    现在只要注意格式即可,具体内容我们下面一一讲解

    2.Http请求

        2.1请求行  

              GET /day09/first HTTP/1.1

      请求行中主要有三个部分  :

            1)GET                代表请求的方式。常用的有:GET请求,和 POST请求。

                        请求方式:GETPOSTHEADPUTCONNECTTRACE

     

            2)/day09/first      代表请求想要获得的资源的URI

                       uri : 统一资源标记符。

                       url:统一资源定位父。

     

            3)HTTP/1.1    代表请求格式的http协议的版本。  

                        http:1.0 : 当前浏览器和服务器建立连接后,一次连接只能发出一次请求。

                        http:1.1: 当前浏览器和服务器建立连接后,一次连接可以发出多次请求。

    那么GET和POST方式为什么事最常用的? 这就要关系到我们的表单。

    html表单中只支持的请求的方式只有两个值:GET 和 POST。

    下面是表单的一段代码:

      

    <form action="提交的地址" method="GET/POST">
        用户名:<input type="text" name="name"/>
        密码:<input type="password" name="password"/>
        <input type="submit" value="提交"/>
    </form>

    表单提交后,表单数据就会随请求一起发送到服务器,数据写在了请求里面,但是GET方式 和 POST方式 把数据写在了请求内的不同地方。

    Get方式

    复制代码
    GET /day09/testGetPost.html?name=eric&password=123456 HTTP/1.1
    Host: localhost:8080
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,zh-cn;q=0.8,zh;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8080/day09/testGetPost.html
    Connection: keep-alive
    复制代码

    可以看到,Get方式提交的请求,表单的数据会写在请求行里,并且在请求资源后用 问号 分开。

    所以,表单数据会随着显示在浏览器的地址栏,Get方式不适合提交敏感数据,并且数据量不能太大,不能超过1KB.

    POST方式

    复制代码
    POST /day09/testGetPost.html HTTP/1.1
    Host: localhost:8080
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,zh-cn;q=0.8,zh;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8080/day09/testGetPost.html
    Connection: keep-alive
    
    name=eric&password=123456
    复制代码

    1)参数放在请求的实体内容中。参数之间以&分割。

    2POST方式可以提交敏感数据

    3POST提交数据大小没有限制。

    以上就是 请求行 中的的分析,下面我们来分析请求头。

    2.2请求头

    复制代码
    Accept: text/html,image/*    -- 浏览器告诉服务器支持的数据类型
    Accept-Charset: ISO-8859-1   -- 浏览器支持的编码
    Accept-Encoding: gzip,compress   ---浏览器支持的数据压缩格式
    Accept-Language: en-us,zh-      --浏览器支持的语言
    Host: www.it315.org:80            --浏览器需要访问的主机和端口
    If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT  --浏览器最后更新的缓存时间
    Referer: http://www.it315.org/index.jsp     --当前请求来自于哪个资源
    User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)  --浏览器类型
    Cookie:name=eric                  --浏览器保存的cookie信息
    Connection: close/Keep-Alive         --浏览器连接的状态。close:关闭。keep-alive:保持连接
    Date: Tue, 11 Jul 2000 18:23:51 GMT    --请求发出的时间
    复制代码

    请求头内包含了很多来自浏览器的信息,我们可以从请求头得到这些信息,这些信息实际上是一些键值对,用这些信息来判断浏览器用户的状态,并且利用这些信息来实现一些功能。

    那么我们接收到这些封装好的信息,如何利用代码得到呢?

    在java中有这样的一个类,用于得到请求行里面的信息:      

    HttpServletRequest对象:用于得到请求信息(十分重要),然后处理,得出不同的响应。

             核心方法:

                请求行:

                  request.getMethod();  得到请求方式

                  request.getRequestURI() / getRequestURL()   得到请求的资源的url

                  request.getProtocol()   得到协议版本

                请求头:

                  request.getHeader(头名称)

                  request.getHeaderNames();    得到所有的头

                  request.getHeaders(头名称)        得到同名头的值

                实体内容:

                  request.getInputStream();  得到实体内容的一个输入流

     

    那么如何得到这个对象呢?我们在服务器建一个 servlet ,然后重写一下父类的doGet()方法,doGet方法就是浏览器以Get方式发送请求道服务器时,服务器就会执行doGet()方法里的内容,看下面一段代码:

    复制代码
    public class TestServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
        }
    }
    复制代码

    我们可以看到,doGet()方法的参数中,就有那么一个HttpServletRequest类型的参数,也就是说,在doGet()方法中,我们可以利用这个参数来调用上面说的HttpServletRequest对象的核心方法,来取得请求里的数据!

    下面我们利用这些方法获取 请求行 里的信息:

    复制代码
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String method = request.getMethod();
            System.out.println("method is :" + method);
            String requestURI = request.getRequestURI();
            System.out.println("requestURI is :" + requestURI);
            String protocol = request.getProtocol();
            System.out.println("protocol is :" + protocol);
        }
    复制代码

    输出结果:

    method is :GET
    requestURI is :/MyFirstProject/TestServlet
    protocol is :HTTP/1.1

    这样就能获取请求行里的信息了!

    同理!获取请求头内的键值对的信息,还有实体内容的信息,也可以利用doGet()方法内的HttpServletRequest来完成,此处不一一演示。那么我们下面研究下doGet()方法!

    doxxx()方法

    上面说过以GET方式提交的请求,Servlet就会调用doGet()方法来处理,十分容易理解的~

    所以,如果浏览器以POST方式来提交请求,Servlet就会调用它的doPost()方法来处理了~

    对应的,请求方式有这么多种:GET、POST、HEAD、PUT、CONNECT、TRACE

    以哪种方式提交的请求,Servlet就会调用doxxx()方法来处理对应的请求了~

    获取表单的数据

    表单的数据会存储在请求中:

         请求行(get方式)

                  GET /day09/testGetPost.html?name=eric&password=123456 HTTP/1.1

          实体内容(post方式)

                  name=eric&password=123456

    细心的读者可能会发现,上面介绍HttpServletRequest的核心方法中,虽然可以获取请求中的数据,但是要清楚得区分出表单内容还是很麻烦,比如说我们想要获得name的值,那么就要写一个程序去判解析字符串,得到name的值。这显得十分麻烦,所以,Servlet中提供了一些简便的方法让我们获取表单数据。

      

        统一的获取请求中表单参数的方法:

          request.getParameter(参数名)         获取单个值的参数,比如获得name的值,就这样写:request.getParameter("name");

          request.getParameterValues(参数名)  获取多个值的参数,有些表单一个属性有多个值,例如你有多个爱好,那么久调用这个方法获取爱好的多个值。

          request.getParameterNames();         获取所有的参数,这个方法获得表单的所有参数的名字,例如一个表单中有:name,id,hobit,address,phone等。

     

    现实生活中,根据不同的需要,用户提交的表单可能是用Get方式提交的,也可能用POST方式提交的,表单数据根据不同的提交方式存储在请求的不同地方,但是我们得到表单数据后要对数据的处理是一样的,如果在doPost()和doGet()中都写同一个处理方法就显得代码太繁琐了,那么我们如何处理这种情况?

      我们可以在doPost()方法中调用doGet()方法,在doGet()判断请求的方式,然后根据两种请求得到数据,然后就对这些数据进行处理。

     

     请求参数的编码问题

    1POST方式

     

    request.setCharacterEncoding(码表);   

     

    用于设置获取实体内容参数时查询的码表。建议放在第一 行代码

    2Get方法

    2.1 手动解码:(推荐使用)

    if("GET".equals(request.getMethod())){
    
    ah = new String(ah.getBytes("iso-8859-1"),"utf-8");
    
    }

    2.2 修改服务器的配置文件(依赖服务器,不推荐使用)

    找到%tomcat%/conf/server.xml,修改以下配置

    <Connector port="8080" protocol="HTTP/1.1" 

                   connectionTimeout="20000" 

                   redirectPort="8443" URIEncoding="utf-8"/>  加入URIEncoding属性,设置URI后面参数的编码

     

     

    HTTP相应

    说完了请求,我们说一下相应,如果你懂了请求里的内容,响应内容就绝对没问题了!

    响应浏览器想服务器发出请求,服务器作出响应,我们看以下响应的格式:

    复制代码
    HTTP/1.1 200 OK                        --响应行
    Server: Apache-Coyote/1.1                --响应头(多个键值对)
    Content-Type: text/html;charset=utf-8
    Content-Length: 46
    Date: Sat, 22 Nov 2014 01:42:06 GMT
                                        --空行
    xxxxxx  
    复制代码

    响应的格式和请求的格式相似。

    响应行

    由三部分组成:

        Http协议版本      HTTP/1.1 

     

        状态码: 服务器告诉浏览器,请求处理的结果。

        常用的状态:

              200     请求处理完成

              302     客户端需要进一步发送请求才能完成过程。通常该状态码与location响应头一起使用。

              404     请求的资源没有找到

              500     服务器的资源出错。

         状态描述: 对状态码的补充

     

    响应头

    复制代码
    Location: http://www.it315.org/index.jsp   ---重定向的地址。通常和302状态码一起使用。
    Server:apache tomcat                   --服务器的类型
    Content-Encoding: gzip                   -- 服务器发送给浏览器的内容压缩格式 
    Content-Length: 80                     --服务器发送浏览器的数据长度
    Content-Language: zh-cn                   --服务器发送给浏览器的内容语言
    Content-Type: text/html; charset=GB2312    --服务器发送给浏览器的内容类型和编码
    Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT   --服务器资源的最后修改时间
    Refresh: 1;url=http://www.it315.org      --定时刷新或者隔n秒跳转页面
    Content-Disposition: attachment; filename=aaa.zip  -- 告诉浏览器以下载方式打开资源
    Transfer-Encoding: chunked 
    Set-Cookie:SS=Q0=5Lb_nQ; path=/search      --服务器发送浏览器的cookie信息
    Expires: -1                               --通知浏览器不使用缓存
    Cache-Control: no-cache                    --通知浏览器不使用缓存
    Pragma: no-cache                         --通知浏览器不使用缓存
    Connection: close/Keep-Alive                连接状态
    Date: Tue, 11 Jul 2000 18:23:51 GMT          响应的发出时间
    复制代码

     最后就是实体内容。  我们可以使用HttpServletResponse对象来操作这些内容,然后发送给浏览器,具体做法其实和HttpServletRequest对象类似。在此不一一讲解。

    学习之所以会想睡觉,是因为那是梦开始的地方。
  • 相关阅读:
    Activity.startManagingCursor方法
    android SQLite使用SQLiteOpenHelper类对数据库进行操作
    Android类参考---SQLiteOpenHelper
    使用SQLiteOpenHelper类对数据库简单操作
    dom4j 最常用最简单的用法(转)
    setContentView()与LayoutInflater.inflate()作用
    Android listview与adapter用法
    ListView属性及divider设置分割线
    android布局属性详解
    Android layout属性之gravity和layout_gravity
  • 原文地址:https://www.cnblogs.com/holdon521/p/4122736.html
Copyright © 2020-2023  润新知