Skip to content

Request

Request对象 - 入门

获取请求行信息

tex
GET /http_request/login?username=user&password=pass HTTP/1.1

相关API

  • String getMethod()

    tex
    得到请求的方式:GET或POST
  • String getRequestURI()

    tex
    Uniform Resource Identifier 统一资源标识符,代表一个资源的名字
    URI = ContextPath + ServletPath
  • StringBuffer getRequestURL()

    tex
    Uniform Resource Locator 统一资源定位符,代表一个可以访问地址
  • String getProtocol()

    tex
    得到协议和版本
  • 【重点】String getContextPath()

    tex
    得到当前项目的访问地址
  • 【重点】String getServletPath()

    tex
    得到当前Servlet的访问地址

案例

  • 获取请求行信息并显示在终端上
实现
  • RequestLineServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/request_line")
    public class RequestLineServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            System.out.println("Method: " + request.getMethod());
            System.out.println("RequestURI: " + request.getRequestURI());
            System.out.println("RequestURL: " + request.getRequestURL());
            System.out.println("Protocol: " + request.getProtocol());
            System.out.println("ContextPath: " + request.getContextPath());
            System.out.println("ServletPath: " + request.getServletPath());
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
输出
tex
Method: GET
RequestURI: /http_request/request_line
RequestURL: http://localhost:8080/http_request/request_line
Protocol: HTTP/1.1
ContextPath: /http_request
ServletPath: /request_line

小结

  • request.getContextPath()

项目路径

  • request.getServletPath()

资源路径

获取请求头信息

tex
Host: localhost:8080

Connection: keep-alive

Content-Type: application/x-www-form-urlencoded

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6

相关API

  • 【重点】String getHeader(String headName)

    tex
    指定请求头中键,得到相应的值
  • Enumeration<String> getHeaderNames()

    tex
    得到请求头中所有的键
Enumeration接口
tex
Enumeration是枚举类型的集合,类似于迭代器
IteratorEnumeration
hasNext()hasMoreElements()
next()nextElement()
  • boolean hasMoreElements()

    tex
    判断是否还有下一个元素,如果有返回true
  • E nextElement()

    tex
    得到当前元素,并且向下移动一个元素

案例1

需求
  • 获取请求头信息并显示在终端上
实现
  • RequestHeaderServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Enumeration;
    
    @WebServlet("/request_header")
    public class RequestHeaderServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                System.out.println(headerName + ": " + request.getHeader(headerName));
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
输出
tex
host: localhost:8080
connection: keep-alive
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6
cookie: JSESSIONID=7D790A7277BAFB203442AA8F084217F7

案例2

需求
  • 获取浏览器版本并显示在命令行上

    tex
    判断是Edge、Chrome、Safari、Firefox或IE浏览器
