JavaWeb开发之十二:JSP九大内置对象

来源:互联网 发布:linux zip文件压缩 编辑:程序博客网 时间:2024/05/19 12:13

一、JSP运行原理

  每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。
  由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
  JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。

二、认识九个内置对象

NO.内置对象类型1pageContextjavax.servlet.jsp.PageContext2requestjavax.servlet.http.HttpServletRequest3responsejavax.servlet.http.HttpServletResponse4sessionjavax.servlet.http.HttpSession5applicationjavax.servlet.ServletContext6configjavax.servlet.ServletConfig7outjavax.servlet.jsp.JspWriter8pagejava.lang.Object9exceptionjava.lang.Throwable

 

 

 

 

 

 

 

 

 

   

  request,response,session,application,config这些对象在前面都已经作了详细的介绍,这里重点介绍一下剩下的pageContext对象,out对象,page对象。

三、内置对象使用说明

3.1、page对象

  page对象表示当前一个JSP页面,可以理解为一个对象本身,即:把一个JSP当作一个对象来看待。page对象在开发中几乎不用,了解一下即可

3.2、out对象

  out对象用于向客户端发送文本数据。 
  out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。 
  JSP页面中的out对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。 
  只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:

  • 设置page指令的buffer属性关闭了out对象的缓存功能
  • out对象的缓冲区已满
  • 整个JSP页面结束

out对象的工作原理图

  

3.3、pageContext对象

  pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象(容器),可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。

3.4、通过pageContext获得其他对象

  • getException方法返回exception隐式对象
  • getPage方法返回page隐式对象
  • getRequest方法返回request隐式对象
  • getResponse方法返回response隐式对象
  • getServletConfig方法返回config隐式对象
  • getServletContext方法返回application隐式对象
  • getSession方法返回session隐式对象
  • getOut方法返回out隐式对象

3.5、pageContext封装其它8大内置对象的意义

  如果在编程过程中,把pageContext对象传递给一个普通java对象,那么这个java对象将可以获取8大隐式对象,此时这个java对象就可以和浏览器交互了,此时这个java对象就成为了一个动态web资源了,这就是pageContext封装其它8大内置对象的意义,把pageContext传递给谁,谁就能成为一个动态web资源,那么什么情况下需要把pageContext传递给另外一个java类呢,什么情况下需要使用这种技术呢,在比较正规的开发中,jsp页面是不允许出现java代码的,如果jsp页面出现了java代码,那么就应该想办法把java代码移除掉,我们可以开发一个自定义标签来移除jsp页面上的java代码,首先围绕自定义标签写一个java类,jsp引擎在执行自定义标签的时候就会调用围绕自定义标签写的那个java类,在调用java类的时候就会把pageContext对象传递给这个java类,由于pageContext对象封装了对其它8大隐式对象的引用,因此在这个java类中就可以使用jsp页面中的8大隐式对象(request,response,config,application,exception,Session,page,out)了,pageContext对象在jsp自定义标签开发中特别重要。

3.6、pageContext作为域对象

  pageContext对象可以作为容器来使用,因此可以将一些数据存储在pageContext对象中。

  pageContext对象的常用方法

1 public void setAttribute(java.lang.String name,java.lang.Object value)2 public java.lang.Object getAttribute(java.lang.String name)3 public void removeAttribute(java.lang.String name)4 public java.lang.Object findAttribute(java.lang.String name)

  重点介绍一下findAttribute方法,这个方法是用来查找各个域中的属性的,查看这个方法的API可以看到关于这个方法的描述:
  Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null.

  当要查找某个属性时,findAttribute方法按照查找顺序"page→request→session→application"在这四个对象中去查找,只要找到了就返回属性值,如果四个对象都没有找到要查找的属性,则返回一个null。

范例:使用pageContext的findAttribute方法查找属性值

