HTTP与request

HTTP协议

  1. HTTP:超文本传输协议,定义了浏览器与服务器之间数据传输的格式;简而言之,就是一种在web中传输数据的格式。
  2. HTTP协议组成:
    1. 请求报文:请求行,请求头,请求体;
      1. 请求行:请求报文中的第一行数据,包括请求方式,URL,协议/版本;
      2. 请求头:以键值对的数据格式,给服务器传输数据。常用的请求头:user-agent,cookie;
      3. 请求体:get请求:没有请求体;post请求:请求体传递请求参数;
      4. GET:向特定的资源发出请求(a href="servlet"标签/js location.href=“servlet”)
      5. POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改
    2. 响应报文:响应行,响应头,响应体;

百科:HTTP协议

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。
所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。
1960年美国人TedNelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。
Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1
协议版本:
HTTP/1.0,发送请求,创建一次连接,获得一个web资源,连接断开。
HTTP/1.1,发送请求,创建一次连接,获得多个web资源,连接断开。

GET和POST请求区别
GET请求
请求行直接传递请求参数
将请求参数追加在URL后面,不安全。例如:form.html?username=jack&username=1234
URL长度限制GET请求方式的数据大小,不可以传输数据量较大或者非文本数据
请求体里面没有内容
POST请求
请求参数以请求体形式发送给服务器,数据传输安全
请求数据可以为非文本数据,可以传输数据量较大的数据
只有表单设置为method=”post”才是post请求.其他的都是get请求, 常见GET请求:地址栏直接访问、< a href=””>、< img src=””> 等

浏览器和服务器是以固定的格式进行通信的,采取的HTTP协议的请求协议。浏览器通过请求协议,将数据传送到服务器中。

request与请求数据的获取

通过request对象可以获取请求携带的数据,分别获取请求行、请求头、请求体中的数据,从而获取用户提交的数据,进行业务逻辑的处理。
什么是HttpServletRequest
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求中的所有信息都封装在这个对象中,我们通过这个对象的方法,可以获得客户这些信息。
HTTPServletRequest的作用
通过Request对象进行的常用操作:

  1. 获取请求行信息:请求方式,url和HTTP版本;
  2. 获取去请求头信息:浏览器类型,cookie等;
  3. 获取请求参数:url后面拼接的参数或者请求体中提交的参数;

获取请求行信息
请求行包括:请求方式,url和协议版本。HttpServletRequest对象提供了以下方法来获取这些信息。

  • String getMethod():获取去请求方式的类型。
  • StringBuffer getRequestURL():获取客户端发出请求完整URL。
  • String getRemoteAddr():获取IP地址。
  • String getProtocol():获取当前协议的名称和版本。

代码:

@WebServlet("/rowServlet")
public class RowServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //请求行API
        //获取请求协议版本号
        String protocol = request.getProtocol();
        System.out.println("protocol = " + protocol);

        //获取请求方式
        String method = request.getMethod();
        System.out.println("method = " + method);

        //IP地址
        String remoteAddr = request.getRemoteAddr();
        System.out.println("remoteAddr = " + remoteAddr);

        //获取URL
        StringBuffer requestURL = request.getRequestURL();
        System.out.println("requestURL = " + requestURL);
    }
}

获取请求头信息
浏览器的请求头信息是由很多:关键字:值 形式的数据组成的。HttpServletRequest对象给我们提供了两个方法用来获取请求的头信息。

  • String getHeader(String name):根据请求头的k关键字获取请求头信息。
  • Enumeration getHeaderNames():返回此请求包含的所有头信息的枚举。

请求头的k关键字如下表所示:

HTTP与request
代码:

@WebServlet("/headerServlet")
public class HeaderServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        //获取请求头API
        String header = request.getHeader("User-Agent");
        System.out.println("header = " + header);
        //获取所有key
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()){
            System.out.println(headerNames.nextElement());
        }
    }
}

获取请求体(请求参数)(很重要)

学习了请求航和请求头的内容,然后就是请求体了,在请求体中,包含的是用户通过浏览器发送的请求参数,因此,我们主要学习的就是获取请求参数的方法。
回顾一下浏览器中的请求数据是怎么提交的。
get请求:提交的数据是拼接在url后面。
post请求:数据是在请求体中发送到后台的。
两者的格式都是name=value

获取请求参数的方法

  • String getParameter(String name):getParameter获得指定参数名对应的值。如果没有返回null,如果有多个则获取第一个。例如username=jack。
  • String[ ] getParameterValues(name):getParameterValues[ ]获取请求数据key相同的多个数据。
  • request.getParameterMap():获取所有表单数据。

代码:
编写用户表单,提供表单字段:username、password、hobby、以post方式提交。
(由于没有设置utf-8,大家在提交数据时,尽量别用中文)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="requestServlet" method="post">

    用户名:<input type="text" name="username"/><br/>

    密码:<input type="text" name="password"/><br/>

    爱好:<input type="checkbox" name="hobby"value="smoking"/> 抽烟

    <input type="checkbox" name="hobby"value="drinking"/> 喝酒

    <input type="checkbox" name="hobby" value="tangtou"/> 烫头  <br/>

    学历:<select name="education">

        <option value="gaozhong">高中</option>

        <option value="dazhuan">大专</option>

        <option value="benke">本科</option>

    </select><br>

    <input type="submit"value="post提交" />
    </form>
