Request详解

Mr.he...大约 6 分钟JavaWebRequest

1. request对象和response对象的基本理解

  1. request和response对象是由服务器创建的。我们只是来使用它们;
  2. request对象的作用是获取请求消息,response对象的作用是设置响应消息。

2. request对象和response对象的原理

3. request对象继承体系结构

ServletRequest		--	接口
	|	继承
HttpServletRequest	-- 接口
	|	实现
org.apache.catalina.connector.RequestFacade//该位置是实现HttpServletRequest接口中的request方法的位置。

tomcat源码下的实现类,打开看源码可以发现继承了HttpServletRequest接口。

4. request功能

主要可以获取请求消息数据,包括请求行、请求头、请求体的数据。

4.1. 获取请求行数据

此处示例的请求行的数据内容为GET /today/demo1?name=zhangsan HTTP/1.1

  • 方法:
    1. 获取请求方式 :GET String getMethod()
    2. (重点)获取虚拟目录:/today String getContextPath()
    3. 获取Servlet路径: /demo1 String getServletPath()

经常在表单action的路径中用该方法,这样修改servlet路径后,会跟着变化,不用再去修改。

  1. 获取get方式请求参数:name=zhangsan String getQueryString()
  2. (重点)获取请求URI:/today/demo1 String getRequestURI(): /today/demo1 StringBuffer getRequestURL() :  http://localhost/today/demo1 URL:统一资源定位符 : http://localhost/today/demo1 中华人民共和国 URI:统一资源标识符 : /today/demo1 共和国

URL和URI的区别:URL是全路径包含HTTP协议、IP地址、资源路径, URI是资源路径。

  1. 获取协议及版本:HTTP/1.1 String getProtocol()
  2. 获取客户机的IP地址: String getRemoteAddr()

重点掌握获取虚拟目录:/today 和获取请求URI:/today/demo1的方法。

4.2. 获取请求头数据

  • 方法:
    1. (重点)String getHeader(String name):通过请求头的名称获取请求头的值
    2. Enumeration<String> getHeaderNames():获取所有的请求头名称
  • 常用的请求头
    1. User-Agent 浏览器告诉服务器,我访问你使用的浏览器版本信息。可以在服务器端获取该头的信息,解决浏览器的兼容性问题。

  1. Referer:http://localhost:8080/today/login.html 告诉服务器,我(当前请求)从哪里来。 - 作用:
    1. 防盗链,比如防止盗版网站直接使用正版链接作为外链;
    2. 统计工作,比如统计访问量。

4.3. 获取请求体数据

只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数。

  • 步骤:
    1. 获取流对象; - BufferedReader getReader():获取字符输入流,只能操作字符数据; - ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据。

获取字节输入流,在后续学习文件上传知识点中讲解。

  1. 再从流对象中拿数据;

这里还需要创建一个login.html的表单页面将数据提交到RequestDemo5的虚拟路径/demo5中。

5. 其他功能

该部分介绍的功能都是很常用的方法。

5.1. 获取请求参数通用方式

不论get还是post请求方式都可以使用下列方法来获取请求参数,非常重要。

  • 通用方式:
    1. String getParameter(String name):根据参数名称获取参数值。    username=zs&password=123
    2. String[] getParameterValues(String name):根据参数名称获取参数值的数组,比如复选框的值。  hobby=game&hobby=study
    3. Enumeration<String> getParameterNames():获取所有请求的参数名称。
    4. Map<String,String[]> getParameterMap():获取所有参数的map集合。
  • 代码部分:
<!--login.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<form action="/today/demo6" method="post">
    <input type="text" name="username"><br>
    <input type="text" name="password"><br>
    <input type="checkbox" name="hobby" value="game">游戏
    <input type="checkbox" name="hobby" value="study">学习<br>
    <input type="submit" value="提交">

</form>

</body>
</html>
//RequestDemo6.java,其中去除了导包的代码
@WebServlet("/demo6")
public class RequestDemo6 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置编码
        request.setCharacterEncoding("utf-8");		
        //post 获取请求参数

        //1. 根据参数名称获取参数值
        String username = request.getParameter("username");
        System.out.println("1. post请求方式:"+username);//1. post请求方式:zhangsan

        //2. 根据参数名称获取参数值大的数组
        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println("2. "+hobby);//2. game 2. study
        }

        //3. 获取所有请求的参数名称
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();
            String value = request.getParameter(name);
            System.out.println("3. "+name +":"+value);
            //3. username:zhangsan 3. password:1234 3. hobby:game
            //此处存在问题是复选框的值只打印了一个。
        }
        //4. 获取所有参数的map集合
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String key : parameterMap.keySet()) {
            String name = key;
            String[] values = parameterMap.get(name);
            System.out.println("4. "+name+":"+ Arrays.toString(values));
            //4. username:[zhangsan] 4. password:[1234] 4. hobby:[game, study]
            //完美解决了复选框只打印一个值的问题
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
        //get 获取请求参数
        //根据参数名称获取参数值
        String username = request.getParameter("username");
        System.out.println("get请求方式:"+username);
        */
        this.doPost(request,response);
    }
}
  • 中文乱码问题 tomcat 8 已经将get方式乱码问题解决了,但post方式还会乱码。
    • 解决方法 在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");

5.2. 请求转发

一种在服务器内部的资源跳转方式。

  • 步骤:
    1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
    2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
  • 特点:
    1. 浏览器地址栏路径不发生变化,状态码为200;
    2. 只能转发到当前服务器内部资源中,服务器外部的资源会报404;
    3. 转发只有一次请求,使用的只有demo7。

5.3. 共享数据

  • 相关概念:
    1. 域对象:一个有作用范围的对象,可以在范围内共享数据;
    2. request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据。
  • 方法:
    1. void setAttribute(String name,Object obj):存储数据;
    2. Object getAttitude(String name):通过键获取值;
    3. void removeAttribute(String name):通过键移除键值对。

一般只能用于请求转发中共享数据。

  • 代码部分
@WebServlet("/demo7")
public class RequestDemo7 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("msg","hello");
        System.out.println("demo7...");
        request.getRequestDispatcher("/demo8").forward(request,response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}
@WebServlet("/demo8")
public class RequestDemo8 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object msg = request.getAttribute("msg");
        System.out.println("demo8...");
        System.out.println(msg);//hello
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

5.4. 获取ServletContext

@WebServlet("/demo9")
public class RequestDemo9 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext servletContext = request.getServletContext();
        System.out.println(servletContext);//这里只需了解获取servletContext
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

主要有获取MIME类型、域对象和获取文件的真实(服务器)路径。该部分功能放到后面部分open in new window详细讲解。