JavaWeb之详解Servlet(五) 野性酷女 2021-09-17 10:22 325阅读 0赞 # 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请求协议运行一个请求参数具有多个值,例如复选框。 ![在这里插入图片描述][20181226194744926.png] 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>  例如存在上面这样一个表单,我们要获取客户端浏览器的请求数据,方法如下: 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); } } } 控制台输出如下: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70] **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)); } } } 控制台输出如下: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70 1] 如何理解上面这一句代码:**request.getRequestDispatcher("/otherServlet").forward(request, response);** 在之前的示例中,我们只有一个Servlet,所以一个请求只在一个Servlet中有效。但请求转发,让这个请求不再当前Servlet中销毁,发送到其他Servlet中。\*\*例如:你去旅游,原本打算到西安玩完回家。但你又想去成都玩,所以你又去了成都,然后回家。\*\*这就是请求转发,这有什么用?我们是不是通过请求转发实现了不同Servlet之间的通信?当然通信并不只有这一种方法。 **4.服务端相关信息** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70 2] ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70 3][] **中文乱码问题:** 继续以上一个表单为例:我们提交如下信息: ![在这里插入图片描述][20181226204059554.png] 控制台输出: ![在这里插入图片描述][2018122620412946.png] 可以看出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提交方式无用) ![在这里插入图片描述][20181226204534692.png] 3、解决其他版本的GET提交: 1.在Tomcat服务器的server.xml中添加 URIEncoding=”UTF-8”(不推荐使用,需重启服务器) ![在这里插入图片描述][20181226204838675.png] 2.万能解决方案(但需要每对一组数据进行操作) ![在这里插入图片描述][20181226204945611.png] [20181226194744926.png]: /images/20210812/3a589e16a24041de81219bc83b01fd7f.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70]: /images/20210812/3e11576da1644fe4b027cd1f061622e6.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70 1]: /images/20210812/6bbf9ca07f994289af00743c3312496d.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70 2]: /images/20210812/d4b53104fb834367aa6617dcbe1413fd.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfemhhb18_size_16_color_FFFFFF_t_70 3]: /images/20210812/fe8fd9e98e2c4961b73f7467d37857b8.png [20181226204059554.png]: /images/20210812/cb0eaa6084e04acb99fe8193a01dc83d.png [2018122620412946.png]: /images/20210812/d98afcde29e4457a9243f3a020f75401.png [20181226204534692.png]: /images/20210812/b4766b37a5fb4bcbb9075770e2107105.png [20181226204838675.png]: /images/20210812/82b9dcf0f74948ca93c106499768dfa9.png [20181226204945611.png]: /images/20210812/403c71536dcd401984887dbe79e5a940.png
还没有评论,来说两句吧...