笔记:jsp的九大内置对象和四大作用域

知识点: 一个jsp页面的本质其实就是一个servlet。重写了Service方法。

tomcat服务器将jsp自动生成servlet的代码存放位置就在tomcat安装目录下的work中。

我的是在:C:\Program Files\Apache Software Foundation\Tomcat 9.0\work\Catalina\localhost\myPro\org\apache\jsp

创建一个 test.jsp页面

笔记:jsp的九大内置对象和四大作用域

服务器自动生成的servlet代码:

笔记:jsp的九大内置对象和四大作用域

jsp由Java代码和HTML代码组成,在生成的servlet中HTML代码是由
javax.servlet.jsp.JspWriter的对象out.write("<html>...</html>")写的。这个对象JspWriter正好是jsp的九大内置对象之一的out。

九大内置对象:

内置对象: jsp也就是servlet自动创建了九个对象。

page、config、request、response、session、application、out、exception、pageContext

exception对象默认不会创建,request和response对象作为参数传入。所以将test.jsp 生成的servlet打开可以看到剩下的6个内置对象的定义。

笔记:jsp的九大内置对象和四大作用域

1.page对象

根据定义我们可以发现page对象的创建:final java.lang.Object page = this;

也就是page的本身就是servlet类本身(this)。

笔记:jsp的九大内置对象和四大作用域

我们可以在jsp打印this和page的地址会发现是指向同一个地址,但是一些方法却被隐藏起来了。

page变量属于pageContext域, 也就是作用范围是当前jsp页面。这很容易理解了。当前page就是当前这个servlet的this指针。当然不能到其他页面。当然刷新页面相当于重新访问servlet,所以page也就重新刷新。之前储存的内容当然也就清空了。

2.config对象

web容器在初始化时使用一个ServletConfig(即config)对象向JSP页面传递信息,此配置信息包括初始化参数(在当前Web应用的应用部署描述文件web.xml中定义)以及表示Servlet或JSP页面所属Web应用的ServletContext对象。

也就是说config对象可以将web.xml配置信息传递到jsp页面。但是jsp初始化配置信息情况比较少,但是对于servlet的使用的情况较多。用法:

web.xml配置:

笔记:jsp的九大内置对象和四大作用域

servlet写法:

笔记:jsp的九大内置对象和四大作用域

我们可以在web.xml配置数据库的账号密码。然后再servlet中得到这个账号密码。当然还能得到一些其他的配置信息。

所以conf对象当然属于pageContext域,作用范围也固然是当前页面。

3. request对象

根据servlet中会发现,request对象并没有在servlet中定义,request对象是作为参数传递过来的。其实request对象是在客户端(浏览器)发送一次请求,服务器(tomcat)自动帮我们将请求的消息封装进request中,生成request对象传给servlet。所以request对象包含了客户端发起请求的所有信息。

request对象的作用是与客户端交互,收集客户端的Form、Cookies、超链接,或者收集服务器端的环境变量。

request对象的常用方法:

  • String getParameter(String name),获取客户端的参数值,常用于表单
  • String[] getParameterValues(String name),获取单个参数的所有值,常用语表单中的多选
  • Enumeration getPameterName(),获取所有的参数的名称
  • void setCharacterEncoding(String encoding),设置字符编码方式
  • Cookie[ ] getCookies(),得到所有的Cookies

当然request还可以得到和设置请求头所有信息。

request还有一个很重要的作用:请求转发。

  • request.getRequestDispatcher("url").forward(request, response);
  • request.getRequestDispatcher("url").include(request, response);

因为可以转发,request对象可以存放数据,

用法:request.setAttribute(str, Object);

在转发的jsp页面中取数据:Object = request.getAttribute(str);

 

forward 和 include 的实质:

我们在servlet中分别用forward和include请求转发跳转页面。用out输出一些内容到网页中,并打印request对象和response对象的地址。然后在跳转的页面输出request对象和response对象的地址。

笔记:jsp的九大内置对象和四大作用域

不论是forward还是include会发现地址不同,也就是jsp页面中的request,forward和servlet中的不是同一个request。但是却可以得到信息,所以应当是拷贝了一份request过去。

forward转发会发现,不论是转发前的“hhhh”还是转发后的“h1111hhh”,都不会在test.jsp的页面中输出。而include却会输出。

我们查看两者的jsp页面的源码便可发现,其实include其实是将servlet所代表的jsp页面和转发的jsp页面合并。所以如果前一个只是单纯的servlet页面,并无jsp。那么include就可以输出一些东西到转发的jsp页面中,但是include并不常用。