实现
java
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/request_header")
public class RequestHeaderServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent.contains("Edge")) {
            System.out.println("Edge浏览器");
        } else if (userAgent.contains("Chrome")) {
            System.out.println("Chrome浏览器");
        } else if (userAgent.contains("Safari")) {
            System.out.println("Safari浏览器");
        } else if (userAgent.contains("Firefox")) {
            System.out.println("Firefox浏览器");
        } else {
            System.out.println("IE浏览器");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
输出
tex
Chrome
Firefox
Safari

小结

  • 请求行

    • getContextPath

    获取项目路径

    • getServletPath

    获取资源路径

  • 请求头

    • getHeader

    传入请求头的键,值作为getHeader函数的返回值

获取请求参数[重点]

  • POST

    tex
    username=user&password=pass
  • GET

    tex
    GET /http_request/login?username=user&password=pass HTTP/1.1

相关API

  • String getParameter(String name)

    通过参数名得到参数的值

  • String[] getParameterValues(String name)

    通过参数名得到一组参数值,返回是字符串的数组

  • 【非重点】Enumeration<String> getParameterNames()

    得到所有参数的名字,返回是枚举的类型

  • Map<String, String[]> getParameterMap()

    得到表单提交的所有参数名和参数值,封装成一个Map集合

  • Part request.getPart(String name)

    Gets the Part with the given name.

  • Collection<Part> getParts()

    Gets all the Part components of this request, provided that it is of type multipart/form-data.

案例

  • 获取注册表单提交的数据并输出到页面上
实现
  • index.html

    html
    <html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
    <form action="request_body" method="get">
        <input type="text" name="username" placeholder="用户名"/><br/>
        <input type="password" name="password" placeholder="密码"/><br/>
        爱好:
        <input type="checkbox" name="hobby" value="eat"/>吃饭
        <input type="checkbox" name="hobby" value="sleep"/>睡觉
        <input type="checkbox" name="hobby" value="hit dodo"/>打豆豆
    
        <input type="submit" value="登录"/>
    </form>
    </body>
    </html>
  • RequestBodyServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.Enumeration;
    import java.util.Map;
    import java.util.Set;
    
    @WebServlet("/request_body")
    public class RequestBodyServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            
            System.out.println("username: " + request.getParameter("username"));
            System.out.println("password: " + request.getParameter("password"));
            System.out.println("hobby: " + Arrays.toString(request.getParameterValues("hobby")));
    
            System.out.println("----");
            Enumeration<String> names = request.getParameterNames();
            while(names.hasMoreElements()) {
                String pname = names.nextElement();
                System.out.println(pname + ": " + request.getParameter(pname));
            }
    
            System.out.println("----");
            Map<String, String[]> map = request.getParameterMap();
            Set<Map.Entry<String, String[]>> entries = map.entrySet();
            for (Map.Entry<String, String[]> entry : entries) {
                System.out.println(entry.getKey() + ": " + Arrays.toString(entry.getValue()));
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
输出
tex
namename: user
password: pass
hobby: [eat, sleep]
----
namename: user
password: pass
hobby: eat
----
username: [user]
password: [pass]
hobby: [eat, sleep]

小结

  • String getParameter(String name)

    获取参数值(一个名字,对应一个值)

  • String[] getParameterValues(String name)

    获取参数值(一个名字,对应多个值)

  • Map<String, String[]> getParameterMap()

    获取参数值(获取所有的参数名和参数值)

参数乱码问题

  • GET 方式的乱码解决方案

    tex
    Tomcat 8.5,GET方式无乱码问题
  • POST 方式的乱码解决方案

    tex
    request.setCharacterEncoding("utf-8");

小结

http://localhost:8080/JavaWeb_day02_Request_war_exploded/request_body

  • 获取请求行信息

    • getContextPath

    获取项目路径

    • getServletPath

    获取资源路径

  • 获取请求头信息

    • String getHeader("name")

    获取请求头,参数传入name,value作为返回值

  • 获取请求参数信息

    • getParameter

    传一个key,返回一个value

    • getParameterValues

    传一个key,返回所有value

    • getParameterMap

    不传参数,返回所有的key和value

  • 参数乱码问题

    request.setCharacterEncoding("utf-8")

  • 注意

    utf-8不是解决乱码问题的万金油

    乱码是因为编码和解码不一致造成的

Request - 深入

转发

定义

用于资源跳转,从一个资源跳转到另一个资源

Forward

相关API

java
request.getRequestDispatcher("/resourceB").forward(request, response);
方法说明
RequestDispatcher getRequestDispatcher(String path)获取请求转发器(request对象方法)
void forward(ServletRequest request, ServletResponse response)将请求转发到另一个资源(Servlet)上

特点【重点】

  • 地址不变
  • 服务器内部跳转
  • 一次请求

案例

  • 浏览器请求 AServlet,转发至 BServlet
实现
java
package com.futureweaver.request;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/resourceA")
public class AServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("AServlet接收到了用户的请求");
        //... 处理自己所负责的业务

        // 通过getRequestDispatcher,获得一个请求调度器
        // 让调度器,转发到"/resourceB"
        // 并且通过forward进行转发
        // 转发时,需要两个参数,一个是request,一个是response
        request.getRequestDispatcher("/resourceB").forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

请求域【重点】

问题

Request-Scope

相关API

  • Object getAttribute(String key)
tex
从作用域中取出值
  • void setAttribute(String key, Object obj)
tex
向作用域中添加键和值,如果之前没有这个键则是添加,如果有就是修改
  • void removeAttribute(String key)
tex
删除指定的键和值

作用

服务器内存区域,用于数据存储

一个盒子,在盒子里面可以存储物品(Object)

小结

  • request.getRequestDispatcher("/资源路径").forward(request, response)
  • void request.setAttribute(String key, Object obj);
  • Object request.getAttribute(String key)
  • void request.removeAttribute(String key)

Request 对象生命周期【难点】

一个对象从创建到销毁的全过程

HTTP-Composition

  • 什么时候创建

    当服务器接收到了浏览器的请求时

  • 什么时候销毁

    当响应结束时

  • 由谁创建

    Tomcat

  • 由谁销毁

    Tomcat

小结

  • 转发的特点

    1. 一次请求
    2. 地址不变
    3. 服务器内部跳转
  • 转发

    java
    request.getRequestDispatcher("/资源路径").forward(request, response)
  • Request 的生命周期

    • 创建

      服务器接收到浏览器的请求时,由Tomcat创建

    • 销毁

      响应结束时,由Tomcat销毁

案例

需求

  • 静态资源-HTML 登录页面(帐号框、密码框、登录按钮)

  • 登录表单提交至 LoginServlet

    利用MyBatis获取真实数据并进行比对

  • 若登录成功,转发至登录成功(LoginSuccessServlet)

  • 若登录失败,转发至登录失败(LoginFailureServlet)

ver 0.1 原生方式

实现

  • index.html

    html
    <html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
    <form action="login" method="post">
        <input type="text" name="username" placeholder="用户名"/><br/>
        <input type="password" name="password" placeholder="密码"/><br/>
        爱好:
        <input type="checkbox" name="hobby" value="吃饭"/>吃饭
        <input type="checkbox" name="hobby" value="睡觉"/>睡觉
        <input type="checkbox" name="hobby" value="打豆豆"/>打豆豆
    
        <input type="submit" value="登录"/>
    </form>
    </body>
    </html>
  • LoginServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
    
            String username = request.getParameter("username");
            String password = request.getParameter("password");
    
            if (username.equals("user") && password.equals("pass")) {
                request.getRequestDispatcher("/login_success").forward(request, response);
            } else {
                request.getRequestDispatcher("/login_failure").forward(request, response);
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
  • LoginSuccessServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/login_success")
    public class LoginSuccessServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            System.out.println(request.getParameter("username") + " login success!");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
  • LoginFailureServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/login_failure")
    public class LoginFailureServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            System.out.println(request.getParameter("username") + " login failure!");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }

ver 0.2 JavaBean方式

什么是JavaBean

  • 类必须用 public 修饰

  • 提供 publi 无参数的构造器

  • 提供 getter 和 setter 方法访问属性

JavaBean的两个概念

  • 字段
tex
就是成员变量,字段名就是成员变量名
  • 属性
    • 通过 setter 或 getter 方法获得
    • 属性名: setter/getter 方法去掉 set/get 前缀,首字母小写
    • 比如: setName() -> Name -> name
    • 一般情况下,字段名称和属性名称是一致的

实现

  • index.html

    html
    <html>
      <head>
        <meta charset="UTF-8">
        <title></title>
      </head>
      <body>
      <form action="login" method="post">
        <input type="text" name="username" placeholder="用户名"/><br/>
        <input type="password" name="password" placeholder="密码"/><br/>
        <input type="submit" value="登录"/>
      </form>
      </body>
    </html>
  • UserInfo.java

    java
    public class UserInfo {
        private String username;
        private String password;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public UserInfo() {
        }
    
        public UserInfo(String username, String password) {
            this.username = username;
            this.password = password;
        }
    }
  • LoginServlet.java

    java
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
    
            UserInfo userInfo = new UserInfo();
            userInfo.setUsername(request.getParameter("username"));
            userInfo.setPassword(request.getParameter("password"));
    
            if (userInfo.getUsername().equals("user") && userInfo.getPassword().equals("pass")) {
                request.getRequestDispatcher("/login_success").forward(request, response);
            } else {
                request.getRequestDispatcher("/login_failure").forward(request, response);
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }

ver 1.0 BeanUtil方式

问题

Request-Content

  • LoginServlet.java
java
UserInfo userInfo = new UserInfo();
userInfo.setUsername(request.getParameter("username"));
userInfo.setPassword(request.getParameter("password"));
  • RegisterServlet.java
java
UserProfile userProfile = new UserProfile();
userProfile.setUsername(request.getParameter("username"));
userProfile.setPassword(request.getParameter("password"));
userProfile.setGender(request.getParameter("gender"));
userProfile.setMobile(request.getParameter("mobile"));
userProfile.setAvatar(request.getParameter("avatar"));

BeanUtils 工具包

  • commons-beanutils-1.9.3.jar

    tex
    核心工具包
  • commons-logging-1.2.jar

    tex
    日志记录包
  • commons-collection-3.2.2.jar

    tex
    增强集合包

BeanUtils常用方法

  • setProperty(Object obj, String name, Object value)

    tex
    给指定对象obj的指定属性name附值指定的值value
    如果属性不存在,则什么也不发生
  • getProperty(Object obj, String name)

    tex
    获取指定对象obj指定属性name的值
    如果属性不存在,则会抛出异常
  • copyProperties(Object dest, Object orig)

    tex
    将一个对象的值赋值给另一个对象
    只有相同属性名才会赋值
    简单记忆: "后付钱" -> 即将后一个对象的值赋值给前一个对象
  • populateObject bean, Map<String, String[]> properties

    tex
    将Map集合中的数据封装到JavaBean对象中

实现

  • LoginServlet.java

    java
    import org.apache.commons.beanutils.BeanUtils;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.util.Map;
    
    @WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
    
            Map<String, String[]> parameterMap = request.getParameterMap();
            UserInfo userInfo = new UserInfo();
            try {
                BeanUtils.populate(userInfo, parameterMap);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    
            if (userInfo.getUsername().equals("user") && userInfo.getPassword().equals("pass")) {
                request.getRequestDispatcher("/login_success").forward(request, response);
            } else {
                request.getRequestDispatcher("/login_failure").forward(request, response);
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }

ver 2.0 MyBatis方式

项目结构

  • resources
    • log4j.properties
    • mybatis-config.xml
    • UserMapper.xml
  • src
    • com.futureweaver
      • domain
        • User.java
      • mapper
        • UserMapper.java
      • utils
        • SessionFactoryUtil.java
      • service
        • UserService.java
      • web
        • LoginServlet.java
  • web
    • WEB-INF
      • lib
        • commons-beanutils-1.9.3.jar
        • commons-logging-1.2.jar
        • commons-collection-3.2.2.jar
        • log4j-1.2.17.jar
        • mybatis-3.5.3.jar
        • mysql-connector-j-8.2.0.jar
      • web.xml
    • index.html

学习目标总结

  • 能够应用 Request 对象的方法
  • 能够了解 Request 请求头信息
  • 能够应用 Request 对象解决获取请求参数中文乱码问题
  • 能够应用 BeanUtils 工具类对请求参数数据进行封装
  • 请求域
  • 转发的三个特点
  • 能够独立运用 Servlet 技术完成登录功能