</body>
</html>
@WebServlet("/requestServlet")
public class RequestServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取用户提交的所有数据
        String username=request.getParameter("username");
        System.out.println("用户提交的所有数据:useranme:"+username);

        String password=request.getParameter("password");
        System.out.println("-------------------password:"+password);

        String[] hobbies=request.getParameterValues("hobby");
        System.out.println("-------------------hobby:"+Arrays.toString(hobbies));

        //可以获取表单提交所有信息
        Map<String,String[]> parameterMap=request.getParameterMap();
        Collection<String[]> values=parameterMap.values();
        for (String[] value:values){
            System.out.println(Arrays.toString(value));
        }
    }
}

request作用域
request的生命周期

【一次请求和响应的完整流程】
1、浏览器向servlet发送请求
2、tomcat收到请求后,创建Request和Response两个对象,并将请求数据封装到request对象中,然后传递给Servlet
3、Servlet接收到请求后,调用request提供的方法。处理浏览器的请求信息,然后通过Response返回信息
4、tomcat将业务逻辑处理的结果,返回给浏览器。
5、浏览器接收到返回消息后,tomcat销毁Request和Response两个对象,同时销毁这两个对象所获得的信息。

  • 创建:浏览器给服务器发送请求后,tomcat创建request对象封装请求数据;
  • 销毁:服务器给浏览器响应信息结束后销毁;

特点:浏览器每次给服务器发送请求,服务器都会为这次请求创建一个request对象。

request域对象
request域对象,一个存储数据的区域对象.是把request当成一个容器来存储数据,request域存储数据主要是用于在两个servlet之间传递数据。request作为域对象,常用的方法如下:

  • void setAttribute(String name,Object o):往request域中设置值。
  • Object getAttribute(String name):从request域中取值。
  • void removeAttribute(String name):从request域中删除值。

演示:
创建一个servlet
往request域中设置值
从request域中取值
将request域中的值移除

@WebServlet("/value")
public class ValueServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用request对象存储值
        request.setAttribute("key","关晓彤");
        //根据KEY  来获取值
        String key = (String) request.getAttribute("key");
        System.out.println("美女 = " + key);

        //移除值
        request.removeAttribute("key");
        Object key1 = request.getAttribute("key");
        if (key1==null){
            System.out.println("删除成功");
        }
    }
}

注意:getParameter()方法和getAttribute()方法的区别

  1. getParameter()方法获取的是浏览器提交的数据(多是表单提交的数据);
  2. getAttribute()方法是获取request域中的数据(通过request.setAttribute()设置的值;

请求转发:
我们之前使用到的请求都是从页面发出,然后请求到Servlet。其实,在Servlet中。请求也可以从一个Servlet发起,然后请求到另一个Servlet或静态页面。这项技术叫做请求转发。
请求转发需要借助以下两个方法实现:

  • RequestDispatcher getRequestDispatcher(String path):获取请求转发器(request对象方法)
  • void forward(ServletRequest request, ServletResponse response):将请求转发到另一个资源(Servlet)上

演示:请求转发
需求:
从一个Servlet转发到另一个Servlet;
从一个Servlet转发到一个静态页面;

@WebServlet("/twoServlet")
public class TwoServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        doGet(req, resp);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        //通过request域对象设置值
        //使用转发 其他servlet
        req.setAttribute("name","xiaoming");
        //避免代码臃肿
        //获取请求转发器
        req.getRequestDispatcher("/thrServlet").forward(req,resp);
    }
}

@WebServlet("/thrServlet")
public class ThrServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        //获取数据,进行处理
        String name=(String)req.getAttribute("name");
        System.out.println("name="+name);
    }
}

从servlet转发到html

@WebServlet("/oneServlet")
public class OneServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //静态资源
        //使用转发
        req.getRequestDispatcher("/one.html").forward(req,resp);
    }
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>关晓彤</h1>
</body>
</html>

转发:

  • 转发是服务器内部的跳转行为;
  • 从一个Servlet转发到另一个资源(静态或者动态),能够实现跳转,但是浏览器地址栏没有改变,因为对浏览器来说,本质上只有一个请求。
  • 请求转发的作用:共享request域中的数据。

登录案例

需求:

  • 设计登录表单页面,数据库用户表user (字段 id,userName,password),通过sql手动插入若干用户数据记录。
  • 基于form表单数据提交,将客户端用户输入的账号和密码发送给服务器Servlet
  • Servlet获取表单提交的账号和密码数据,基于所学的JdbcTemplate直接访问数据库t_user表,查询账号和密码是否正确
  • 根据数据库查询的结果,如果账号密码错误,转发到error.html。账号密码都正确转发到success.html页面。

HTTP与request搭建环境:
HTTP与request