(10)HttpServletRequest请求域的作用及其常用方法

HttpServletRequest请求对象接口

HttpServletRequest接口是Tomcat服务器提供的org.apache.catalina.connector.RequestFacade给实现的,它的父接口是ServletRequest

public interface HttpServletRequest extends ServletRequest {}

public class RequestFacade implements HttpServletRequest {}

jakarta.servlet.http包下的类和接口

  • HttpServletRequest: Tomcat服务器将“请求协议”中的数据全部解析出来,然后将这些数据全部封装到request对象当中
  • HttpServletResponse: Tomcat服务器将“响应协议”中的数据全部解析出来,然后将这些数据全部封装到response对象当中

HttpServletRequest接口是用来封装“请求协议”中的数据的对象(请求域)是Servlet规范中的一员,全类名是jakarta.servlet.http.HttpServletRequest

  • 因为用户发送请求的时候遵循了HTTP协议,所以发送的是HTTP的请求协议
  • Tomcat服务器将HTTP协议中的信息以及数据全部解析出来,然后把这些信息封装到HttpServletRequest对象当中,传给了我们javaweb程序员
  • javaweb程序员面向HttpServletRequest接口编程,通过调用HttpServletRequest的方法获取到请求参数的信息

HttpServletRequest对象创建和销毁的时机

  • 当用户每发送一次请求时Tomcat服务器就会创建一个HttpServletRequest对象, 一次请求就会对应一个request/response
  • request和response对象的生命周期都只在当前请求中有效

获取查询字符串的方法

HttpServletRequest采用Map<String, String[]>的数据结构封装请求参数,采用String[]可以避免Map集合key重复的时候value覆盖问题

  • 前端提交的数据永远都是字符串,后端获取的也是字符串(前端提交的数字120其实是以字符串"120"的方式提交的)
#前端提交的数据格式:username=abc&userpwd=111&aihao=s&aihao=d&aihao=tt

#Map<String,String>结构中key重复的时候value会覆盖
key         value
---------------------
username    abc
userpwd     111
aihao       s
aihao       d
aihao       tt

#Map<String, String[]>,采用String[]可以避免Map集合key重复的时候value覆盖问题
key				value
-------------------------------
username		{"abc"}
userpwd			{"111"}
aihao			{"s","d","tt"}

HttpServletRequest父接口是ServletRequest , ServletRequest接口的方法的子类可以直接继承

方法名功能
Map<String,String[]> getParameterMap()获取请求参数参数的Map集合形式
Enumeration< String > getParameterNames()获取Map集合中所有的key
String[] getParameterValues(String name)根据Map集合的key获取Map集合的value
String getParameter(String name)根据Map集合的key获取value这个一维数组当中的第一个元素(最常用),大部分一维数组中只有一个元素

获取请求参数的方式

  • 第一种: 使用getParameterMap方法获取请求参数的Map集合,使用Map集合的keyset方法获取所有key,使用Map集合的put方法根据key获取一维数组values
  • 第二种: 通过request对象的getParameterNames方法获取参数Map集合的所有key/name,遍历每一个key使用getParameterValues获取其对应的一维数组values
  • 第三种: 直接通过request对象的getParameterValues方法根据Map集合中key的名称获取其对应的一维数组values
  • 第四种: 直接通过request对象的getParameter方法根据Map集合中key的名称获取其对应的一维数组values的第一个元素
#前端提交的数据username=zhangsan&userpwd=123&interest=s&interest=d会被服务器采用Map<String,String[]>结构封装到request对象中
key				value
---------------------------
"username"		{"zhangsan"}
"userpwd"		{"123"}
"interest"		{"s", "d"}

