JSP的九大内置(隐式)对象
在JSP中有九个对象可以直接使用而不用获取,在JSP转为Servlet的过程中会帮我们定义获取好,所以可以直接使用,如下。
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
隐式对象 | 说明 |
---|---|
request | 转译后对应HttpServletRequest/ServletRequest对象 |
response | 转译后对应HttpServletRespons/ServletResponse对象 |
session | 转译后对应HttpSession对象 |
application | 转译后对应ServletContext对象 |
out | 转译后对应JspWriter对象,其内部关联一个PringWriter对象 |
page | 转译后对应this |
config | 转译后对应ServletConfig对象 |
exception | 译后对应Throwable对象,代表由其他JSP页面抛出的异常对象,只会出现于JSP错误页面(isErrorPage设置为true的JSP页面) |
pageContext | 转译后对应PageContext对象,它提供了JSP页面资源的封装,并可设置页面范围属性 |
转译后的对象我们基本都很熟悉,也就不过多的介绍了,不明白的看看我的servlet的文章吧。
out对象
需要注意的是out这个隐式对象,转译后为JSPWriter,用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至可以关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
1.设置page指令的buffer属性关闭了out对象的缓存功能
2.out对象的缓冲区已满
3.整个JSP页面结束
举例如下:
<body>
aaa<br>
<%
out.print("bbb");
response.getWriter().write("ccc");
%>
</body>
浏览器返回结果如下:
ccc aaa
bbb
原因如下:JSP在运行到 response.getWriter().write(“ccc”); 时会将内容输出至response的出ccc,而aaa和bbb的输出都是由out来完成的,而aaa在bbb的前面,在jsp页面结束,两者被输出,结果就是如上
pageContext对象
pageContext与其他8大对象的关系
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象(还有三个域对象:ServletContext,Session,Request),这个域对象的生命周期最短,作用域最小,他的作用域就是当前的jsp页面,当然它可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
pageContext获取其他8大对象:
- getException方法返回exception隐式对象
- getPage方法返回page隐式对象
- getRequest方法返回request隐式对象
- getResponse方法返回response隐式对象
- getServletConfig方法返回config隐式对象
- getServletContext方法返回application隐式对象
- getSession方法返回session隐式对象
- getOut方法返回out隐式对象
pageContext对forward和include的简写
pageContext为什么要封装其它8大内置对象呢?在JSP中不是都可以直接获取吗?如果在编程过程中,把pageContext对象传递给一个普通java对象,那么这个java对象将可以操作其他8大对象,可以做的事情就很多了。
request.getRequestDispatcher("/xxxx/xxx").forward(request, response);
request.getRequestDispatcher("/xxxx/xxx").include(request, response);
pageContext.forward("/xxxx/xxx");//jsp下
pageContext.include("/xxxx/xxx");//jsp下
servlet中获取pageContext的方法为:
PageContext pageContext = javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true, 8192, true);
pageContext域的属性操作
pageContext对象中的操作域中数据的方法
- public void setAttribute(java.lang.String name,java.lang.Object value)
- public java.lang.Object getAttribute(java.lang.String name)
- public void removeAttribute(java.lang.String name)
pageContext对象中还封装了访问其它域的方法(和上面的方法不同之处就是多了一个参数,这个参数是可以直接指定相应的域)
- public java.lang.Object getAttribute(java.lang.String name,int scope)
- public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
- public void removeAttribute(java.lang.String name,int scope)
代表各个域的常量
- PageContext.APPLICATION_SCOPE
- PageContext.SESSION_SCOPE
- PageContext.REQUEST_SCOPE
- PageContext.PAGE_SCOPE
下面这个方法是非常重要的,因为这个方法是在所有的域中查找数据,查找顺序是:pageContext->request->session->ServletContext,如果查找不到相应的数据的话,就返回一个空字符串,这个方法和之后要说到的el表达式的功能是一样的
findAttribute方法 (*重点,查找各个域中的属性)
四大作用域
到此为止,web开发接触到了4个域对象:
- pageContext(称之为page域)
- request(称之为request域)
- session(称之为session域)
- servletContext(称之为application域)
四大作用域的作用范围大小为pageContext<request<session<servletContext
application(ServletContext)
1、生命周期:当Web应用被加载进容器时创建代表整个web应用的application对象,当服务器关闭或Web应用被移除时,application对象跟着销毁。
2、作用范围:整个Web应用。
3、作用:
- 3.1 application.setAttribute(“key”,Object value):存储整个web应用公用的数据
-
3.2 在不同Servlet 之间转发(不常用)
this.getServletContext().getRequestDispatcher(“/servlet/Demo10Servlet”).forward(request,response);
注意:由于request对象也有getRequestDispatcher(“**”)方法,所有我们开发是通常使用request调用该方法实现重定向。
- 3.3 读取资源文件。
资源的读取一般用到以下方法:
this.getServletContext().getRealPath(“/1.properties”)
this.getServletContext().getResourceAsStream(“/1.properties”)
session 域 (HttpSession)
HttpSession 在服务器中,为浏览器创建独一无二的内存空间,在其中保存会话相关的信息。
1、生命周期:在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的session,如果没有就在内存 中创建一个session并返回。
当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。
如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。
如果调用session提供的invalidate() ,可以立即销毁session。
注意:服务器正常关闭,再启动,Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内,则活化后session还是存在的。否则Session不存在。 如果JavaBean 数据在session钝化时,没有实现Serializable 则当Session活化时,会消失。所以保存在session中的javaBean应该实现Serializable。
2、作用范围:一次会话。
3、作用:保存登录的用户信息、购物车信息等
request域 –(HttpServletRequest)
1、生命周期:在service 方法调用前由服务器创建,传入service方法。整个请求结束,request生命结束。
2、作用范围:整个请求链(请求转发也存在)。
3、作用: 在整个请求链中共享数据。最常用到:在Servlet 中处理好的数据交给Jsp显示,此时参数就可以放置在Request域中带过去。
pageContext域—(PageContext)
1、生命周期:当对JSP的请求时开始,当响应结束时销毁。
2、作用范围:整个JSP页面,是四大作用域中最小的一个。
3、作用:
(1)获取其它八大隐式对象,可以认为是一个入口对象。
(2)获取其所有域中的数据
(3)跳转到其他资源 其身上提供了forward和include方法,简化重定向和转发的操作
JSP标签库
虽然我们希望JSP页面仅用作数据显示模块,不要嵌套任何java代码引入任何业务逻辑,但在实际开发中不引入一点业务逻辑是不可能的,但引入业务逻辑会导致页面出现难看java代码,怎么办?
Sun公司允许用户开发自定义标签封装页面的java代码,以便jsp页面不出现一行java代码。当然sun公司在jsp页面中也内置了一些标签(这些标签叫做jsp标签),开发人员使用这些标签可以完成页面的一些常用业务逻辑。
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在JSP页面中提供业务逻辑功能。
<jsp:include>标签
<jsp:forward>标签
<jsp:param>标签
<jsp:useBean>标签
<jsp:setProperty>标签
<jsp:getProperty>标签
1.标签
语法:
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
- 动态引入
<jsp:include>
标签是动态引入(和使用代码进行include一样),<jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。
- 静态引入
<%@ include file="/head.jsp"%>
include指令是静态引入(编译时引入),涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
- 重点注意
不管是<jsp:include>标签,还是include指令,它们都会把两个JSP页面内容合并输出,所以这两个页面不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。
2.标签
<jsp:forward>
标签用于把请求转发给另外一个资源。
语法:
<jsp:forward page="relativeURL | <%=expression%>" />
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。
3.或者标签
当使用<jsp:include>
和<jsp:forward>
标签引入或将请求转发给其它资源时,可以使用<jsp:param>
标签向这个资源传递参数。
语法1:
<jsp:include page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
语法2:
<jsp:forward page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:forward>
<jsp:param>
标签的name属性用于指定参数名,value属性用于指定参数值。在<jsp:include>
和<jsp:forward>
标签中可以使用多个<jsp:param>
标签来传递多个参数。
4.标签,标签,标签
<body>
<!-- 找到就直接用,找不到实例化 scope默认是page域-->
<jsp:useBean id="person" class="com.wy.entity.Person" scope="page"/>
<!-- 直接设置属性值(8种基本类型的转换) -->
<jsp:setProperty name="person" property="name" value="xxx"/>
<!-- 用请求参数给属性赋值(8中基本类型的转换) -->
<jsp:setProperty name="person" property="name" param="name"/>
<!-- 获取Person中的属性name的值 -->
<jsp:getProperty name="person" property="name"/>
</body>
同时我们定义了一个Bean对象:com.wy.entity.Person,其中有一个name属性(一定要有get/set方法才叫属性)
对于标签<jsp:useBean>
他可以指定在哪个域中创建这个bean对象,他的规则是首先在这个域中查找有没有这个对象,没有就创建,有就直接拿来使用。
对于<jsp:setProperty>
标签,可以直接使用value属性设置属性的值,这里面他内部是有一个类型转换的,可以将字符串值转化成8中基本类型的值,其他对象类型的转化是会报错的,比如我们现在Person类中有一个属性birthday是Date型的,那么我们这里就不能直接写成这样:
<jsp:setProperty name="person" property="birthday" value="1990-08-01"/>
这样系统会报类型转化错误,
当然我们可以直接使用脚本表达式给这个属性值传递一个Date类型的对象,这样就不会又错了:
<jsp:setProperty name="person" property="birthday" value="<%=new Date()%>"/>
当然我们也可以使用请求参数来设置属性值:
<jsp:setProperty name="person" property="names" param="name"/>
我们访问:http://localhost:8080/JspDemo/bean.jsp?names=person,这样就可以进行属性赋值
同时这里的name属性中的填的是<jsp:useBean>
标签中的id值,所以说,当我们在使用get/setProperty标签的时候一定是在useBean标签之后
关于取出属性值的标签<jsp:getProperty>
的话就简单了。
JSP的路径配置
由于JSP本质就是一个Servlet,所以配置融Servlet一样
<!-- jsp路径配置 -->
<servlet>
<servlet-name>SimpleJspServlet</servlet-name>
<jsp-file>/index.jsp</jsp-file>
<load-on-startup>1</load-on-startup >
</servlet>
<servlet-mapping>
<servlet-name>SimpleJspServlet</servlet-name>
<url-pattern>/index5.jsp</url-pattern>
</servlet-mapping>
对jsp做路径映射会使得访问控制更加灵活