复制代码
 1 <%@page contentType="text/html;charset=UTF-8"%> 2 <%@page import="java.util.*"%> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <head> 5     <title>pageContext的findAttribute方法查找属性值</title> 6 </head> 7 <% 8     pageContext.setAttribute("name1", "孤傲苍狼"); 9     request.setAttribute("name2", "白虎神皇");10     session.setAttribute("name3", "玄天邪帝");11     application.setAttribute("name4", "灭世魔尊");12 %>13 <%14     //使用pageContext的findAttribute方法查找属性,由于取得的值为Object类型,因此必须使用String强制向下转型,转换成String类型15     //查找name1属性,按照顺序"page→request→session→application"在这四个对象中去查找16     String refName1 = (String)pageContext.findAttribute("name1");17     String refName2 = (String)pageContext.findAttribute("name2");18     String refName3 = (String)pageContext.findAttribute("name3");19     String refName4 = (String)pageContext.findAttribute("name4");20     String refName5 = (String)pageContext.findAttribute("name5");//查找一个不存在的属性21 %>22 <h1>pageContext.findAttribute方法查找到的属性值:</h1>23 <h3>pageContext对象的name1属性:<%=refName1%></h3>24 <h3>request对象的name2属性:<%=refName2%></h3>25 <h3>session对象的name3属性:<%=refName3%></h3>26 <h3>application对象的name4属性:<%=refName4%></h3>27 <h3>查找不存在的name5属性:<%=refName5%></h3>28 <hr/>29 <h1>使用EL表达式进行输出:</h1>30 <h3>pageContext对象的name1属性:${name1}</h3>31 <h3>request对象的name2属性:${name2}</h3>32 <h3>session对象的name3属性:${name3}</h3>33 <h3>application对象的name4属性:${name4}</h3>34 <h3>不存在的name5属性:${name5}</h3>
复制代码

运行结果:

  

  EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、 session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回”” (注意,不是null,而是空字符串)。

pageContext对象中封装了访问其它域的方法

1 public java.lang.Object getAttribute(java.lang.String name,int scope)2 public void setAttribute(java.lang.String name, java.lang.Object value,int scope)3 public void removeAttribute(java.lang.String name,int scope)

代表各个域的常量

1 PageContext.APPLICATION_SCOPE2 PageContext.SESSION_SCOPE3 PageContext.REQUEST_SCOPE4 PageContext.PAGE_SCOPE 

范例:pageContext访问其它域

复制代码
 1 <%@page contentType="text/html;charset=UTF-8"%> 2 <%@page import="java.util.*"%> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <head> 5     <title>pageContext访问其它域</title> 6 </head> 7 <% 8     //此时相当于往session对象中存放了一个name属性,等价于 session.setAttribute("name","孤傲苍狼"); 9     pageContext.setAttribute("name","孤傲苍狼",PageContext.SESSION_SCOPE);10 %>11 <%12     //取得session对象的属性,使用pageContext对象获取13     String refName1 = (String)pageContext.getAttribute("name",PageContext.SESSION_SCOPE);  14     //由于取得的值为Object类型,因此必须使用String强制向下转型,转换成String类型15      String refName2 = (String)session.getAttribute("name");  16 %>17 <h1>取出存放在session对象中的属性值:</h1>18 <p>第一种做法:使用pageContext.getAttribute("attributeName",PageContext.SESSION_SCOPE);去取出session对象中值</p>19 <h3>姓名:<%=refName1%></h3>20 <p>第二种做法:使用session.getAttribute("attributeName");去取出session对象中值</p>21 <h3>姓名:<%=refName2%></h3>
复制代码

  

3.7、PageContext引入和跳转到其他资源

  PageContext类中定义了一个forward方法(用来跳转页面)和两个include方法(用来引入页面)来分别简化和替代RequestDispatcher.forward方法和include方法。
  方法接收的资源如果以“/”开头, “/”代表当前web应用。

范例:使用pageContext的forward方法跳转到其他页面

复制代码
 1 <%@page contentType="text/html;charset=UTF-8"%> 2 <%@page import="java.util.*"%> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <head> 5     <title>使用pageContext的forward方法跳转页面</title> 6 </head> 7 <% 8     //使用pageContext的forward方法跳转到pageContextDemo05.jsp页面,/代表了当前的web应用 9     pageContext.forward("/pageContextDemo05.jsp");10     //使用pageContext.forward(relativeUrlPath)替代RequestDispatcher.forward(relativeUrlPath)11     //使用RequestDispatcher的forward方法实现的跳转方式12     //pageContext.getRequest().getRequestDispatcher("/pageContextDemo05.jsp").forward(request, response);13 %>
复制代码

运行结果如下:
  

1 pageContext.forward("/pageContextDemo05.jsp");

  这种写法是用来简化和替代pageContext.getRequest().getRequestDispatcher("/pageContextDemo05.jsp").forward(request, response);这种写法的。在实际开发中,使用pageContext.forward(relativeUrlPath)方法跳转页面用得不多,主要是因为要在Jsp页面中嵌套java代码,所以这种做法简单了解一下即可,在开发中,要想从一个Jsp页面采用服务器端跳转的方式跳转到另一个Jsp页面,那么一般会使用<jsp:forward>标签,<jsp:forward>标签用于把请求转发给另外一个资源。