#一维数组的toString()方法的输出形式
String[] values = {"abc", "def", "xyz"};
//[Ljava.lang.String;@2f92e0f4
System.out.println(values); 
public class RequestTestServlet extends HttpServlet{
	public void doPost(HttpServletRequest request, HttpServletResponse response)
		throws IOException,ServletException{
		// 获取包含请求参数Map集合
		Map<String,String[]> parameterMap = request.getParameterMap();  
		// 通过Map集合的keySet方法获取Map集合中一个含有所有key的Set集合
		Set<String> keys = parameterMap.keySet();
        // 遍历集合中的key,获取其对应的一维数组value,如username=[Ljava.lang.String;@7cce40b4
		Iterator<String> it = keys.iterator();
		while(it.hasNext()){
			String key = it.next();
			String[] values = parameterMap.get(key);
            System.out.println(key + "=" + values);
			
			// 遍历获取到的一维数组的元素
			System.out.print(key + "=");
			for(String value : values){
				System.out.print(value + ",");
			}
			// 换行
			System.out.println();
		}

		// 通过request的getParameterNames方法获取这个Map集合的所有key
		Enumeration<String> names = request.getParameterNames();
		while(names.hasMoreElements()){
			String name = names.nextElement();
			System.out.println(name);
            String[] values = request.getParameterValues(name);
            // 遍历获取到的一维数组的元素
			for(String value : values){
				System.out.print(value + ",");
			}
			System.out.println();   
		}

		// 直接通过name获取value这个一维数组
		String[] usernames = request.getParameterValues("username");
		String[] userpwds = request.getParameterValues("userpwd");
		String[] interests = request.getParameterValues("interest");
		// 遍历一维数组的元素
		for(String username : usernames){
			System.out.println(username);
		}
		for(String userpwd : userpwds){
			System.out.println(userpwd);
		}
		for(String interest : interests){
			System.out.println(interest);
		}

		// 通过name获取value这个一维数组的第一个元素,因为这个一维数组中一般只有一个元素
		String username = request.getParameter("username");
		String userpwd = request.getParameter("userpwd");
        // 获取的都是一维数组当中的第一个元素
		System.out.println(username);
		System.out.println(userpwd);
		
        // 表单interest是个复选框有多个元素,需要获取整个数组
		String[] interests = request.getParameterValues("interest");
        // 遍历interests数组
		for(String interest : interests2){
			System.out.println(interest);
		}
	}
}

存储数据和转发的方法

request对象也叫“请求域”对象 , “请求域”对象要比“应用域”对象范围小很多

  • 只有用户发送请求的时候才会创建请求对象开启请求域 ,一个请求对象request对应一个请求域对象
  • 请求域的生命周期只在一次请求内有效, 一次请求结束之后请求域就销毁了
  • 请求域和应用域的选用原则: 尽量使用小的域对象,因为小的域对象占用的资源较少
方法名功能
void setAttribute(String name, Object obj)向请求域当中绑定数据
Object getAttribute(String name)根据name从请求域当中获取数据
void removeAttribute(String name)将请求域当中绑定的数据移除

在BSevlet中拿不到AServelt中向请求域中存储的数据 ,因为这两个Servlet对应不同的请求即不同的请求域

  • 在AServlet当中new一个BServlet对象,然后调用BServlet对象的doGet方法并把request对象传过去也可以实现功能但不符合规范
  • 每一个Servlet对象的创建不能自己由程序员来决定, 因为自己new的Servlet对象生命周期不受Tomcat服务器的管理
// AServelt中向请求域中存储数据
public class AServlet extends HttpServlet{
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException{
		// 获取系统当前时间
		Date nowTime = new Date();
		// 向request请求域当中绑定数据
		request.setAttribute("sysTime", nowTime);
        // 在AServlet当中new一个BServlet对象,然后调用BServlet对象的doGet方法并把request对象传过去也可以实现功能但不符合规范
        // 每一个Servlet对象的创建不能自己由程序员来决定, 因为自己new的Servlet对象生命周期不受Tomcat服务器的管理
- 
	}
}

// BSevlet中取出AServelt中向请求域中绑定的数据 
public class BServlet extends HttpServlet{
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException{
		// 无法从request域当中取出绑定的数据
		Object obj = request.getAttribute("sysTime");
		// 输出到浏览器
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.print("request域当中获取的系统当前时间 = " + obj);
	}
}

跳转方法(Servlet共享数据)

两个或者多个Servlet共享同一份数据的方式

  • 第一种: 将数据放到ServletContext应用域当中,这种方式由于应用域范围太大占用资源太多不建议使用
  • 第二种请求转发机制(一次请求): 将数据放到request域当中,然后在AServlet中转发到BServlet保证AServlet和BServlet在同一次请求当中

请求转发的时候路径要以“/”开始且不加项目名, 转发的对象可以是静态的html或动态的Servlet,只要是Tomcat服务器当中的合法资源都可以转发