也就是response并不会传递,只是两个页面合并后才能用转发前页面的response对象的getWriter。

因此:请求转发只能转发到同一web项目的资源。客户浏览器只做了一次请求,服务器完成请求处理并转发请求,页面跳转。所以url地址不会变化,仍然是客户端(浏览器)的第一次请求的URL。

请求转发,不改变url地址,会跳转界面,还会将request对象的信息传递过去,直到请求结束,才会销毁request对象。

所以request对象属于request域,在请求结束后才会真正销毁。虽然每个页面都会新建一个request对象,但是对于请求转发来说,request会完全复制过去,也就相当于request对象并未消失。所以属于request域。刷新页面相当于重新发送请求,所以request对象会重新创建,之前的信息丢失。

4. response对象

Response对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应。Response对象只提供了一个数据集合cookie,它用于在客户端写入cookie值。若指定的cookie不存在,则创建它。若存在,则将自动进行更新。结果返回给客户端浏览器。

response最重要的就是响应页面。所以response最重要的也就是得到和设置响应头的信息

常用方法:

  • String setCharacterEncoding()//设置响应字符编码格式
  • String getCharacterEncoding()//获取响应字符编码格式
  • void setContentType(String type)//设置响应MIME类型
  • sendRedirect(java.lang.String location)//请求重定向
  • PrintWriter getWriter()//获取打印输出对象

response可以响应界面并给浏览器添加cookie

用法:response.addCookie(cookie);

response还有一个很重要的功能,重定向:

用法:response.sendRedirect(location);

重定向也可以跳转界面,但是与请求转发不同的是重定向并不能传递request,地址栏上的url也会发生变化,而且能够访问其他web项目的资源。

本质:客户端(浏览器)发送了两次请求。客户端(浏览器)发送第一次请求,服务器接受处理,response返回一个状态码302  (3xx状态码重定向到其他地方: 需要客户端再次发送请求),客户端(浏览器)接收,发现是302,于是又发送了一条请求,请求的url便是重定向的参数location,服务器接收请求处理并跳转页面。

因为是客户端(浏览器)发送的请求,所以自然可以访问其他web项目。地址栏也自然会发生变化。

因此,response其实是pageContext域的属性,在访问jsp或者servlet时服务器自动创建,但是在有关请求转发或者重定向时,都没有拷贝过去,所以response是自然是属于pageContext域。

5. session对象

Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。

session实现的两种机制:

1. cookie, 服务器没生成一个session对象存储信息,每个session对象都有一个sessionid, 响应客户端(浏览器)生成一个cookie,存放sessionid,服务器会读取cookie中的sessionid来检索到以前的session对象。

2.重写url,上述方法在浏览器禁用cookie的话无法实现,所以我们在每个访问的url后加上sessionid也同样能做到。

得到session的一种方式:

HttpSession session = request.getSession();

为session设值:

session.setAttribute("usrid", userid);

取值:

userid = session.getAttribute("usrid");

session的生存周期,session会在客户端关闭,或者超过设定时间时自动销毁,默认为30分钟。

设值时间的一种方式,也可以在xml配置文件,或者tomcat中配置。

session.setMaxInactiveInterval(900);  //在60*15 = 900, 15分钟后销毁

故,session属于session域。生存周期为时间到,或者浏览器关闭,自动销毁。

6.application对象

application对象的使用方法和session很类似,但是不同的是application的生存周期是在web项目删除或者服务器关闭才会销毁。

原理: 在服务器端创建的对象,储存在服务器端的内容中。所以客户端的一切行为都不会影响到application对象。

所以application属于application域,作用范围在整个web项目。

7. out对象

作用向页面输出内容, out对象被封装为javax.servlet.jsp.jspWriter接口,通过调用pageContext.getOut()方法可以获取out对象。

out对象是字符流对象,其作用和用法与ServletResponse.getWriter()方法返回的PrintWriter对象十分类似。都可以向页面输出信息,但是有所不同,那就是PrintWriter输出的内容一般都会在out对象输出内容的前面,给个例子:

笔记:jsp的九大内置对象和四大作用域

访问该页面,得到结果:

笔记:jsp的九大内置对象和四大作用域

但是也可以按照我们希望的顺序输出,那就是在out输出完后加一个方法 out.flush();顺序就是我们的代码顺序了。

原理:

PrintWriter 有一个缓冲区, 当我们用printwriter对象输出页面的内容会全部到缓冲区中,然后输出到页面。而JSPWriter也有这么一个缓冲区,当缓冲区满了就会输出到PrintWriter的缓冲区。然后再一起输出到页面。

