Jsp(3):内置对象和四种域对象的理解

时间:2021-10-06 04:28:52

由来:在jsp开发中,会频繁使用到一些对象 。例如HttpSession,ServletContext,ServletContext,HttpServletRequet。所以Sun公司设计Jsp时,在jsp页面加载完毕之后就会自动帮开发者创建好这些对象,开发者只需要直接使用这些对象调用方法即可!这些创建好的对象就叫内置对象,一共有九个。

内置对象名 类型
request HttpServletRequest
 response  HttpServletResponse
config ServletConfig
application ServletContext
session Httpsession
exception Thrwable(错误处理页面)
page Object(this:当前jsp翻译的类如我们上次写到的hello.jsp翻译变成了hello_jsp.java中的生命周期方法)
out JspWriter
pageContext pageContext

我们可以随便打开一个以jsp翻译的java源文件

public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException { PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null; try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out; String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; }

  从上面可以看到内置对象都是在service方法中创建的,而指令和声明是成员变量和方法,故不能在指令和声明中使用内置对象


1、out对象

  是jspWriter类,相当于带缓存的PrintWriter。有点与PrintWriter方法相似

Jsp(3):内置对象和四种域对象的理解

如果我们在jsp页面执行以下代码会发现

<%
out.write("abc");
response.getWriter().write("2222223");
%>

因为out中添加了缓冲区的设置,所以在浏览器中先打印出后面的语句,前面的要等其缓冲区(默认大小是8kb)没有满,要等jsp页面执行完之后才打印,我们也可以去手动刷新页面

Jsp(3):内置对象和四种域对象的理解         Jsp(3):内置对象和四种域对象的理解

我们可以在jsp的指令部分去设置缓冲区大小

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" buffer="8kb"%>

我们继续做实验,在jsp页面运行如下的代码

<%
out.write("abc");
//查看缓冲区的大小
System.out.println("当前缓冲区的大小:"+out.getBufferSize());
System.out.println("当前缓冲区的剩余大小:"+out.getRemaining());
%>

看到的结果是这样的:

Jsp(3):内置对象和四种域对象的理解

我们在浏览端发送了只有“abc”这样3个字节,却是用了两百多个字节的大小,多余的部分去哪了呢?这个时候我们可以全看看out_jsp.java文件,

 out.write("\r\n");
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" <title>My JSP 'out.jsp' starting page</title>\r\n");
out.write(" </head>\r\n");
out.write(" <body>\r\n");
out.write(" \t"); out.write("abc");
//查看缓冲区的大小
System.out.println("当前缓冲区的大小:"+out.getBufferSize());
System.out.println("当前缓冲区的剩余大小:"+out.getRemaining()); out.write("\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");

其实我们会发现,我们向浏览发送字节远不止abc,其实还有一些标签等的内容,他们是要发送到浏览器端,也是占大小的。

我们再来做一个实验,如下代码,

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" buffer="1kb"%>
<%
System.out.println(out.getRemaining());
for(int i=1;i<=1024;i++)
out.write("a");
//查看缓冲区的大小
response.getWriter().write("郭庆兴");
%>

看到这个时候的效果:

Jsp(3):内置对象和四种域对象的理解

不知道为什么我这里出现了一开始的缓冲区大小是1022(我设置了应该是1kb buffer="1kb"),但是这不是我的重点,重点是他这个图说明了缓冲区的运行机制,如果缓冲区满了,就立即将其打印出来,没有满,就等待页面执行完才打印,就像第一次1022缓冲区满了之后去打印,然后又重新往里放两个a,此时缓冲区没有满,就必须等待jsp页面加载完后执行,所以出现在“郭庆兴”的后面出现。

(我发现不知道哪里用了两个字节使得一开始的缓冲区大小只有1022B,我有试了buffer="2kb"和buffer="3kb",发现其剩余大小都正常)

Jsp(3):内置对象和四种域对象的理解

2、exception 对象

该对象表示其他页面所抛出的异常对象(Throwable对象)

我们打开jsp翻译后的java源文件发现,在该文件的service方法中居然里面八大内置对象都存在,就唯独没有该对象,这是因为我们没有指定其为错误处理页面,只有指定当前页面为错误错里页面后才可以去使用它。

3、pageContext对象

jsp的上下文对象,为了我们更方便的去使用其他八个内置对象。

(例如当我们要在service方法之外去调用session对象或者request对象等,)

public void _jspService(request,response){

创建内置对象

HttpSession session =....;

ervletConfig config = ....;

    把8个经常使用的内置对象封装到PageContext对象中

PageContext pageContext  = 封装;

调用method1方法(如果将这八个内置对象一个一个的作为参数传递给下面的方法,显然过于麻烦,这个时候我们可以使用已经封装好了的pageContext作为参数传递过去明显就简单多了)

method1(pageContext);

}

