Live2D
复制代码

11-HttpServletRequest接口解析

1、解析HttpServletRequest接口

HttpServlet模板类中的service方法中需要两个参数对象,分别是HttpServletRequest类型和HttpServletResponse类型的,分别探讨。
--研究:javax.servlet.http.HttpServletRequest接口
	1、这是Servlet规范中的一个重要接口
	
	2、继承关系:
	public interface HttpServletRequest extends ServletRequest{}
	
	3、该接口的实现类是web容器负责的,Tomcat服务器有自己的实现。
	所以说跟前面讲的几个接口一样,程序员只需要面向接口调用,无需关系具体的实现内容
	
	4、该接口封装的信息:
	--封装的是请求协议中的全部内容
		请求方式(这就是为什么该接口中有获取请求方式字符串返回的方法)
		URL
		协议版本号
		表单提交的数据
		...
	
	5、HttpServletRequest接口类型的变量名一般定义为:request,表示请求。
	一个HttpServletRequest对象表示一次请求,100个请求对应该类型对象100个
	所以说request对象的生命周期是短暂的
	--一次请求:目前为止,这样理解:在网页上点击超链接,最终到网页停下来,是一次完整的请求
	
	6、该接口中的常用方法
	--对请求中提交的表单数据操作的方法如下
	(要注意下面几个方法是继承于ServletRequest接口中的方法):
	表单中提交的数据被封装到request对象中,该对象中的map集合存储这些数据:
	Map集合中的key是name,vluae是一个String类型是一维数组
	--String getParameter(String name)
	该方法通过key获取value一维数组中首元素
	(通常情况下,这个一维数组只存一个元素,所以该方法使用次数最多)
	--String[] getParameterValues(String name)
    该方法是通过Map集合中的key获取value
    (这个就可以获取到value一维数组中的其他元素,使用次数比上面少)
    
	--Map getParameterMap()
	该方法获取存储表单提交数据的那个Map集合对象
	--Enumeration getParameterNames()
	该方法获取Map集合对象中的key,存放到一个Enumeration类型的集合中(该集合前面见到过)

2、接口中常用方法中对提交的表单数据操作方法的示例

2.1 创建名为idea-servlet-http-8的web项目,配置好相应环境。

2.2 编写一个注册表单页面,register.html,设置为欢迎页面

register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>register page</title>
</head>
<body>
    <form action="/idea-servlet-http-8/query" method="post">
        用户名
             <input type="text" name="username" >
        <br>
        密码
            <input type="password" name="password">
        <br>
        性别
            男<input type="radio" name="sex" value="f">
            女<input type="radio" name="sex" value="m">
        <br>
        爱好
            <input type="checkbox" name="hobby" value="sport">运动
            <input type="checkbox" name="hobby" value="music">音乐
            <input type="checkbox" name="hobby" value="dance">跳舞
            <input type="checkbox" name="hobby" value="study">学习
            <input type="checkbox" name="hobby" value="read">阅读
        <br>
        学历
            <select name="grade">
                <option value="primary">小学</option>
                <option value="high">高中</option>
                <option value="college">大学</option>
            </select>
        <br>
        简历
            <textarea rows="10" cols="60" name="introduce"></textarea>
        <br>
        <input type="submit" value="注册">
        <input type="reset" value="重置">
    </form>
</body>
</html>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <welcome-file-list>
        <welcome-file>注册用户</welcome-file>
        <welcome-file>/register.html</welcome-file>
    </welcome-file-list>
    
    <servlet>
        <servlet-name>register</servlet-name>
        <servlet-class>com.servlet.httpservletrequest.RequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>register</servlet-name>
        <url-pattern>/query</url-pattern>
    </servlet-mapping>
</web-app>
RequestServlet.java
package com.servlet.httpservletrequest;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

