`
ilovejsj
  • 浏览: 205565 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

对request的理解

阅读更多
对request的理解

(1)
页面一(base.jsp)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
  <head>
    <base href="<%=basePath%>">
    <title>base.jsp</title>
  </head>
  <body>
    <form action="basetest/request.jsp">
    <%
     request.setAttribute("key","request");
    %>
    <input type="text" name="helloTest" value="helloTest">
    <br><input type="submit" value="提交">
   </form>
  </body>
</html>
页面二(request.jsp)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
  <head>
    <base href="<%=basePath%>">
    <title>request.jsp</title>
  </head>
  <body>
    <%
     out.println(request.getAttribute("key"));
     Enumeration enumer=request.getAttributeNames();
     while(enumer.hasMoreElements())
     {
      out.println(enumer.nextElement());
     }
    %>
  </body>
</html>
页面一在request中用setAttribute放入一对象,在页面二中取不到打印结果为null
原因就在于request对象的创建过程,request和response对象是web容器中接收到一个对servlet(jsp的本质就是一个servlet)的请求时创建的,request中封装了用户的http请求信息,然后容器把这两个对象传递给servlet。
也就是说第一个页面中的request和第二个页面中的request是完全没有任何关系的由容器创建的两个request,页面间传递对象(不经过其它页面或servlet)还是用session,application吧。

(2)
request的作用范围是,用户请求的当前Web组件以及与当前Web共享同一个用户请求的其它web组件。
首先先来比较一下@include和jsp:includer的区别
我现在有三个文件request.jsp,includeTest.html,includeTest.jsp要包含其它两个页面,关键代码如下(页面body标签间的内容)
request.jsp
<fieldset>
   <legend>myself</legend>
  
   String tempstr="hello world";<br>
   <%String tempstr="hello world"; %><br>
  
   out.println(tempstr);<br>
   <%out.println(tempstr); %><br>
   Enumeration<br>
   <%
     Enumeration enumer=request.getAttributeNames();
     while(enumer.hasMoreElements())
     {
      out.println(enumer.nextElement());
      out.print("<br>");
     }
    %><br>
    pageContext.setAttribute("key","page(request.jsp)");<br>
   <%pageContext.setAttribute("key","page(request.jsp)");%><br>
    request.setAttribute("key","request(request.jsp)");<br>
   <%request.setAttribute("key","request(request.jsp)");%><br>
  </fieldset>
  <fieldset>
   <legend>includeTest.html(@include)</legend>
   <%@include file="includeTest.html"%>
  </fieldset>
  <fieldset>
   <legend>includeTest.html(jsp:include)</legend>
   <jsp:include page="includeTest.html"></jsp:include>
  </fieldset>
  <fieldset>
   <legend>includeTest.jsp(@include)</legend>
   <%@include file="includeTest.jsp"%>
  </fieldset>
  <fieldset>
   <legend>includeTest.jsp(jsp:include)</legend>
//先注释掉
   <%//<jsp:include page="includeTest.jsp"></jsp:include> %>  
  </fieldset>
includeTest.html
out.println(pageContext.getAttribute("key"));<br>
   <%out.println(pageContext.getAttribute("key")); %><br>
  
   out.println(request.getAttribute("key"));<br>
   <%out.println(request.getAttribute("key")); %><br>
  
    out.println(session.getAttribute("key"));<br>
   <%out.println(session.getAttribute("key")); %><br>
  
   out.println(application.getAttribute("key"));<br>
   <%out.println(application.getAttribute("key")); %><br>
  
    out.println(tempstr);<br>
   <%out.println(tempstr); %><br>
   Enumeration<br>
   <%
     enumer=request.getAttributeNames();
     while(enumer.hasMoreElements())
     {
      out.println(enumer.nextElement());
      out.print("<br>");
     }
    %><br>
includeTest.jsp页面的内容和includeTest.html的一摸一样

结果
myselfString tempstr="hello world";

out.println(tempstr);
hello world
Enumeration

pageContext.setAttribute("key","page(request.jsp)");

request.setAttribute("key","request(request.jsp)");

includeTest.html(@include)
out.println(pageContext.getAttribute("key"));
page(request.jsp)
out.println(request.getAttribute("key"));
request(request.jsp)
out.println(tempstr);
hello world
Enumeration
key

includeTest.html(jsp:include)
out.println(pageContext.getAttribute("key"));

out.println(request.getAttribute("key"));

out.println(tempstr);

Enumeration


includeTest.jsp(@include)
out.println(pageContext.getAttribute("key"));
page(request.jsp)
out.println(request.getAttribute("key"));
request(request.jsp)
out.println(tempstr);
hello world
Enumeration
key

includeTest2.jsp(jsp:include)
//注释掉了,空

先说@include
你如果和我一起创建的话你会发现includeTest.jsp页面已经报错说是tempstr,enumer变量未定义,现在先不用着急,咱们先发布到服务器上看看。
如果你访问这个request.jsp页面的时候你会发现一切正常没有报错。原因就在于jsp页面编译的时候遇到@include就直接把所要包含的页面的所有内容拿过来与当前页面融合为一个整体再去一起编译,无论他是要包含一个jsp页面还是一个html页面,所以html页面中的java代码也能照样解析。在包含的页面中主页面中的变量都可以访问到,当然你也可以在includeTest.html或includeTest.jsp中定义变量在request.jsp或includeTest.html或includeTest.jsp调用访问不过要定义好包含顺序(同理在这三个页面中不能变量重名,一个页面有个变量名a在其它页面中就不能有变量名为a,否则编译出错)。
怎么来证明上面这段话的正确性呢?
(1)@include进来的includeTest.jsp或includeTest.html页面都打印出了在request.jsp中放入到pageContext和request中的值。由pageContext的作用范围可以证明。
(2)查看tomcat work目录下有没有生成includeTest.java文件,你会发现没有(jsp:include就会生成)
(3)查看生成的servlet源代码。tomcat work目录下查看request.java你会发现里面包含着其他包含页面的源代码。这个证明更充分。

再说jsp:include
把上面request.jsp中的注释去掉直接访问的话你会发现报错:tempstr(enumer) cannot be resolved(变量无法解析)这就是jsp:include与@include的区别,它是先编译要包含的页面然后把编译后的在整体包过来,两个页面是独立编译的,所以变量就不能互访。两个页面是独立的你可以定义相同的变量名,但是被包含页面中你照样可以主页面中request中存储的对象。
includeTest2.jsp(jsp:include)
out.println(pageContext.getAttribute("key"));
null
out.println(request.getAttribute("key"));
request(request.jsp)

Enumeration
javax.servlet.include.request_uri
javax.servlet.include.context_path
javax.servlet.include.servlet_path
key

如何证明呢?
(1)pageContext的值没有打印出来为null。
(2)查看includeTest.html(jsp:include)显示的结果。你可以看到直接打印出的都是页面信息,如果你点击右键查看源代码你会发现java代码片段并没有解析还是源代码的形式,这是由于它是jsp:include是让包含的文件独立去解析,html后缀的为静态页面容器不会去编译直接包进来所以原来代码什么样包进来就是什么样。(你可能会问<%out.println(request.getAttribute("key")); %>这些内容为什么在页面上没有显示出来,"<"相当于html中的关键字表示标签的开始,html解析器无法解析这个标签所以这段代码就不能像普通文本那样显示出来了)。
(3)查看tomcat work目录下有没有生成includeTest.java文件,你会发现生成了
(4)查看生成的servlet源代码,request_jsp.java。找到解析jsp:include的那部分代码如下
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "includeTest.jsp", out, false);
JspRuntimeLibrary类位于tomcat Lib目录下的jasper.jar中,反编译include部分的源代码如下
  public static void include(ServletRequest request, ServletResponse response, String relativePath, JspWriter out, boolean flush)
    throws IOException, ServletException
  {
    if ((flush) && (!(out instanceof BodyContent))) {
      out.flush();
    }

    String resourcePath = getContextRelativePath(request, relativePath);
    RequestDispatcher rd = request.getRequestDispatcher(resourcePath);

    rd.include(request, new ServletResponseWrapperInclude(response, out));
  }
很明显的看到是一个转发,这也就是为什么request.jsp中放入request中对象在被包含的页面中还可以访问的真正原因。

现在咱们回到对开头第一句话的理解
“request的作用范围是,用户请求的当前Web组件以及与当前Web共享同一个用户请求的其它web组件。”
在这个例子中“其它的web组件”就是指@include和jsp:include包含进来的其它页面。
其实还有一个,那就是jsp:forward所指向的页面。
forward.jsp
out.println(pageContext.getAttribute("key"));<br>
   <%out.println(pageContext.getAttribute("key")); %><br>
  
   out.println(request.getAttribute("key"));<br>
   <%out.println(request.getAttribute("key")); %><br>
  
   String tempstr="hello world forward";<br>
   <%String tempstr="hello world forward"; %><br>
  
   out.println(tempstr);<br>
   <%out.println(tempstr); %><br>
  
   Enumeration<br>
   <%
    Enumeration enumer=request.getAttributeNames();
     while(enumer.hasMoreElements())
     {
      out.println(enumer.nextElement());
      out.print("<br>");
     }
    %><br>
结果
out.println(pageContext.getAttribute("key"));
null
out.println(request.getAttribute("key"));
request(request.jsp)
String tempstr="hello world forward";

out.println(tempstr);
hello world forward
Enumeration
javax.servlet.forward.request_uri
javax.servlet.forward.context_path
javax.servlet.forward.servlet_path
key
直接查看生成的servlet源代码,选取关键代码
import javax.servlet.jsp.JspFactory;
private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();
PageContext pageContext  = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
PageContext _jspx_page_context = null;
_jspx_page_context = pageContext;
if (true) {
        _jspx_page_context.forward("forward.jsp");
        return;
}
由此可见其实还是一个转发,所以仍然可以获取request中的对象。
分享到:
评论
3 楼 steafler 2010-08-10  
学习了,细微的差别啊
2 楼 dwbin 2010-08-10  
J-catTeam 写道
上下文 

楼上正解,我一直以来也吧request当成线程变量来理解的。页面跳转的同时服务器启动的已经不再是同一个线程了。
同时一个servelt和他所转向的jsp都属于一个线程之内的。
对于include的理解就是<%%>之内的就是java语句,所以属于和jsp一同编译即先合过来再编译,而<jsp:include>属于标签,该部分是通过标签类来包含的,该过程没有包含编译,所以只能是包含编译后的文件。
1 楼 J-catTeam 2010-08-10  
上下文 

相关推荐

    Request、Request.Form和Request.QueryString的区别

    理解它们之间的区别,并根据实际需求选择合适的使用方式,是提升Web应用性能和用户体验的关键。在处理大量数据时,应优先考虑使用`Request.Form`;而在处理简单查询参数时,`Request.QueryString` 更为合适;而对于...

    C# request获取参数.docx

    C# Request 获取参数详解 在 C# 中,获取请求参数是 Web 开发中一个非常重要的步骤。Request 对象提供了多种方式来获取请求参数,本文...同时,了解 Request 对象的工作机制也可以帮助我们更好地理解 Web 开发的原理。

    PHP生成唯一RequestID类

    在IT行业中,尤其是在分布式系统开发中,跟踪请求的唯一标识符(Request ID)是非常重要的。...通过阅读和理解提供的代码,开发者可以轻松地将这种机制融入自己的项目中,实现高效的问题定位和故障排查。

    c#Request关于Url分析

    在Web开发中,对URL进行解析和操作是非常常见的需求之一。在C#中,可以通过`.NET`框架提供的多种方法来处理URL。本文将详细介绍如何使用`HttpRequest`对象来分析和获取URL的相关信息。 #### 1. `Request.Url`与`...

    request-hook.zip

    总的来说,Request-Hook是Chrome DevTools的一个强大补充,它增强了开发者对网络请求的控制和理解。通过提供对关键参数的定位、JS文件的本地替换以及对cookies和headers的深度分析,Request-Hook大大简化了复杂的...

    PHP - HTTP_Request2实现短信验证码注册登录完整示例:PHP -HTTP_Request2.php和附件说明.rar

    这个示例中的“PHP - HTTP_Request2.php”文件应包含上述代码逻辑,而“文档说明”可能包含了详细的使用指南和API接口文档,帮助开发者理解如何配置HTTP_Request2实例,以及如何与短信服务商的API进行交互。...

    HTTP Request Editor.zip

    HTTP Request Editor是一款强大的工具,专为开发者和网络爱好者设计,用于HTTP抓包和编辑。它允许用户捕获、查看并修改HTTP请求,这...通过熟练掌握和使用这款工具,可以显著提高工作效率,并加深对Web通信机制的理解。

    request、session作用域的理解

    Request、Session 作用域的理解 Request 作用域: * Request 作用域是指在当前请求中有效的信息共享范围 * 在 Servlet/JSP 中,Request 作用域是通过 HttpServletRequest 接口实现的 * Request 作用域的信息共享是...

    session,request区别

    在Web开发中,理解`session`和`request`这两个概念是非常重要的。它们都是用来处理用户会话管理和数据传输的关键组件。本文将深入探讨这两者之间的区别,帮助开发者更好地理解和运用这些机制。 #### Session的概念...

    get、post、request的区别

    总的来说,理解GET、POST和REQUEST的差异,并在编程中采取适当的验证措施,是确保代码安全性和可靠性的重要步骤。在进行代码审核时,关注这些细节可以有效降低潜在的安全风险,提高应用的健壮性。

    Jmeter Java Request Demo

    这可以帮助你理解和调试Java Request中关于TCP通信的部分。 综上所述,JMeter的Java Request功能强大且灵活,不仅可以处理常见的HTTP请求,还能应对TCP这样的底层网络通信,甚至是与复杂的分布式消息系统如RocketMQ...

    Jsp的request的用法

    在本篇文章中,我们将深入探讨`request.getParameter()`和`request.setAttribute()`以及`request.getAttribute()`的区别,并提供相关示例来帮助理解它们的用法。 **一、request.getParameter() 和 request....

    koa源码-request模块

    《Koa源码解析——Request模块深度探讨》 在Node.js的世界中,Koa作为一款现代化的Web框架,以其简洁的API和中间件机制深受开发者...在实际开发中,结合源码阅读和实践,将使我们对Koa的理解更加深入,提升开发技能。

    实例详解JSP内置对象--request对象

    实例详解JSP内置对象--request对象 request对象是JSP中的内置对象之一,它提供了访问HTTP请求信息的功能。...通过本文的实例解析,我们可以更好地理解request对象的使用和掌握,并将其应用于实际开发中。

    AJAXRequest 开发者手册

    通过深入学习AJAXRequest开发者手册,开发者可以更好地理解和应用AJAX技术,提高网页交互性和用户体验。手册中的详细示例和解释将有助于解决实际开发中遇到的问题。同时,了解和掌握AJAXRequest库的使用,也能为项目...

    TP5 Request 请求对象

    在PHP开发领域,尤其是基于Laravel或ThinkPHP框架的应用中,`Request`对象是一个至关重要的概念。本篇文章将深入探讨ThinkPHP5(简称...在实际项目中,结合源码阅读和实践操作,将有助于进一步理解和运用这一重要概念。

    ASP.NET Core自定义中间件如何读取Request.Body与Response.Body的内容详解

    通过正确地备份、读取和恢复`Request.Body`和`Response.Body`,我们可以在自定义中间件中实现对请求和响应数据的全面监控。这在开发日志记录、安全审计或其他需要拦截请求和响应数据的场景中特别有用。理解这些核心...

    request域对象的实例代码

    Request对象,全称为...通过对Request对象的深入理解和熟练运用,开发者可以更高效地构建Java Web应用程序。在实际项目中,经常需要结合Response、Session和其他域对象一起使用,以实现更复杂的业务逻辑。

    Request_ServerVariables参数详解

    - **性能优化**:了解客户端请求的具体内容,以便对服务进行针对性优化。 - **功能开发**:例如根据请求头中的语言偏好设置页面语言。 - **调试工具**:在开发过程中,利用这些信息快速定位问题所在。 总之,`...

    Request Maker测试工具

    在Web开发过程中,理解并掌握如何利用这样的工具进行API接口测试至关重要。Request Maker通过提供一个直观的界面,使得用户可以方便地构造GET、POST、PUT、DELETE等不同类型的HTTP请求,并查看服务器的响应数据,...

Global site tag (gtag.js) - Google Analytics