范例:使用pageContext的include方法引入资源

复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <head> 4     <title>使用pageContext的include方法引入资源</title> 5 </head> 6 <% 7     pageContext.include("/jspfragments/head.jsp"); 8 %> 9     使用pageContext的include方法引入资源10 <%11     pageContext.include("/jspfragments/foot.jsp");12 %>13 <hr/>14 <%--15 <jsp:include page="/jspfragments/head.jsp"/>16 使用jsp:include标签引入资源17 <jsp:include page="/jspfragments/foot.jsp"/>18 --%>
复制代码

运行结果:

  

   在实际开发中,使用pageContext的include方法引入页面这种做法也很少用,一般都使用jsp:include标签引入资源,因此这种做法了解一下即可。

javaweb学习总结(十八)——JSP属性范围

  所谓的属性范围就是一个属性设置之后,可以经过多少个其他页面后仍然可以访问的保存范围。

一、JSP属性范围

  JSP中提供了四种属性范围,四种属性范围分别指以下四种:

  • 当前页:一个属性只能在一个页面中取得,跳转到其他页面无法取得
  • 一次服务器请求:一个页面中设置的属性,只要经过了服务器跳转,则跳转之后的页面可以继续取得。
  • 一次会话:一个用户设置的内容,只要是与此用户相关的页面都可以访问(一个会话表示一个人,这个人设置的东西只要这个人不走,就依然有效)
  • 上下文中:在整个服务器上设置的属性,所有人都可以访问

二、属性的操作方法

  既然JSP中提供了四种属性范围,则四种属性范围中都将包含以下的属性操作方法。

No.

方法

描述

1

public void setAttribute(String name,Object value)

设置属性

2

public object getAttribute(String name)

取得属性

3

public void removeAttribute(String name)

删除属性

  属性的操作无外乎就是增加、取得和删除这个几个操作。

  单词Attribute的意思是“属性”,setAttribute(String name,Object value)从单词的组合来看就可以知道是这个方法的是设置属性,设置属性的名字和属性的值,名字(name)String类型,值(value)Object类型,由于值为Object类型,这表示可以设置任意类型的数据作为值,因为所有的类都是从Object类型继承而来。因此设置属性值的时候可以是任意类型的数据。getAttribute(String name)方法是根据属性的名字取得属性,removeAttribute(String name)方法是根据属性的名字删除属性。

三、JSP四种属性范围的具体介绍

