九大内置对象
JSP容器为某个页面提供了java对象,开发者可以直接使用它们,而不需要提前进行声明,而这个对象又被称之为隐式对象,预定义变量,以及所说的内置对象。
JSP一共有九个内置对象:
对象 | 描述 |
---|---|
request | HttpServletRequest 接口的实例 |
response | HttpServletResponse 接口的实例 |
out | JspWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
但是为什么可以直接使用,以及在哪里使用呢?先看jsp转换为java文件后的源码:
从这里可以看出(除Exception)其实在转换的Java文件的方法**_jspService**,而这个也就说明了在jsp中脚本中只能在**<%% >** 中使用,毕竟这个脚本格式下写的java代码才会在**_jspService**方法中。
但是上面只有八个,我们说的是九个,第九个如何出来,那就需要将jsp中page指令中添加如下:
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %>
然后打开生成的java文件看一下:
这样数一下就是九个对象了。
resuqest对象
request对象是javax.servlet.http.HttpServletRequest 类的实例。每当客户端请求一个JSP页面时,JSP引擎就会制造一个新的request对象来代表这个请求。
request对象提供了一系列方法来获取HTTP头信息,cookies,HTTP方法等等。
演示:
<%
Enumeration<String> en=request.getHeaderNames();
while(en.hasMoreElements()){
System.out.println(en.nextElement());
}
%>
具体形成Java位置,就不截取了,毕竟前面几篇文章聊过。
看效果:
所以可以看出其可以使用HttpServletRequest 对象的所有的方法。
response对象
response对象是javax.servlet.http.HttpServletResponse类的实例。当服务器创建request对象时会同时创建用于响应这个客户端的response对象。
response对象也定义了处理HTTP头模块的接口。通过这个对象,开发者们可以添加新的cookies,时间戳,HTTP状态码等等。
演示:
response.getWriter().write("骨灰是宫崎老贼的仁慈啊");
所以可以看出其可以使用HttpServletResponse对象的所有的方法。
response.getWriter().write()和response.getWriter().println() 区别
**esponse.getWriter()返回的是PrintWriter,这是一个打印输出流。**两个方法有什么区别呢?
-
print
response.getWriter().print(),不仅可以打印输出文本格式的(包括html标签),还可以将一个对象以默认的编码方式转换为二进制字节输出 -
write
response.getWriter().write() ,只能打印输出文本格式的(包括html标签),不可以打印对象。
其实两者虽然区别但是没有过大的区别,为什么这个地方聊呢,因为为下一个对象作为铺垫。
out对象
out对象是javax.servlet.jsp.JspWriter 类的实例,用来在response对象中写入内容。
最初的JspWriter类对象根据页面是否有缓存来进行不同的实例化操作。可以在page指令中使用buffered='false’属性来轻松关闭缓存。
JspWriter类包含了大部分java.io.PrintWriter类中的方法。不过,JspWriter新增了一些专为处理缓存而设计的方法。还有就是,JspWriter类会抛出IOExceptions异常,而PrintWriter不会。
下表列出了我们将会用来输出boolean,char,int,double,String,object等类型数据的重要方法:
方法 | 描述 |
---|---|
out.print(dataType dt) | 输出Type类型的值 |
out.println(dataType dt) | 输出Type类型的值然后换行 |
out.flush() |
ide 中out提示报错
在ide的jsp页面调用out对象发现报错如下:
因为缺少一个jsp-api.jar 的jar包,所以可以打开自己tomcat路径然后再lib文件夹下复杂:
然后将包引入即可:
可以看出解决了。
然后看起效果:
竟然也可以在页面上显示,这个有一个疑问了为什么和response的效果差不多,以及两者有什么区别,以及使用那个?
out 和response 区别
先搞一个测试:
第一个:
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %>
<html>
<head>
<title>test</title>
</head>
<body>
<%
out.write("out1");
out.write("out2");
response.getWriter().write("response1");
response.getWriter().write("response2");
%>
</body>
</html>
可以看出out输出的内容要在response后面.
现在在如此修改:
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Enumeration" %>
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %>
<html>
<head>
<title>test</title>
</head>
<body>
<%
out.write("out1");
out.flush();
out.write("out2");
response.getWriter().write("response1");
response.getWriter().write("response2");
%>
</body>
</html>
为什么会有这样的结果呢?
看图解释:
这个又有一个问题,那么在返回页面数据的时候用out对象还是response对象返回数据呢?
看一下jsp生成的java文件:
可以看出官网使用的out,所以一般情况下。在jsp页面中统一使用out 来进行输出。避免打乱页面输出内容的顺序。
而官网为什么使用out,其原因是自然是out对象在数据返回的时候性能会更好一些,不然官网为什么要使用out呢.
out的write方法和println方法区别
查看源码可以看出print⽅法是⼦类JspWriter,write是Writer类中定义的方法法 。
public abstract class JspWriter extends Writer
而JspWriter是一个writer的子类,而看一下官网文档:
可以看出JspWriter类没有重写write方法,调用父类wrier的write方法。
所以看出两者本质调用的方法是不同的,具体呈现有什么什么不同呢?
-
out.write() 仅支持输出字符类型数据,字符串,字符数据,字符串等
-
out.print() 可以将各种数据通过都转换为字符串形式,看源码无论布尔还是字符等都转换为字符串
老规矩演示:
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Enumeration" %>
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %>
<html>
<head>
<title>test</title>
</head>
<body>
<%
out.write("你惹他干嘛 <br>");
out.print("宫崎老贼的怜悯啊");
out.print("宫崎老贼的怜悯啊 <br>");
out.println("宫崎老贼的怜悯啊1");
out.println("宫崎老贼的怜悯啊1");
%>
<br>
<% out.write(97);
%>
<br>
<%
out.print(97); %>
</body>
</html>
补充:其实可以看出println和print再页面呈现的只多了一个空格,而不是换一下。
其实可以看出out.write中参数为数字的话,是asicc码。
所以可以看出out.write适合输出字符串,out.print适合输出任何数据,因为比write多了一步转换为字符串,所以一般在我们选择两个方法的时候,防止出错就采用out.print方法
session对象
ession对象是 javax.servlet.http.HttpSession 类的实例。和Java Servlets中的session对象有一样的行为。
session对象用来跟踪在各个客户端请求间的会话。
这个在四大域对象里面聊.
application对象
application对象直接包装了servlet的ServletContext类的对象,是javax.servlet.ServletContext 类的实例。
这个对象在JSP页面的整个生命周期中都代表着这个JSP页面。这个对象在JSP页面初始化时被创建,随着jspDestroy()方法的调用而被移除。
通过向application中添加属性,则所有组成您web应用的JSP文件都能访问到这些属性。
这个在四大域对象里面聊.
config对象
config对象是 javax.servlet.ServletConfig 类的实例,直接包装了servlet的ServletConfig类的对象。
这个对象允许开发者访问Servlet或者JSP引擎的初始化参数,比如文件路径等。
以下是config对象的使用方法,不是很重要,所以不常用:
config.getServletName();
它返回包含在元素中的servlet名字,注意,元素在 WEB-INF\web.xml 文件中定义。
pageContext 对象
pageContext对象是javax.servlet.jsp.PageContext 类的实例,用来代表整个JSP页面。
这个对象主要用来访问页面信息,同时过滤掉大部分实现细节。
这个对象存储了request对象和response对象的引用。application对象,config对象,session对象,out对象可以通过访问这个对象的属性来导出。
pageContext对象也包含了传给JSP页面的指令信息,包括缓存信息,ErrorPage URL,页面scope等。
PageContext类定义了一些字段,包括PAGE_SCOPE,REQUEST_SCOPE,SESSION_SCOPE, APPLICATION_SCOPE。它也提供了40余种方法,有一半继承自javax.servlet.jsp.JspContext 类。
其中一个重要的方法就是 removeAttribute(),它可接受一个或两个参数。比如,pageContext.removeAttribute(“attrName”) 移除四个scope中相关属性,但是下面这种方法只移除特定 scope 中的相关属性:
pageContext.removeAttribute("attrName", PAGE_SCOPE);
这个在四大域对象里面聊.
page 对象
这个对象就是页面实例的引用。它可以被看做是整个JSP页面的代表。
page 对象就是this对象的同义词。
来演示:
<%
System.out.println(page==this);
%>
可以看后台输出的数据:
exception 对象
exception 对象包装了从先前页面中抛出的异常信息。它通常被用来产生对出错条件的适当响应。
四大域对象
其实四大域对象,也是上面九个内置对象中的四个,其是为什么说是域对象呢?
因为其更多的时候作为存储数据来进行交互的,其中四个域名对象是:
域对象 | 类 | 描述 |
---|---|---|
pageContext | PageContext重新类的实现类 | 当前JSP页面范围内有效 |
request | HttpServletRequest类 | 数据一次请求中有效 |
session | HttpSession类 | 一个会话范围有效,通俗的说就是其生命周期是打开浏览器访问,直到浏览器关闭结束 |
application | ServletContext类 | 整个web范围内都有效,简单的说就是web工程不关闭服务器,那其数据一致都存在. |
而域对象自然也有共同点:
- 域对象必须能够有存储数据的功能,还可以获取数据的功能.
- 域对象的内部原理本质就是一个Map集合存储的键值对.
而其常用的方法也是很类似,所以不再演示了,毕竟这个如果演示的话,其重复太多了.
方法 | 描写 |
---|---|
setAttribute(String name, Object value) | 用来存储一个对象,也可以称之为存储一个域属性。 |
getAttribute(String name) | 获取名为name的域属性 |
removeAttribute(String name) | 用来移除域属性,如果参数name指定的域属性不存在,那么本方法不做任何处理; |