刚刚的代码也就是。

  1. printwriter.write("<h1>PrintWriter1</h1>");   "PrintWriter1"进入PrintWriter的缓冲区。
  2. out.write("<h1>JSPWriter</h1>");  "JSPWriter"进入JSPWriter的缓冲区。
  3. printwriter.write("<h1>PrintWriter2</h1>");   "PrintWriter2"进入PrintWriter的缓冲区。
  4. 结束,JSPWriter缓冲区的内容写到PrintWriter的缓冲区中。
  5. 所以PrintWriter的缓冲区变成"PrintWriter1" "PrintWriter2" "JSPWriter";

可以用out.getBufferSize()查看缓冲区的大小,我的默认是8192。

out.flush 函数就是讲out缓冲区的内容直接输出到PrintWriter缓冲区中。

一些函数:

1.public abstract void clear()
清除缓冲区中的内容,不将数据发送至客户端。
2.public abstract void clearBuffer()
将数据发送至客户端后,清除缓冲区中的内容。
3.public abstarct void close()
关闭输出流。
4.public abstract void flush()
输出缓冲区中的数据。
5.public int getBufferSize()
获取缓冲区的大小。缓冲区的大小可用<%@ page buffer="size" %>设置。
6.public abstract int getRemainning()
获取缓冲区剩余空间的大小
7.public boolean isAutoFlush()
获取用<%@ page is AutoFlush="true/false"%>设置的AutoFlush值。
8.public abstract void newLine()
输出一个换行字符,换一行。
9.public abstract void print()
显示各种数据类型的内容。
10.public abstract void println()
分行显示各种数据类型的内容。 笔记:jsp的九大内置对象和四大作用域

所以out对象为pageContext域。

8. exception对象

使用它,必须结合page指令中的isErrorPage属性和errorPage属性。都是在头部定义。如果定义了errorPage="error.jsp"那么就会抛出异常跳转到error.jsp页面,而不会直接弹出500错误。如果定义了isErrorPage="true",就说明这个页面就是能够接受异常的错误界面。

_jspx_page_context对异常的处理也非常简单:如果该页面的page指令指定了errorPage属性,则将请求forward到errorPage属性指定的页面,否则使用系统页面来输出异常信息。但是该页没有内置exception对象。

errorPage页面则定义了exception对象,定义如下:

java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);

也就是forward中的request请求带来了exception的信息。所以exception对象只存在error.jsp页面中,不会到其他页面。所以exception作用域:pageContext

举个栗子:

笔记:jsp的九大内置对象和四大作用域笔记:jsp的九大内置对象和四大作用域

运行结果:

笔记:jsp的九大内置对象和四大作用域

9. pageContext对象

JSP页面的管理者(上下文),它能获得其他八个内置对象。得到四个作用域常量。

1、获得其它八大内置对象 getXxx()c

  • pageContext.getOut();  //获得out对象
  • pageContext.getApplication();  //获得application对象
  • pageContext.getRequest();       //获得request对象。
  • ......  //获得其他内置对象

2、 提供作用域常量 scope, 其实就是int类型,分别为1、2、3、4。封装起来代表四种类型。

  • PageContext.PAGE_SCOPE  page
  • PageContext.REQUEST_SCOPE  request
  • PageContext.SESSION_SCOPE  response
  • PageContext.APPLICATION_SCOPE  application

3、为各个域存值和取值

  •  pageContext.getAttribute(name [, scope]);  //获得scope作用域数据
  •      pageContext.setAttribute(name,value [, scope]); //给scope作用域设置内容
  •  pageContext.removeAttribute(name [, scope]);  //给scope作用域移除内容

scope就是上面的四种作用域常量 。

一次获得指定名称内容

4、findAttribute(name); //依次从page、request、session、application 获得内容。

所以pageContext对象也是pageContext域。它只在本身页面范围有效。

四大作用域:

pageContext  <  request  <  session < application

pageContext 域:   范围页面本身。

request 域:   范围一次请求。

session域:  范围在设定时间内整个浏览器,只要浏览器不关闭,都有效。

application域:  范围整个服务器运行。只要项目没被移除,或者服务器没重启或关闭,那么application都存在。

 

参考链接,致谢:

https://www.cnblogs.com/whgk/p/6427759.html

http://blog.csdn.net/meiyalei/article/details/2129120

https://www.cnblogs.com/fjdingsd/p/4918748.html

http://blog.csdn.net/qq_34342083/article/details/53944941