3.1、page属性范围(pageContext

  page属性范围相对好理解一些:在一个页面设置的属性,跳转到其他页面就无法访问了。但是在使用page属性范围的时候必须注意的是,虽然习惯上将页面范围的属性称为page范围,但是实际上操作的时候是使用pageContext内置对象完成的。

pageContext属性范围操作流程图

    

  pageContext从字面上的定义,可以发现,是表示一个页面(page)的上下文(Context),可以表示一个页面中的所有内容。

  从操作流程图来看,在第一个页面设置的属性经过服务器端跳转到第二个页面以后,在第二个页面是无法取得在第一个页面中设置的属性的,就好比现在坐着的桌子上有一支笔,但一旦离开了这张桌子,坐到别的桌子上时,笔就没有了。

  下面通过代码来观察此范围的属性

范例:pageContextDemo01.jsp

在页面中设置两个属性

复制代码
 1 <%@page contentType="text/html;charset=UTF-8"%> 2 <%@page import="java.util.*"%> 3 <% 4     //此时设置的属性只能够在本页中取得 5     pageContext.setAttribute("name","孤傲苍狼");  //设置属性 6     pageContext.setAttribute("date",new Date()); //设置属性 7     //注意:这里设置的两个属性的名字分别为name和date,这两个是字符串类型的数据,但对应的属性值MLDN和new Date这个两个值却不是字符串类型,而是两个Object类型的数据。 8 %> 9 <%10     //取得设置的属性11     String refName = (String)pageContext.getAttribute("name");  12     //由于取得的值为Object类型,因此必须使用String强制向下转型,转换成String类型13     Date refDate = (Date)pageContext.getAttribute("date");14 %>15 <h1>姓名:<%=refName%></h1>16 <h1>日期:<%=refDate%></h1>
复制代码

程序运行结果如下:

  

  这说明了在本页设置的pageContext范围属性在本页确实可以取得,下面使用跳转语句,观察跳转之后是否还可以取得属性。

范例:pageScopeDemo02.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     pageContext.setAttribute("name","孤傲苍狼");  5     pageContext.setAttribute("date",new Date()); 6 %>7 <%--使用jsp:forward标签进行服务器端跳转--%>8 <jsp:forward page="/pageScopeDemo03.jsp" />
复制代码

范例:pageScopeDemo03.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     String refName = (String)pageContext.getAttribute("name");  5     Date refDate = (Date)pageContext.getAttribute("date");6 %>7 <h1>姓名:<%=refName%></h1>8 <h1>日期:<%=refDate%></h1>
复制代码

  在以上程序中的pageScopeDemo02.jsp只是设置了两个属性,跳转到pageScopeDemo03.jsp之后再在pageScopeDemo03.jsp中取在pageScopeDemo02.jsp设置的page属性。此时,运行结果如下:

  

  使用了服务器端跳转,但是发现内容并不能取得,证明page范围的属性只能在本页中取得,跳转到其他页面之中不能取得。如果现在希望跳转到其他页面之中,依然可以取得,则可以扩大属性范围,使用request属性范围即可。

3.2、request属性范围

  request属性范围表示在一次服务器跳转中有效,只要是服务器跳转,则设置的request属性可以一直传递下去。

  

 范例:requestScopeDemo01.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     request.setAttribute("name","孤傲苍狼");  5     request.setAttribute("date",new Date()); 6 %>7 <%--使用jsp:forward标签进行服务器端跳转--%>8 <jsp:forward page="/requestScopeDemo02.jsp" />
复制代码

 范例:requestScopeDemo02.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     //取得requestScopdemo01.jsp设置的属性5     String refName = (String)request.getAttribute("name");  6     Date refDate = (Date)request.getAttribute("date");7 %>8 <h1>姓名:<%=refName%></h1>9 <h1>日期:<%=refDate%></h1>
复制代码

运行结果如下:

  

  从运行结果来看,程序跳转了,但是与page范围相比,内容可以向下继续传递,即在第一个页面设置的属性跳转到第二个页面后在第二个页面中依然可以取得第一个页面设置的属性。

  如果现在有第三个页面了,则也可以继续向后传递

范例:修改requestScopeDemo02.jsp

1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%--使用jsp:forward标签进行服务器端跳转--%>4 <jsp:forward page="/requestScopeDemo03.jsp" />

范例:requestScopeDemo03.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     //取得requestScopdemo01.jsp设置的属性5     String refName = (String)request.getAttribute("name");  6     Date refDate = (Date)request.getAttribute("date");7 %>8 <h1>姓名:<%=refName%></h1>9 <h1>日期:<%=refDate%></h1>
复制代码

  以上的结果依然可以访问,但是如果,此时使用了超链接的方式传递的话,则属性是无法向下继续传递的。

范例:修改requestScopeDemo03.jsp

复制代码
 1 <%@page contentType="text/html;charset=UTF-8"%> 2 <%@page import="java.util.*"%> 3 <% 4     //取得requestScopdemo01.jsp设置的属性 5     String refName = (String)request.getAttribute("name");   6     Date refDate = (Date)request.getAttribute("date"); 7 %> 8 <h1>姓名:<%=refName%></h1> 9 <h1>日期:<%=refDate%></h1>10 <h1>11 <%--使用超链接的形式跳转,这是客户端跳转,URL地址会改变--%>12 <a href="${pageContext.request.contextPath}/requestScopeDemo04.jsp">跳转到requestScopeDemo04.jsp</a>13 </h1>
复制代码

  此时使用了超链接跳转,一旦跳转之后,地址栏改变,所以此种跳转也可以称为客户端跳转。

requestScopeDemo04.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     //取得requestScopdemo01.jsp设置的属性5     String refName = (String)request.getAttribute("name");  6     Date refDate = (Date)request.getAttribute("date");7 %>8 <h1>姓名:<%=refName%></h1>9 <h1>日期:<%=refDate%></h1>
复制代码

运行结果:

 

  requestScopeDemo04.jsp页面显示的结果是null。这说明了在requestScopeDemo01.jsp这个页面设置的属性经过超链接这种客户端跳转到别的页面时别的页面是无法取得requestScopeDemo01.jsp中设置的属性的。

  如果还想进一步扩大属性范围,则可以使用session范围属性

 3.3、session属性范围

  session设置的属性不管如何跳转,都可以取得的。当然,session只针对一个用户

  

  在第一个页面上设置的属性,跳转(服务器跳转/客户端跳转)到其他页面之后,其他的页面依然可以取得第一个页面上设置的属性。

下面通过代码来观察session属性范围

范例:sessionScopeDemo01.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     //此时设置的属性只能够在与本页相关的任何页面中取得5     session.setAttribute("name","孤傲苍狼");  //设置属性6     session.setAttribute("date",new Date());7 %>8 <%--使用服务器端跳转--%>9 <jsp:forward page="/sessionScopeDemo02.jsp"/>
复制代码

  这里使用的是服务器端跳转

sessionScopeDemo02.jsp

复制代码
 1 <%@page contentType="text/html;charset=UTF-8"%> 2 <%@page import="java.util.*"%> 3 <% 4     String refName = (String)session.getAttribute("name"); 5     Date refDate = (Date)session.getAttribute("date"); 6 %> 7 <h1>姓名:<%=refName%></h1> 8 <h1>日期:<%=refDate%></h1> 9 <%--使用超链接这种客户端跳转--%>10 <h1><a href="${pageContext.request.contextPath}/sessionScopeDemo03.jsp">sessionScopeDemo03</a></h1>
复制代码

  这里使用的是超链接这种客户端跳转

  运行程序sessionScopeDemo01.jsp结果如下所示:

  

sessionScopeDemo03.jsp

复制代码
1 <%@page contentType="text/html;charset=UTF-8"%>2 <%@page import="java.util.*"%>3 <%4     String refName = (String)session.getAttribute("name");5     Date refDate = (Date)session.getAttribute("date");6 %>7 <h1>姓名:<%=refName%></h1>8 <h1>日期:<%=refDate%></h1>
复制代码

  点击超链接sessionScopeDemo03,跳转到了sessionScopeDemo03.jsp这个页面,此时程序的运行结果如下:

  

  这说明了即使是采用客户端跳转,在别的页面依然可以取得第一个页面中设置的session属性。但是,如果,此时新开了一个浏览器,则sessionScopeDemo03.jsp肯定无法取得sessionScopeDemo01.jsp中设置的session对象的属性,因为session只是保留了一个人的信息。

  如果一个属性想让所有的用户都可以访问,则可以使用最后一种属性范围:application范围。

3.4application属性范围

  

  因为application属性范围是在服务器上设置的一个属性,所以一旦设置之后任何用户都可以浏览到此属性。

下面通过代码来观察application属性范围

范例:applicationScopeDemo01.jsp

复制代码
1 <%@ page contentType="text/html;charset=GBK"%>2 <%@ page import="java.util.*"%>3 <%4     //此时设置的属性任何用户都可以取得5     application.setAttribute("name","孤傲苍狼");  //设置属性6     application.setAttribute("date",new Date());7 %>8 <h1><a href="${pageContext.request.contextPath}/applicationScopeDemo02.jsp">applicationScopeDemo02</a></h1>
复制代码

范例:applicationScopeDemo02.jsp

复制代码
1 <%@ page contentType="text/html;charset=GBK"%>2 <%@ page import="java.util.*"%>3 <%4     String refName = (String)application.getAttribute("name");5     Date refDate = (Date)application.getAttribute("date");6 %>7 <h1>姓名:<%=refName%></h1>8 <h1>日期:<%=refDate%></h1>
复制代码

观察页面的运行效果:

  

  开启多个浏览器窗口,运行applicationScopeDemo02.jsp时,都可以显示出上图所示的结果,因为属性范围设置在了服务器中,所以只要是连接到此服务器的任意用户都可以取得此属性,当然,如果服务器关闭的话,则此属性肯定消失。

  如把Tomcat服务器先关闭后再重新启动,打开浏览器窗口运行applicationScopeDemo02.jsp时,得到的结果如下图所示:

  

  注意:如果在服务器上设置了过多的application属性,则会影响到服务器的性能。

3.5、关于pageContext属性范围的进一步补充

  之前所讲解的四种属性范围,实际上都是通过pageContext属性范围设置上的。打开pageContext所在的说明文档。

  

  PageContext类继承了JspContext类,在JspContext类中定义了setAttribute方法,如下:

         public abstract void setAttribute(String name,Object value,int scope) 

   此方法中存在一个scope的整型变量,此变量就表示一个属性的保存范围。

  

  PageContext类继承了JspContext类,所以在PageContext类中实现了抽象的setAttribute方法:

1 public abstract void setAttribute(String name,Object value,int scope)

  这个setAttribute()方法如果不写后面的int类型的scope参数,则此参数默认为PAGE_SCOPE,则此时setAttribute()方法设置的就是page属性范围,如果传递过来的int类型参数scopeREQUEST_SCOPE,则此时setAttribute()方法设置的就是request属性范围,同理,传递的scope参数为SESSION_SCOPEAPPLICATION_SCOPE时,则表示setAttribute()方法设置的就是session属性范围和application属性范围。

下面通过代码来观察此四种属性范围常量的作用,以:request为例

范例:pageScopeDemo04.jsp

复制代码
1 <%@page contentType="text/html;charset=GBK"%>2 <%@page import="java.util.*"%>3 <%4     pageContext.setAttribute("name","孤傲苍狼",PageContext.REQUEST_SCOPE);  //设置属性,并指明属性范围5     pageContext.setAttribute("date",new Date(),PageContext.REQUEST_SCOPE); //设置属性,并指明属性范围6 %>7 <jsp:forward page="/pageScopeDemo05.jsp"/>
复制代码

pageScopeDemo05.jsp

复制代码
 1 <%@page contentType="text/html;charset=GBK"%> 2 <%@page import="java.util.*"%> 3 <% 4     //使用request对象获取属性 5     String refName = (String)request.getAttribute("name"); 6     Date refDate = (Date)request.getAttribute("date"); 7     //也可以使用pageContext对象获取属性,只要在获取时指明对象的属性范围即可 8     String refName2 = (String)pageContext.getAttribute("name", PageContext.REQUEST_SCOPE); 9     Date refDate2 = (Date)pageContext.getAttribute("date", PageContext.REQUEST_SCOPE);10 %>11 使用request对象获取属性:12 <h1>姓名:<%=refName%></h1>13 <h1>日期:<%=refDate%></h1>14 使用pageContext对象获取属性:15 <h1>姓名:<%=refName2%></h1>16 <h1>日期:<%=refDate2%></h1>
复制代码

运行结果:

  

  从运行结果可以看到:在pageScopeDemo04.jsp使用的是pageContext对象调用setAttribute()方法设置的属性范围是request的属性范围,因此在调用此方法时,把一个int类型的scope范围常量REQUEST_SCOPE传递了进来,这个REQUEST_SCOPE属性范围常量的作用就是告诉pageContext对象现在要设置的属性范围是request的属性范围,所以pageScopeDemo05.jsp这个页面中可以直接使用request.getAttribute();方法获取在pageScopeDemo04.jsp设置的属性。

四、jsp四种属性范围的使用场合

  1、request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的。
  2、session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐。
  3、application(servletContext):如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在application(servletContext)域中,像聊天数据。

javaweb学习总结(十九)——JSP标签

一、JSP标签介绍

  JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。

二、JSP常用标签

  jsp的常用标签有以下三个

  • <jsp:include>标签  
  • <jsp:forward>标签  
  • <jsp:param>标签

2.1、<jsp:include>标签 

  <jsp:include>标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:
    <jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
  page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
  flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。 

范例:使用jsp:include标签引入资源

复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <html> 4   <head> 5     <title>jsp的jsp:include标签测试</title> 6   </head> 7  8   <body> 9   <%--使用jsp:include标签引入其它JSP页面--%>10   <jsp:include page="/jspfragments/head.jsp"/>11     <h1>网页主体内容</h1>12     <jsp:include page="/jspfragments/foot.jsp"/>13   </body>14 </html>
复制代码

运行结果:

  

2.2、<jsp:include>标签与include指令的区别

  <jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。 
  而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。

  通过下面的例子来说明<jsp:include>标签与include指令的区别

demo.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <%!3     int i=1000;4 %>5 <h1>demo.jsp中i的值为:<%=i%></h1>

分别使用include指令和<jsp:include>标签两种包含语句,包含以上的demo.jsp

范例:使用@include包含内容

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <%!3     int i=10;4 %>5 <h1>JspIncludeTagDemo01.jsp中i的值为:<%=i%></h1>6 <h1><%@include file="/jspfragments/demo.jsp"%></h1>

此时在编译jsp时就已经提示出错了,如下所示:

  

  这个错误说的是变量i已经重复定义了

  运行JspIncludeTagDemo01.jsp,结果如下:

  

  运行后发现出现了重复定义变量i的错误提示信息,因为静态包含是将全部内容包含进来之后,再进行处理,属于先包含后处理。由于被包含进来的页面demo.jsp中定义了一个变量i,而包含页面JspIncludeTagDemo01.jsp本身又定义了一个变量i,所以服务器在处理JspIncludeTagDemo01.jsp这个页面时就会发现里面有两个重复定义的变量i,因此就会报错。

而如果现在使用的是<jsp:include>动态包含的话,观察以下程序:

范例:使用动态包含

复制代码
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1>JspIncludeTagDemo02.jsp</h1>3 <%!4     int i=10;5 %>6 7 <h1>JspIncludeTagDemo02.jsp中i的值为:<%=i%></h1>8 <h1><jsp:include page="/jspfragments/demo.jsp" /></h1>
复制代码

运行结果:

  

  发现结果已经可以正确地显示,而且不会互相影响,这是因为使用jsp:include属于动态包含,动态包含就是指先将各个页面分别处理,处理完之后再将处理后的结果包含进来。
  不管是<jsp:include>标签,还是include指令,它们都会把两个JSP页面内容合并输出,所以这两个页面不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。

2.3、*.jspf扩展名文件在jsp:include、@include和c:import中的区别

  JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。今天无意中发现,把一个JSP文件命名为jspf扩展名,然后include到另一个jsp文件中的,发现只有用"@include"指令的时候,jspf文件的内容才会被解析并执行其中的jsp指令和tag,而使用"jsp:include"和JSTL的"c:import"都没有用,jspf文件被当作纯文本文件处理了。

比如现在有一个head.jspf页面和foot.jspf页面

head.jspf

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1 style="color:red;">网页头部</h1>

foot.jspf

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1 style="color:blue;">网页尾部</h1>

首先使用"@include"指令将"head.jspffoot.jspf" include到IncludeTagTest.jsp页面,如下所示:

复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <html> 4   <head> 5     <title>jsp的Include指令测试</title> 6   </head> 7  8   <body> 9    <%--使用include标签引入引入jspf页面--%>10     <%@include file="/jspfragments/head.jspf" %>11     <h1>网页主体内容</h1>12     <%@include file="/jspfragments/foot.jspf" %>13   </body>14 </html>
复制代码

  运行IncludeTagTest.jsp页面,运行结果如下:

  

  jspf文件的内容会被解析并执行其中的jsp指令和tag,查看浏览器解析JspIncludeTagTest.jsp页面生成的源代码,如下所示:

  

  然后再使用<jsp:include>"标签将"head.jspffoot.jspf" include到JspIncludeTagTest.jsp页面中,如下所示:

复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <html> 4   <head> 5     <title>jsp的jsp:include标签测试</title> 6   </head> 7  8   <body> 9   <%--使用jsp:include标签引入其它JSPf页面--%>10   <jsp:include page="/jspfragments/head.jspf"/>11     <h1>网页主体内容</h1>12     <jsp:include page="/jspfragments/foot.jspf"/>13   </body>14 </html>
复制代码

运行JspIncludeTagTest.jsp页面,运行结果如下:

  

  查看浏览器解析JspIncludeTagTest.jsp页面生成的源代码,如下所示:

  

  可以看到,head.jspffoot.jspf中的<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>没有解析执行,而是原封不动地作为文本内容输出到页面上了,在IE下看不到<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>的输出,在google和火狐浏览器下运行可以看到页面上输出<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>,如下所示:

  

  这说明jspf文件Tomcat服务器被当作纯文本文件处理了,没有当作jsp页面来解析执行,那么该如何解决这个问题呢?如何让tomcat服务器能够解析执行*.jspf文件中的java代码和标签呢,有如下的几种解决办法:

解决办法一:修改web.xml文件,添加对扩展名为*.jspf文件的映射

如下所示:

复制代码
 1     <!-- 让jspf扩展名同样成为JSP Servlet处理的文件。 --> 2     <servlet-mapping> 3         <servlet-name>jsp</servlet-name> 4         <url-pattern>*.jspf</url-pattern> 5     </servlet-mapping> 6     <!-- 让jsp扩展名同样成为JSP Servlet处理的文件。 --> 7     <servlet-mapping> 8         <servlet-name>jsp</servlet-name> 9         <url-pattern>*.jsp</url-pattern>10     </servlet-mapping>
复制代码

  上面的配置方式也可以简写成这样:

1     <servlet-mapping>2         <servlet-name>jsp</servlet-name>3         <url-pattern>*.jsp</url-pattern>4         <!-- 让jspf扩展名同样成为JSP Servlet处理的文件。-->5         <url-pattern>*.jspf</url-pattern>6     </servlet-mapping>

  两种写法的效果都是一样的。

添加这样的配置信息后,此时tomcat服务器就可以正常解析执行*.jspf文件了,如下所示:

  

解决办法二:修改Tomcat服务器的web.xml文件,添加对扩展名为*.jspf文件的映射

找到tomcat服务器的web.xml文件,如下所示:

  

找到名字为jsp的那个Servlet,如下所示:

复制代码
 1 <servlet> 2         <servlet-name>jsp</servlet-name> 3         <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> 4         <init-param> 5             <param-name>fork</param-name> 6             <param-value>false</param-value> 7         </init-param> 8         <init-param> 9             <param-name>xpoweredBy</param-name>10             <param-value>false</param-value>11         </init-param>12         <load-on-startup>3</load-on-startup>13 </servlet>
复制代码

然后根据Servlet名找到对应的servlet-mapping配置,如下所示:

1     <!-- The mappings for the JSP servlet -->2     <servlet-mapping>3         <servlet-name>jsp</servlet-name>4         <url-pattern>*.jsp</url-pattern>5         <url-pattern>*.jspx</url-pattern>6     </servlet-mapping>

在这里可以看到,名字为jsp的那个Servlet只支持*.jsp和*.jspx两种扩展名,因此可以在这个地方添加多一个<url-pattern>*.jspf</url-pattern>,如下所示:

复制代码
1     <!-- The mappings for the JSP servlet -->2     <servlet-mapping>3         <servlet-name>jsp</servlet-name>4         <url-pattern>*.jsp</url-pattern>5         <url-pattern>*.jspx</url-pattern>6         <url-pattern>*.jspf</url-pattern>7     </servlet-mapping>
复制代码

  经过这样的配置之后,Tomcat服务器就可以正常解析和执行*.jspf文件了。

2.3、<jsp:forward>标签

  <jsp:forward>标签用于把请求转发给另外一个资源。
  语法:
      <jsp:forward page="relativeURL | <%=expression%>" /> 
  page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。

范例:使用<jsp:forward>标签跳转页面

forwarddemo01.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <%--使用<jsp:forward>标签跳转到forwarddemo02.jsp--%>3 <jsp:forward page="/forwarddemo02.jsp"/>

forwarddemo02.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1>跳转之后的页面!!</h1>

运行结果如下:

  

  从页面的显示效果来看,页面已经完成了跳转,但地址栏没有变化,地址栏中显示的地址还是forwarddemo01.jsp,但页面显示的内容却是forwardemo02.jsp中的内容。因为此跳转属于服务器端跳转。只要是服务器端跳转,则地址栏永远没有变化。

2.4、<jsp:param>标签

  当使用<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:include>
  <jsp:param>标签的name属性用于指定参数名,value属性用于指定参数值。在<jsp:include>和<jsp:forward>标签中可以使用多个<jsp:param>标签来传递多个参数。

范例:使用<jsp:param>标签向被包含的页面传递参数

JspIncludeTagDemo03.jsp

复制代码
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1>JspIncludeTagDemo03.jsp</h1>3 <hr/>4 <jsp:include page="/jspfragments/Inc.jsp">5     <jsp:param name="parm1" value="hello" />6     <jsp:param name="parm2" value="gacl" />7 </jsp:include>
复制代码

Inc.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1>接收从JspIncludeTagDemo03.jsp页面中传递过来的参数:</h1>3 <h2><%=request.getParameter("parm1")%></h2>4 <h2><%=request.getParameter("parm2")%></h2>

  在JspIncludeTagDemo03.jsp页面中使用<jsp:include>标签将Inc.jsp页面包含进来,使用<jsp:param/>标签向Inc.jsp页面传递了两个参数parm1和parm2

  JspIncludeTagDemo03.jsp页面运行结果如下:

  

 范例:使用<jsp:param>标签向要跳转的页面传递参数

forwarddemo03.jsp

复制代码
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <%--使用<jsp:forward>标签跳转到forwarddemo04.jsp--%>3 <%--使用<jsp:param>标签向forwarddemo04.jsp传递参数--%>4 <jsp:forward page="/forwarddemo04.jsp">5     <jsp:param name="ref1" value="hello" />6     <jsp:param name="ref2" value="gacl" />7 </jsp:forward>
复制代码

forwarddemo04.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>2 <h1>跳转之后的页面!!</h1>3 <h1>接收从forwarddemo03.jsp传递过来的参数:</h1>4 <h1>ref1:<%=request.getParameter("ref1")%></h1>5 <h1>ref2:<%=request.getParameter("ref2")%></h1>

运行结果如下:

  


0 0
原创粉丝点击