public class RequestServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取表单提交的用户信息,这些数据被封装到request对象中
        //用request对象里的方法就可以获取这些信息了
        /*
            表单提交数据的格式如下,用POST请求方式,数据格式如下:
            username=admin&password=123&sex=m&hobby=sport&hobby=music&grade=college&introduce=ok
            而这些信息封装到request对象中实际是存到一个map集合中的,且集合中的value是一个数组类型
            如下:
            Map<String,String[]>
            key             value
            -----------------------------
            username        {"admin"}
            password        {"123"}
            sex             {"m"}
            hobby           {"sport","music"}
            grade           {"college"}
            introduce       {"ok"}
         */

        //测试方法:String getParameter(String name)
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String hobby = request.getParameter("hobby");
        String grade = request.getParameter("grade");
        String introduce = request.getParameter("introduce");
        System.out.println(username);
        System.out.println(password);
        System.out.println(sex);
        System.out.println(hobby);
        System.out.println(grade);
        System.out.println(introduce);
        System.out.println("==================================================");

        //测试方法:String[] getParameterValues(String name)
        //这里只有爱好hobby可以选择多个,所以下面只获取表单数据中爱好的数据
        String[] interest = request.getParameterValues("hobby");
        //遍历集合interest
        for (String value:
             interest) {
            System.out.println(value);
        }
        System.out.println("==================================================");

        //测试方法:Map getParameterMap()
        Map<String,String[]> data = request.getParameterMap();
        //获取data集合中的key并且存放进一个Set集合中
        Set keys1 = data.keySet();
        //遍历keys集合获取data中的value
        for (Object name:
             keys1) {
            System.out.println(data.get(name));
            String[] values = data.get(name);
            System.out.print(name+" = ");
            for (String value:
                 values) {
                System.out.print(value+" ");
            }
            System.out.println();
        }
        System.out.println("==================================================");
        //从输出结果可以看做出,data集合中的value是每个类型数据的数组对象
        //数组的toString方法输出如:[Ljava.lang.String;@7c910271,即[L+完整的类名;@+内存地址经过hash计算转换成16进制

        //测试方法:Enumeration getParameterNames()
        Enumeration names = request.getParameterNames();
        //遍历names集合获取其中Map集合中的value
        while (names.hasMoreElements()){
            String keys2 = (String)names.nextElement();
            String[] values = request.getParameterValues(keys2);
            System.out.print(keys2+" = ");
            for (String value:
                values ) {
                System.out.print(value+" ");
            }
            System.out.println();
        }

    }
}

2.3 输出如下

MeteoAdmin
123456
f
sport
college
ok

