JSP 中的 request 内置对象

request 对象是 HttpServletRequestWrapper 类的实例。它的继承体系如下:

_request 对象继承层次结构图.png

ServletRequest 接口的唯一子接口是 HttpServletRequest ,HttpServletRequest 接口的唯一实现类 HttpServletRequestWrapper ,单从 request 对象一脉单传的类继承体系可以看出,javaweb 标准类库只支持了 http 协议。 Servlet/JSP 中大量使用了接口而不是实现类,这恰恰就是面向接口编程的最佳应用啊。

request 内置对象是由 Tomcat 创建的,可以用来封装 HTTP 请求参数信息、进行属性值的传递以及完成服务端跳转,这就是 request 对象最重要的三个功能了。

request 对象的创建流程

一旦 http 请求报文发送到 Tomcat 中, Tomcat 对数据进行解析,就会立即创建 request 对象,并对参数赋值,然后将其传递给对应的 jsp/servlet 。一旦请求结束,request 对象就会立即被销毁。服务端跳转,因为仍然是同一次请求,所以这些页面会共享一个 request 对象。

通过 request 获取请求参数

request 对象的内存模型可以简单的划分为参数区和属性区。参数区存放的是 Tomcat 解析 http 请求报文后提取出来的请求参数名和参数值。手动想象它在内存中的对象模型,想象下那个图,就理解了它的数据数据结构了,就更能够理解方法内部到底干了什么。堆区对象内的一个个变量指向这个对象外部的一个个字符串对象,如果是多值参数,对应的就是一个个字符串数组对象。

_request对象内存图.png

对于单值参数,只有String getParameter(String name)方法,得到对应的字符串对象的地址引用,而没有对应的 setxxx()方法,因为参数只能由 Tomcat 从 http 报文中收集而来的。如果浏览器没有输入 value 值,得到的字符串对象自然就是 null ,并不是老师说的返回值是一个 "" 空字符串,这可以自己写代码验证啊

对于多值参数,比如表单中的复选框,因为可以选择多个参数,所以同一个参数名会对应多个参数值,那么 request 对象如何去获取呢?通过String[] getParameterValues(String name)方法可以得到这个多值参数的数组对象地址引用。对于复选框的内容,因为它是一个数组对象,所以如果浏览器没有输入值,那么 request 拿到的是一个 null 的数组对象,这时候就很可能会产生空指针异常。通常这种前端页面的工作应该放在浏览器端,通过 javaScript 来处理,而不应该交给服务端处理。

因为 rqeust 本质上也是 Map 结构,所以也可以得到一个 key 值的 Enumeration 迭代器对象(再次强调,这是一个集合对象的内部类对象),这和 Map 的数据结构是一样的,你看知识点都是相通的。得到所有参数名迭代器对象的方法如下:Enumeration getParameterNames()。因为无论客户端浏览器如何改变,它的所有请求参数名和值始终都会被 Tomcat 收集后,存放到对应的 request 对象中,然后就可以通过这个 key 值的迭代器对象 Enumeration 依次拿到所有的 key 值,再拿到对应的 value 值。然后存放到对应的数据对象中,一路传递到 DAO 层,存到数据库中去。这是一种优秀的编程思想,收集表单中传送过来的所有参数,Struts 框架中就专门有做这件事情的一个模块。

还可以通过Map getParameterMap()方法得到所有参数名和参数值组成的 Map 对象,不负责任的猜想,Enumeration getParameterNames()方法内部就是调用了Map getParameterMap()方法得到一个 Map 对象,然后调用它的 Enumeration keys()方法就得到了 Enumeration 迭代器对象。

通过 request 获取和设置请求属性

属性区存放的是 JSP/Servlet 中使用setAttribute(String name,Object o)方法设定的属性名和属性值,然后可以通过Object getAttribute(String name)方法得到属性值对象,需要 Object 类型对象进行向下转型。设定属性的目的是为了利用 request 对象在不同 JSP/Servlet 中传递数据。

request 动态编码

利用 request 完成服务端跳转

JSP 中有一个 forward 动作,可以实现服务端跳转的功能,但是这属于 JSP 语法范畴,只能在 JSP 页面之间进行跳转。点击此处查看 forward 动作笔记,但是在实际 web 项目中通常需要在各种 JSP 页面和 Servlet 类中进行跳转,这时候 JSP 的 forward 动作就无法满足要求了,所以 request 对象提供了一种服务端跳转的方法,这个方法非常重要,以后所有的服务端跳转都是用这种方式。

首先通过 HttpServletRequest 接口提供的getRequestDispatcher(String path)方法返回一个 RequestDispatcher 对象,其中参数 path 是想要跳转的目标路径。Dispatcher 是一个名词,表示调度员的意思,所以 RequestDispatcher 是一个请求调度员对象,从名字可以看出它具有请求调度的能力。该对象提供了两个方法分别用来替代 JSP 的 forward 和 include 动作,方法如下:

  • forward(ServletRequest reqeust,ServletResponse response)
  • include(ServletRequest reqeust,ServletResponse response)

具体使用方式如下:

//服务端跳转
request.getRequestDispatcher("success.jsp").forward(request,response);
//包含页面
request.getRequestDispatcher("menu.html").include(request,response);

这里要补充一点的是,一旦执行到 RequestDispatcher 对象的 forward() 方法,就会立即进行服务端跳转,此方法后面的代码将不再被执行。

针对上面注释掉的一点,实际编程中发现并不是这样的。无论是 request 的请求转发还是 response 的请求重定向,它都并不是表面意义上的立即进行跳转。它后面的代码仍很有可能会执行,如果后面还有请求转发或者重定向的语句被执行,这就会带来java.lang.IllegalStateException: Cannot forward after response has been committed异常,至于底层为什么没有就此结束此方法,真的不理解,先记住这个特点吧。解决办法很简单,在跳转语句后面紧跟着 return 语句就此结束此方法,不让后面语句执行。

request 对象其他方法

String getRemoteAddr()得到客户端浏览器的 IP 地址,以字符串对象的形式返回。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容