知识点: 一个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页面
服务器自动生成的servlet代码:
jsp由Java代码和HTML代码组成,在生成的servlet中HTML代码是由 javax.servlet.jsp.JspWriter的对象out.write(“…“)写的。这个对象JspWriter正好是jsp的九大内置对象之一的out。
九大内置对象:
内置对象: jsp也就是servlet自动创建了九个对象。 page、config、request、response、session、application、out、exception、pageContext exception对象默认不会创建,request和response对象作为参数传入。所以将test.jsp 生成的servlet打开可以看到剩下的6个内置对象的定义。
1.page对象
根据定义我们可以发现page对象的创建:final java.lang.Object page = this; 也就是page的本身就是servlet类本身(this)。
我们可以在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配置:
servlet写法:
我们可以在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对象的地址。
不论是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对象输出内容的前面,给个例子:
访问该页面,得到结果:
但是也可以按照我们希望的顺序输出,那就是在out输出完后加一个方法 out.flush();顺序就是我们的代码顺序了。 原理: PrintWriter 有一个缓冲区, 当我们用printwriter对象输出页面的内容会全部到缓冲区中,然后输出到页面。而JSPWriter也有这么一个缓冲区,当缓冲区满了就会输出到PrintWriter的缓冲区。然后再一起输出到页面。 刚刚的代码也就是。
- printwriter.write(“<h1>PrintWriter1</h1>”); “PrintWriter1”进入PrintWriter的缓冲区。
- out.write(“<h1>JSPWriter</h1>”); “JSPWriter”进入JSPWriter的缓冲区。
- printwriter.write(“<h1>PrintWriter2</h1>”); “PrintWriter2”进入PrintWriter的缓冲区。
- 结束,JSPWriter缓冲区的内容写到PrintWriter的缓冲区中。
- 所以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() 分行显示各种数据类型的内容。 所以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 举个栗子:
运行结果:
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