public void method1(PageContext pageContext){

希望使用内置对象

从PageContext对象中获取其他8个内置对象

JspWriter out =pageContext.getOut();

HttpServletRequest rquest = pageContext.getRequest();

........

}

Jsp(3):内置对象和四种域对象的理解

注意:pageContext也是一个域对象,已经有四个域对象了:request,servletContext,还有session,现在又有pageContext,(cookie不是域对象,而是将数据发送到浏览器端保存),那么现在servlet已经有三个域对象了,而jsp有四个域对象(jsp就是一个servlet)。

#保存数据

1)默认情况下,保存到page域

pageContext.setAttribute("name");

2)可以向四个域对象保存数据

pageContext.setAttribute("name",域范围常量)

#获取数据

  1)、默认情况下,从page域获取

pageContext.getAttribute("name")

  2)、可以从四个域中获取数据

      pageContext.getAttribute("name",域范围常量)

          PageContext.PAGE_SCOPE (page域)

  PageContext.REQUEST_SCOPE(request域)

PageContext..SESSION_SCOPE(session域)

PageContext.APPLICATION_SCOPE(aplication域:即servletContext)

  3)、自动在四个域中搜索数据

pageContext.findAttribute("name");

    如果有相同的名字,则按照顺序:page域 -> request域 -> session域- > context域(application域)  

我们可以来对pageContext来做实验

<%
//pageContext作为域对象去保存数据
pageContext.setAttribute("message", "i am coming");
pageContext.setAttribute("message", "我是pageContext中设置的request域中的值,i am coming", pageContext.REQUEST_SCOPE);
//request.setAttribute("name", "gqxing"); //等价于上面的代码 request.setAttribute("value", "request's value");
%>
<hr>
<%--
原则:在那个域中保存数据,必须在哪个域中取数据。
--%>
<%
//获取数据
String message=(String)pageContext.getAttribute("message");
out.print(message+"<hr>");
String name=(String)request.getAttribute("message");
out.print(name);
%> <hr>
<span>用pageContext中的request域去取request域中设置的值(request.setAttribute("value", "request's value");)</span>
<% String value=(String)pageContext.getAttribute("message", pageContext.REQUEST_SCOPE);
out.print(value);
%>
<hr><span>用findattribute去查找:</span>
<%--
findAttribute:自动搜索功能
顺序:page域(pageContext)——>request域——>session域——>application域。
--%>
<%
String name3=(String)pageContext.findAttribute(message);
out.print(name);
%>

  结果如图所示:

Jsp(3):内置对象和四种域对象的理解


关于四种域对象的理解

可以来试着去辨别各自的区别(jsp的四个域对象的作用范围)

page域(pageContext):只能作用于当前页面,既不能用来做做转发的数据分享,也不能做重定向的数据分享

request域:只能作用于同一个请求的数据共享,所以只能在请求的转发中使用

session域:只能作用于一次对话*享数据(一次对话:用户打开浏览器,浏览多个web站点后,关闭该浏览器),转发和重定向都可以使用

context域(application):只能在同一个web应用中使用。(全局的)

我们可以做如下的实验:

先用请求的转发做一个实验,如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head> <title>My JSP 'demo4.jsp' starting page</title>
</head>
<body>
<%--数据的保存面 --%>
<%pageContext.setAttribute("messsage", "page'vale",pageContext.PAGE_SCOPE);
pageContext.setAttribute("message", "request'value",pageContext.REQUEST_SCOPE);
pageContext.setAttribute("message", "session'value",pageContext.SESSION_SCOPE);
pageContext.setAttribute("message", "context'value", pageContext.APPLICATION_SCOPE);
%>
<%
request.getRequestDispatcher("/demo5.jsp").forward(request, response);
%>
</body>
</html>

  然后在另一个页面去接受数据

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
page:<%=pageContext.getAttribute("message") %>
<hr>
request:<%=pageContext.getAttribute("message",pageContext.REQUEST_SCOPE) %>
<hr>
session:<%=pageContext.getAttribute("message",pageContext.SESSION_SCOPE) %>
<hr>
application(context):<%=pageContext.getAttribute("message",pageContext.APPLICATION_SCOPE) %>
</body>
</html>

 最后发现结果如图所示:

Jsp(3):内置对象和四种域对象的理解

当我们将转发方式改为重定向的时候,如下:

response.sendRedirect(request.getContextPath()+"/demo5.jsp");

这时结果如图:

Jsp(3):内置对象和四种域对象的理解