方法名功能
RequestDispatcher getRequestDispatcher(String path)获取请求转发器对象

把AServlet和BServlet放到一次请求当中, 即执行了AServlet之后立马跳转到BServlet保证两个Servlet在同一次请求当中

  • 先获取请求转发器对象(包含下一个要跳转资源的路径), 然后调用请求转发器RequestDispatcher的forward方法进行转发(携带request和response参数)
// AServelt向请求域中存储数据并转发到BSevlet
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取系统当前时间
        Date nowTime = new Date();
        // 将系统当前时间绑定到请求域当中
        request.setAttribute("sysTime", nowTime);
        // 第一步:先获取请求转发器对象,把"/b"这个路径包装到请求转发器当中,实际上是把下一个跳转的资源的路径告知给Tomcat服务器
        //RequestDispatcher dispatcher = request.getRequestDispatcher("/b");
        // 第二步:调用请求转发器RequestDispatcher的forward方法进行转发,转发的时候request和response都是要传递给下一个资源的
        //dispatcher.forward(request, response);

        // 转发到一个Servlet
        request.getRequestDispatcher("/b").forward(request, response);
        // 转发到一个HTML
        // request.getRequestDispatcher("/test.html").forward(request, response);
    }
}

// BSevlet中取出AServelt中向请求域中绑定的数据 
public class BServlet extends HttpServlet{
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException{
		// 可以从request域当中取出绑定的数据
		Object obj = request.getAttribute("sysTime");
		// 输出到浏览器
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.print("request域当中获取的系统当前时间 = " + obj);
	}
}

获取请求参数和处理乱码方法

解决请求体(POST请求才有)含有中文时后端服务器接收数据时乱码问题: 通过request对象设置请求体的字符集request.setCharacterEncoding(“UTF-8”)

  • 对于Tomcat9及其之前版本,浏览器发起POST请求时服务器接收中文时会出现乱码问题
  • 对于Tomcat10及其之后版本, request请求体当中数据的字符集默认就是UTF-8,浏览器发起POST请求和GET请求都不会出现乱码问题

解决发起GET请求时请求行含有中文乱码问题: 需要修改CATALINA_HOME/conf/server.xml配置文件,在Connector标签写一个URIEncoding属性指定URI的字符集

  • 对于Tomcat9和8版本, 不写URIEncoding属性指定URI的字符集时默认按照UTF-8字符集处理数据,所以发起GET请求时服务器接收中文不会出现乱码问题
  • Tomcat8之前的版本发起GET请求时请求行含有中文会出现乱码问题,需要在Connector标签写一个URIEncoding属性指定URI的字符集
<Connector URIEncoding="UTF-8" port="8080" />

解决响应体含有中文时浏览器接收数据时乱码问题: 通过response对象设置响应体的字符集response.setContentType(“text/html;charset=UTF-8”)

  • 对于Tomcat9及其之前版本,当浏览器发起POST请求和GET请求时服务器响应的数据含有中文时都会出现乱码问题

  • 对于Tomcat10及其之后版本, 当浏览器发起POST请求和GET请求时服务器响应的数据含有中文时都不会出现乱码问题

方法名功能
String getRemoteAddr();获取客户端的IP地址
void setCharacterEncoding(String)设置请求体的字符集 , 处理POST请求的乱码问题
String getContextPath()获取应用的根路径(底层还是调用ServletContext对象的方法)
String getMethod()获取请求方式
String getRequestURI()获取请求的URI (带项目名)
String getServletPath()获取Servlet 的路径 (项目名后面的路径)
public class TestServlet extends HttpServlet{
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException{
        // 获取客户端的IP地址
        String remoteAddr = request.getRemoteAddr();
        // 处理POST请求的乱码问题: 设置请求体的字符集
        request.setCharacterEncoding("UTF-8");
        // 解决Tomcat9及其之前版本响应乱码问题
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
		out.print("你好Servlet");
        // 获取应用的根路径
        String contextPath = request.getContextPath();
        // 获取请求方式
        String method = request.getMethod();
        // 获取请求的URI,/aaa/testRequest(aaa是项目名)
        String uri = request.getRequestURI();  
        // 获取Servlet路径,/testRequest(不带项目名)
        String servletPath = request.getServletPath(); 
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值