==================================================
sport
music
dance
study
read
==================================================
[Ljava.lang.String;@65272c20
username = MeteoAdmin 
[Ljava.lang.String;@324f44a1
password = 123456 
[Ljava.lang.String;@290ca47
sex = f 
[Ljava.lang.String;@22b94d25
hobby = sport music dance study read 
[Ljava.lang.String;@7e23237e
grade = college 
[Ljava.lang.String;@36011a57
introduce = ok
 
==================================================
username = MeteoAdmin 
password = 123456 
sex = f 
hobby = sport music dance study read 
grade = college 
introduce = ok
 

3、该接口中的常用方法

--比较简单的常用方法如下:
	-String getContextPath() 
    //获取上下文的路径(就是webapp的根路径,/部署在服务器上的项目名)
    
	String getMethod()	
    //获取请求方式
    
	String getRequestURI()
    //获取URI
    //(/服务器上项目名/资源路径,/资源路径就是web.xml文件中url-pattern标签中的路径)
    
	StringBuffer getRequestURL()
    //获取URL请求路径
    
	String getServletPath()
    //获取Servlet PATH(就是资源路径,url-pattern标签中的路径)
    
	String getRemoteAddr()
    //获取发送请求的客户端的IP地址
	
--与ServletContext接口中相似的方法
	Object getAttribute(String name)	//向request对象中读取数据	
	void setAttribute(String name, Object o)	//向request对象中添加数据
	void removeAttribute(String name)	//向request对象中移除数据
    
	--HttpServletRequest范围:
    首先该接口类型的变量命名为 request,代表当前的本次请求。
    一次请求对应一个request对象,100个对应100个。请求范围极小,request只能在同一次请求中传递数据。
    
ServletContext接口中的方法作用
	Object getAttribute(String name)	--//从ServletContext范围中读取数据
	void setAttribute(String name, Object o) --//从ServletContext范围中添加数据
	void removeAttribute(String name)	--//从ServletContext范围中移除数据
	--ServletContext范围是一个所有用户共享的范围对象
    一般把ServletContext类型的变量命名为application。
    可知该对象代表一个应用。一个webapp只有一个该对象,范围极大。
    
关于范围的选择:
	1、ServletContext 应用范围,可以跨用户传输
	2、HttpServletRequest 请求范围,只能在一个请求中传递数据
    【可以跨Servlet对象传递数据,但这多个Servlet的必须在同一个请求当中】
	优先选择request范围
	
--获取转发器对象的方法
	RequestDispatcher getRequestDispatcher(String path)
	--使用方法:获取转发器后使用转发器的forward方法将request和response对象传进去就可以转发了
	因为转发到的路径所需要的是本次请求的request和response对象,所以还是同一次请求
	
--解决乱码的方法
	void setCharacterEncoding(String env) 
	
--Cookie[] getCookies()  学习Cookies
-- HttpSession	getSession()	学习Session
--HttpSession	getSession(boolean create)

3.1 创建web项目测试上面两类方法

创建web项目idea-servlet-http-9,测试上面两类方法(简单常用以及与ServletContext接口相同的)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试HttpServletRequest</title>
</head>
<body>
    <a href="/idea-servlet-http-9/method/test">测试request</a>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.servlet.httpservletrequest.RequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/method/test</url-pattern>
    </servlet-mapping>
</web-app>
RequestServlet.java
package com.servlet.httpservletrequest;

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

public class RequestServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        //获取上下文路径(webapp根路径)
        String webPath = request.getContextPath();
        out.print(webPath);
        out.print("<br>");

        //获取浏览器的请求方式
        String method = request.getMethod();
        out.print(method);
        out.print("<br>");

        //获取URI
        String uri = request.getRequestURI();
        out.print(uri);
        out.print("<br>");

        //获取URL
        StringBuffer url = request.getRequestURL();
        out.print(url);
        out.print("<br>");

        //获取Servlet Path
        String servletPath = request.getServletPath();
        out.print(servletPath);
        out.print("<br>");

        //获取客户端IP地址
        String ip = request.getRemoteAddr();
        out.print(ip);
        out.print("<br>");
    }
}

测试结果如下:

4、下面测试后面的三个方法和一个获取请求转发器的方法

首先我们创建了两个类继承HttpServlet,分别是AServlet和BServlet;再创建一个实体类User,其中有两个属性userCode和userName。我们在AServlet类中创建一个User对象并给两个属性赋值,将该对象用

void setAttribute(String name, Object o)方法添加进request对象范围,然后在该类中用getAttribute(String name)方法获取数据,部署项目启动服务器,对AServlet对象发送一个请求,可以成功获取request对象中存进去的数据;然后在BServlet类中写一个获取数据的方法,然后部署项目启动服务器,先发送一个对AServlet对象的请求,使其运行对request对象添加数据的方法,然后发送一个对BServlet对象的请求,结果是没有从该请求的request范围对象中获取数据。因为这里是两个请求,所以是两个request对象,肯定是获取不到另一个request对象中的数据的。

那么我们将对这两个对象的请求合并成一个请求,是可以获取到的,需要用到转发技术。实现方法如下

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试HttpServletRequest</title>
</head>
<body>
    <a href="/idea-servlet-http-9/method/test">测试request</a><br>
    <a href="/idea-servlet-http-9/method/a">测试request</a><br>
    <a href="/idea-servlet-http-9/method/b">测试request</a>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.servlet.httpservletrequest.RequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/method/test</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>AServlet</servlet-name>
        <servlet-class>com.servlet.httpservletrequest.AServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AServlet</servlet-name>
        <url-pattern>/method/a</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>BServlet</servlet-name>
        <servlet-class>com.servlet.httpservletrequest.BServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>BServlet</servlet-name>
        <url-pattern>/method/b</url-pattern>
    </servlet-mapping>
</web-app>
AServlet.java
package com.servlet.httpservletrequest;

import com.servlet.entity.User;

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

public class AServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //创建一个User对象
        User user = new User();
        user.setUserCode("16020521234");
        user.setUserName("nick");

        //将User对象存放进request范围对象中
        request.setAttribute("user",user);

        //取出request范围中的数据
        //Object obj = request.getAttribute("user");
        //response.getWriter().print(obj);

        //希望在另一个Servlet对象中取出本request范围中的数据
        //将另一个对象的请求容纳进本对象的请求中,就可以共用本对象的request范围了
        //跳转
        //执行完AServlet后,跳转到BServlet继续执行,这样两个类对象就放到同一个请求中了
        //使用转发技术,forward(转发)方法

        //1、获取获取转发器对象(以下转发器指向了BServlet,路径中是url-pattern标签中的内容)
        RequestDispatcher dispatcher = request.getRequestDispatcher("/method/b" );
        //2、调用转发器的forward方法将request和response传过去就可完成转发,共用一个request和response对象
        dispatcher.forward(request,response);

    }
}


BServlet.java
package com.servlet.httpservletrequest;

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

public class BServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //取出request范围中的数据
        Object obj = request.getAttribute("user");
        response.getWriter().print(obj);

    }
}

测试结果如下:

通过操作,当我们点击AServlet的时候,即使获取本请求request对象数据的方法在另一个Servlet对象中,仍然将数据获取到了;我们返回,点击BServlet时,是无法获取数据的。
posted @ 2021-08-08 00:09  Milen-jie  阅读(398)  评论(1编辑  收藏  举报