JavaWeb之详解Servlet(五)

HttpServletRequest

         在Http协议中,有这样两部分,请求与响应,今天介绍请求对象
         当我们继承HttpServlet后,需对service(HttpServletRequest req, HttpServletResponse resp)进行重写,那么req和resp是什么时候进行创建的呢?
         Web服务器收到一个Http请求后,会针对每个请求创建一个HttpServletRequest对象和HttpServletResponse对象。若需要获取客户端提交的相关信息,则需要从HttpServletRequest对象中获取;若需要向客户端发送数据,则需要通过HttpServletResponse对象来完成。

HttpServletRequest

         1、请求的生命周期

         当客户端浏览器将请求(字符序列)发送到服务器后,服务器会根据HTTP请求协议的格式对请求进行解析。同时,服务器会创建HttpServletRequest的实现类RequestFacade的对象,即请求对象。然后在调用相应的set方法,将解析出的数据封装到请求对象中。此时HttpServletRequest实例就创建并初始化完毕了。也就是说,请求对象是由服务器创建。
         当服务器向客户端发送响应结束后,HttpServletRequest实例对象被服务器销毁。
         一次请求对应一个请求对象,另外一个请求对应另外一个请求对象,与之前的请求对象没有任何关系。HttpServletRequset实例的生命周期很短暂。

         2.请求参数:

         HttpServletRequest对于请求中所携带的参数是以Map的形式接受的,并且该Map的key为String,value为String数组。注意value为String数组。
         因为Http请求协议运行一个请求参数具有多个值,例如复选框。
在这里插入图片描述
         html的代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="registerServlet" method="post">
		姓名:<input type="text" name="name"><br/>
		年龄:<input type="text" name="age"><br/>
		爱好:<input type="checkbox" name="hobby" value="playing">玩游戏
			  <input type="checkbox" name="hobby" value="swiming">游泳
			  <input type="checkbox" name="hobby" value="reading">看书<br/>
		<input type="submit" value="注册">
	</form>
</body>
</html>

        &nbsp例如存在上面这样一个表单,我们要获取客户端浏览器的请求数据,方法如下:

protected void service(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
		
		//接受指定参数名称的请求参数值
		//本质上getParameter("name"),等同于getParameterValues("name")[0]
		String name = request.getParameter("name");
		int age = Integer.parseInt(request.getParameter("age"));
		System.out.println("name = " + name);
		System.out.println("age = " + age);
		System.out.println("-----------------");
		//获取所有的请求参数名称
		Enumeration<String> names = request.getParameterNames();
		//遍历枚举
		while(names.hasMoreElements()){
			System.out.println(names.nextElement());
		}
		System.out.println("-----------------");
		//获取指定参数的所有值
		String[] hobbys = request.getParameterValues("hobby");
		for(String hobby : hobbys){
			System.out.println(hobby);
		}
		System.out.println("-----------------");
		//获取存放请求的参数Map
		Map<String, String[]> map = request.getParameterMap();
		for(Entry<String, String[]> entry : map.entrySet()){
			//获取参数名
			String key = entry.getKey();
			//获取参数值
			String[] values = entry.getValue();
			for(String value : values){
			System.out.println(key + "..." + value);
			}
		}
	}

         控制台输出如下:
在这里插入图片描述

         HttpServletRequest请求常用方法:

         getParameter(String str)         str为HTML文件中的标签的name属性值
         getParameterNames()            获得请求中的所有参数值
         getParameterValues(String str)         获去该属性的所有值,例如复选框
         getParameterMap()            获取请求中所有的参数和值的映射关系,key为String,value为String[]

         3.域属性

         在Request中也存在域属性空间,用于存放有名称的数据。该数据只在当前Request请求中可以进行访问。

         常用方法:

         getAttribute(String name)                获取该属性的值
         getAttributeNames()                         获取所有的属性名
         setAttribute(String key,Object)         在请求中放入属性
         removeAttribute(String name)         删除请求中的属性

         我们知道,一次请求对应一次响应。当请求没有被销毁时,我们边可以从请求中获取数据。例如存在如下两个Servlet,SomeServelt和OtherServlet。

         SomeServlet代码如下:

public class SomeServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//向请求中放入属性
		request.setAttribute("name", "wangzhao");
		request.setAttribute("age", "120");
		
		//从请求中删除指定域属性
		request.removeAttribute("age");
		
		// 将请求转发给otherServlet, 说明请求没有被销毁
		request.getRequestDispatcher("/otherServlet").forward(request, response);
		
	}
}

         OtherServlet代码如下:

public class OtherServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		    //从请求中获取指定名称的域属性
			String name = (String)request.getAttribute("name");
			String age = (String)request.getAttribute("age");
			
			System.out.println(name);
			System.out.println(age);
			
			
			//从请求中获取请求中的所有域属性名称
			Enumeration<String> names = request.getAttributeNames();
			while(names.hasMoreElements()){
				String element = names.nextElement();
				System.out.println(element +" = " + request.getAttribute(element));
			}
	}

}

         控制台输出如下:
在这里插入图片描述

如何理解上面这一句代码:request.getRequestDispatcher("/otherServlet").forward(request, response);

在之前的示例中,我们只有一个Servlet,所以一个请求只在一个Servlet中有效。但请求转发,让这个请求不再当前Servlet中销毁,发送到其他Servlet中。**例如:你去旅游,原本打算到西安玩完回家。但你又想去成都玩,所以你又去了成都,然后回家。**这就是请求转发,这有什么用?我们是不是通过请求转发实现了不同Servlet之间的通信?当然通信并不只有这一种方法。

         4.服务端相关信息
在这里插入图片描述

         中文乱码问题:
继续以上一个表单为例:我们提交如下信息:

在这里插入图片描述

         控制台输出:
在这里插入图片描述
         可以看出name出现了乱码。为什么出现乱码?原因如下:

         原因:一旦有浏览器经过Http协议传输,则这些数据均将以字节的形式上传给服务器。因为HTTP协议的底层使用的是TCP传输协议。TCP,是一种面向连接的、可靠的、基于字节流的、端对端的通信协议。在请求中,这些字节均以%开头,并以16进制形式出现。如%5A%3D等。

         当用户通过浏览器提交一个UTF-8编码格式的两个字的中文请求时,浏览器会将这两个中文字符变为六个字节(一般一个UTF-8汉字占用三个字节),即形成六个类似%8E的字节表示形式,并将这六个字节上传至Tomcat服务器。

         Tomcat服务器在接收到这六个字节后,并不知道他们原始采用的是什么字符编码。而Tomcat默认的编码格式为ISO-8859-1。所以会将这六个字节按照ISO-8859-1的格式进行编码,编码后再控制台显示,所以再控制台会显示乱码。

         解决方案:
         1、Tomcat9的get提交已经解决了中文乱码问题。
         2、Post提交方式,在Service方法添加如下一行代码。(注意,先添加后然后再获取数据,该代码对get提交方式无用)
在这里插入图片描述
         3、解决其他版本的GET提交:
         1.在Tomcat服务器的server.xml中添加 URIEncoding=”UTF-8”(不推荐使用,需重启服务器)
在这里插入图片描述

          2.万能解决方案(但需要每对一组数据进行操作)
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值