780 likes | 932 Views
张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕. JSP 入门 JSP 基本语法 JSP 指令 out 对象 pageContext 对象 JSP 标签 JSP 的中文乱码问题. 第 8 讲 JSP. 建立对 JSP 的直观认识 JSP 的运行原理 分析 JSP 所生成的 Servlet 代码 JSP 隐式对象 注册与配置 jsp 页面的访问路径 JSP 与 JavaScript 的综合应用 JSP 与 Servlet 的应用比较. JSP 入门. JSP 起源.
E N D
张孝祥IT课堂-深入体验Java Web开发内幕 IT资讯交流网 WWW.IT315.ORG
JSP入门 JSP基本语法 JSP指令 out对象 pageContext对象 JSP标签 JSP的中文乱码问题 第8讲 JSP IT资讯交流网 WWW.IT315.ORG
建立对JSP的直观认识 JSP的运行原理 分析JSP所生成的Servlet代码 JSP隐式对象 注册与配置jsp页面的访问路径 JSP与JavaScript的综合应用 JSP与Servlet的应用比较 JSP入门 IT资讯交流网 WWW.IT315.ORG
JSP起源 • 在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。 • 如果使用Servlet程序来输出只有局部内容需要动态改变的网页,其中所有的静态内容也需要程序员用Java程序代码产生,整个Servlet程序的代码将非常臃肿,编写和维护都将非常困难。 • 对大量静态内容的美工设计和相关HTML语句的编写,并不是程序员所要做的工作,程序员对此也不一定在行。网页美工设计和制作人员不懂Java编程,更是无法来完成这样的工作。 • 为了弥补Servlet的缺陷,SUN公司在Servlet的基础上推出了JSP(Java Server Pages)技术作为解决方案。 • JSP是简化Servlet编写的一种技术,它将Java代码和HTML语句混合在同一个文件中编写,只对网页中的要动态产生的内容采用Java代码来编写,而对固定不变的静态内容采用普通静态HTML页面的方式编写。 IT资讯交流网 WWW.IT315.ORG
建立对JSP的直观认识 • JSP页面是由HTML语句和嵌套在其中的Java代码组成的一个普通文本文件,JSP 页面的文件扩展名必须为.jsp。 • 在JSP页面中编写的Java代码需要嵌套在<%和%>中,嵌套在<%和%>之间的Java代码被称之为脚本片段(Scriptlets),没有嵌套在<%和%>之间的内容被称之为JSP的模版元素。 • JSP中的Java代码可以使用out.println语句将其他Java程序代码产生的结果字符串输出给客户端,也可以使用System.out.println语句将它们打印到命令行窗口。 • JSP文件就像普通的HTML文件一样,它们可以放置在WEB应用程序中的除了WEB-INF及其子目录外的其他任何目录中,JSP页面的访问路径与普通HTML页面的访问路径形式也完全一样。 • 在JSP页面中也可以使用一种称之为JSP表达式的元素,只需将要输出的变量或表达式直接封装在<%= 和 %>之中,就可以向客户端输出这个变量或表达式的运算结果。在JSP表达式中嵌套的变量或表达式后面不能有分号。 动手体验:了解JSP程序的基本应用 IT资讯交流网 WWW.IT315.ORG
JSP的运行原理 • WEB容器(Servlet引擎)接收到以.jsp为扩展名的URL的访问请求时,它将把该访问请求交给JSP引擎去处理。Tomcat中的JSP引擎就是一个Servlet程序,它负责解释和执行JSP页面。 • 每个JSP 页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器(Servlet引擎)像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。 • Tomcat 5.x把为JSP页面创建的Servlet源文件和class类文件放置在“<TOMCAT_HOME>\work\Catalina\<主机名>\<应用程序名>\”目录中,Tomcat将JSP页面翻译成的Servlet的包名为org.apache.jsp.<JSP页面在WEB应用程序内的目录名> 。 • JSP规范也没有明确要求JSP中的脚本程序代码必须采用Java语言,JSP中的脚本程序代码可以采用Java语言之外的其他脚本语言来编写,但是,JSP页面最终必须转换成Java Servlet程序。 • 可以在WEB应用程序正式发布之前,将其中的所有JSP页面预先编译成Servlet程序。 多学两招:让JSP引擎不检测JSP页面是否发生修改 IT资讯交流网 WWW.IT315.ORG
分析JSP所生成的Servlet代码 • JSP页面翻译成的Servlet继承了org.apache.jasper.runtime.HttpJspBase类,HttpJspBase类是HttpServlet的一个子类,因此JSP页面翻译成的Servlet是HttpServlet的一个孙子类。HttpJspBase类实现了javax.servlet.jsp.HttpJspPage接口中的部分方法,因此,HttpJspBase类是抽象的。 • SUN公司为JSP的WEB容器开发商和JSP页面开发人员提供了一套专门应用于开发JSP程序的Java类,这套Java类被称为JSP API。HttpJspPage接口和JspPage接口属于JSP API,在HttpJspPage接口中只定义了一个_jspService方法,但它继承了JspPage接口,JspPage接口中定义了两个方法:jspInit()和jspDestroy()。 • HttpJspBase的init方法调用了jspInit和_jspInit方法,destroy方法内部调用了jspDestroy和_jspDestroy方法,service方法内部调用了_jspService方法。在HttpJspBase中实现的init、service和destroy方法都被声明成了final类型。 • JSP页面中的位于<% %>外面的每行和紧临<%%>两边的每段文本被转换成以这些文本作为参数的一条条out.write语句,JSP脚本片断(位于<%%>内的一段java代码)中的java代码被原封不动地搬移进了_jspService方法中的相应位置处,JSP表达式(位于<%=和%>之中的内容)则是被转换成以其中的变量或表达式作为参数的out.print语句。 指点迷津:out.print语句与out.write语句的区别 IT资讯交流网 WWW.IT315.ORG
public void _jspService(HttpServletRequest request, HttpServletResponseresponse) throws java.io.IOException, ServletException { JspFactory _jspxFactory = null; PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config= null; JspWriter out = null; Object page = this; ... ... Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request); if (exception != null) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } JSP隐式对象 IT资讯交流网 WWW.IT315.ORG
JSP隐式对象应用 多学两招:使用JSP页面学习Servlet API IT资讯交流网 WWW.IT315.ORG
<servlet> <servlet-name>SimpleJspServlet</servlet-name> <jsp-file>/jsp/simple.jsp</jsp-file> <load-on-startup>1</load-on-startup > </servlet> …… <servlet-mapping> <servlet-name>SimpleJspServlet</servlet-name> <url-pattern>/xxx/yyy.html</url-pattern> </servlet-mapping> 注册与配置JSP页面的访问路径 IT资讯交流网 WWW.IT315.ORG
JSP与JavaScript的综合应用 • JavaScript是由浏览器解释执行的程序代码,它是网页内容的一部分,主要用于在网页上产生动态的显示效果和实现与用户的交互功能。 • JSP程序则是由WEB服务器解释执行的程序代码,它用于产生供浏览器显示的网页内容。 • 由于JavaScript代码属于网页的内容部分,所以,JavaScript代码也可以通过JSP页面输出。 • JavaScript和JSP的关系犹如HTML代码和JSP的关系,即JavaScript代码是JSP程序输出的一段可以被浏览器解释执行的特殊文本内容。 动手体验:JSP与JavaScript的应用关系 IT资讯交流网 WWW.IT315.ORG
JSP与JavaScript的应用关系图例 IT资讯交流网 WWW.IT315.ORG
<script language="javascript"> function checkAll() { var count = document.mailForm.mail.length; for(var i=0; i<count; i++) { document.mailForm.mail[i].checked = document.mailForm.ifAll.checked; } } </script> <form name="mailForm"> <input type="checkbox" name="mail" value="1">邮件1<br> <input type="checkbox" name="mail" value="2">邮件2<br> <input type="checkbox" name="mail" value="3">邮件3<br> <input type="checkbox" name="ifAll" onclick="checkAll()">全选 </form> “全选”的JavaScript代码 IT资讯交流网 WWW.IT315.ORG
“全选”的JavaScript代码问题与解决 • 如果收件夹中连一封邮件都没有,那么将不会出现名称为“mail”的复选框,对这种情况可以用下面的任何一条语句进行判断: • if(document.mailForm.mail == null) • if(!document.mailForm.mail) • if(typeof(document.mailForm.mail) == "undefined") • 如果收件夹中只有一封邮件,那么将只会出现一个名称为“mail”的复选框,这可以在排除连一封邮件都没有的程序代码的基础上,使用下面的任何一条语句进行判断: • if(document.mailForm.mail.length == null) • if(!document.mailForm.mail.length) • if(typeof(document.mailForm.mail.length) == "undefined") IT资讯交流网 WWW.IT315.ORG
“全选”的完整JavaScript代码 <script language="javascript"> function checkAll() { //如果邮箱中存在邮件 if(document.mailForm.mail != null) { //如果邮箱中有多封邮件 if(document.mailForm.mail.length != null) { var count = document.mailForm.mail.length; for(var i=0; i<count; i++) { document.mailForm.mail[i].checked = document.mailForm.ifAll.checked; } } else //如果邮箱中只有一封邮件 { document.mailForm.mail.checked = document.mailForm.ifAll.checked; } } } </script> IT资讯交流网 WWW.IT315.ORG
“全选”的完整JavaScript代码改进 <script language="javascript"> function checkAll() { //如果邮箱中不存在邮件,就直接返回。 if(document.mailForm.mail == null) { return; } /*如果邮箱中存在一封或多封邮件,程序的执行流程才会到达下面的部 分。下面的if条件判断邮箱中只有一封邮件的情况。*/ if(document.mailForm.mail.length == null) { document.mailForm.mail.checked = document.mailForm.ifAll.checked; return; } //下面的代码用于处理邮箱中有多封邮件的情况 var count = document.mailForm.mail.length; for(var i=0; i<count; i++) { document.mailForm.mail[i].checked = document.mailForm.ifAll.checked; } } </script> IT资讯交流网 WWW.IT315.ORG
降低代码的嵌套层次,提高程序的易阅读性(1) fuction x() { if(...) { 111... } else { 222... } } fuction x() { if(...) { 111... return; } //在这里可以先歇一会了,然后再继续考虑下面的代码 222... } IT资讯交流网 WWW.IT315.ORG
降低代码的嵌套层次,提高程序的易阅读性(2) fuction x() { if(!...) { return; } //原来位于里层的if语句可以直接在下面编写了。 if(...) { 111... } else { 222... } } fuction x() { if(...) { if(...) { 111... } else { 222... } } } IT资讯交流网 WWW.IT315.ORG
Web邮件列表的模拟程序 <%! //定义一个方法读取并返回文本文件中的每行数据 Vector getMails(ServletContext application) throws Exception { //要注意mails.txt文件的位置 InputStream ips = application.getResourceAsStream("/mails.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(ips)); Vector vMails = new Vector(); String mail = br.readLine(); while(mail != null) { vMails.add(mail); mail = br.readLine(); } br.close(); return vMails; } %> <form name="mailForm"> <% //调用getMails()方法,读取文本文件中的数据并输出给客户端 Vector v = getMails(application); for(Enumeration e = v.elements();e.hasMoreElements();) { String mail = (String)e.nextElement(); out.println("<input type ='checkbox' name='mail'>" + mail + "<br>"); } %> <input type="checkbox" name="ifAll" onclick="checkAll()">全选 </form> IT资讯交流网 WWW.IT315.ORG
JSP与Servlet的应用比较 • JSP是一种以产生网页显示内容为中心的WEB开发技术,它可以直接使用模版元素来产生网页文档的内容。 • JSP页面的源文件要比Servlet源文件简单,并且JSP页面的开发过程要比Servlet的开发过程简单得多。 Session技术是一种将会话状态保存在服务器端的技术 ,它可以比喻成是医院发放给病人的病历卡和医院为每个病人保留的病历档案的结合方式。 • JSP引擎可以对JSP页面的修改进行检测,并自动重新翻译和编译修改过的JSP文件。 • 在JSP中使用JavaBean和自定义标签,可以分离用于表现外观的HTML文本内容和用于处理业务逻辑的Java代码。 • JSP技术是建立在Servlet技术基础之上的,所有的JSP页面最终都要被转换成Servlet来运行,要想深入掌握JSP,必须先对Servlet有比较充分的理解。 • 在大型WEB应用程序的开发中,Servlet与JSP经常要混合使用,各司其职,Servlet通常用作控制组件,并处理一些复杂的后台业务,JSP则作为显示组件。 • 一次响应过程可以划分成几个功能模块来协同完成,首先由Servlet完成流程控制和业务处理,并将结果数据存储在request或session域中,然后将请求转发(forward)到JSP页面,再由JSP页面从request或session域中取出结果数据并完成响应内容的输出。通过这种方式实现业务逻辑与显示内容的分离,从而将应用程序开发者和网页作者的工作分离。 IT资讯交流网 WWW.IT315.ORG
JSP基本语法 • JSP模版元素 • JSP表达式 • JSP脚本片断 • EL表达式 • JSP注释 • 特殊字符序列的转义处理 • 如何查找JSP页面中的错误 IT资讯交流网 WWW.IT315.ORG
JSP模版元素 • JSP页面中的静态HTML内容称之为JSP模版元素,在静态的HTML内容之中可以嵌套JSP的其他各种元素来产生动态内容和执行业务逻辑。 • JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。 IT资讯交流网 WWW.IT315.ORG
JSP表达式 • JSP表达式(expression)提供了将一个java变量或表达式的计算结果输出到客户端的简化方式,它将要输出的变量或表达式直接封装在<%= 和 %>之中。 举例:Current time: <%= new java.util.Date() %> • JSP表达式中的变量或表达式的计算结果将被转换成一个字符串,然后被插入进整个JSP页面输出结果的相应位置处。 • JSP表达式中的变量或表达式后面不能有分号(;),JSP表达式被翻译成Servlet程序中的一条out.print(…)语句。 IT资讯交流网 WWW.IT315.ORG
JSP脚本片断(1) • JSP脚本片断(scriptlet)是指嵌套在<% 和 %>之中的一条或多条Java程序代码。 • 在JSP脚本片断中,可以定义变量、执行基本的程序运算、调用其他Java类、访问数据库、访问文件系统等普通Java程序所能实现的功能。 • 在JSP脚本片断可以直接使用JSP提供的隐式对象来完成WEB应用程序特有的功能。 • JSP脚本片断中的Java代码将被原封不动地搬移进由JSP页面所翻译成的Servlet的_jspService方法中,所以,JSP脚本片断之中只能是符合Java语法要求的程序代码,除此之外的任何文本、HTML标记、其他JSP元素都必须在脚本片断之外编写。 • JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每条命令执行语句后面必须用分号(;)结束。 • 在一个JSP页面中可以有多个脚本片断(每个脚本片断代码嵌套在各自独立的一对<% 和 %>之间),在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。 IT资讯交流网 WWW.IT315.ORG
JSP脚本片断(2) • 在一个JSP页面中可以有多个脚本片断(每个脚本片断代码嵌套在各自独立的一对<% 和 %>之间),在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。 举例: <% int x = 3; %> <p>这是一个HTML段落</p> <% out.println(x); %> • 多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。 举例:上面的JSP内容与下面的JSP内容具有同样的运行效果 <p>这是一个HTML段落</p> <% int x = 3; out.println(x); %> IT资讯交流网 WWW.IT315.ORG
JSP脚本片断(3) • 单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例如,涉及条件和循环处理时,多个脚本片断及其他元素组合的结果必须能形成完整的条件和循环控制语句。 • 由于脚本片断中的Java代码将被原封不动地搬移进由JSP页面所翻译成的Servlet的_jspService方法中,脚本片断之外的任何文本、HTML标记以及其他JSP元素也都会被转换成相应的Java程序代码插入进_jspService方法中,且脚本片断和其他JSP元素的插入位置与它们在JSP页面中的原始位置相对应。 • 在脚本片断中可以使用条件、循环、选择等流程控制语句来创建其周围的其他元素的执行逻辑,因此,在编写JSP页面时应考虑各个元素之间的先后顺序和相互关系,特别是将循环、条件判断等语句分布在若干个脚本片断中编写时对其邻近的其他JSP元素产生的影响。 • 举例1: for (int i=1; i<5; i++) { out.write("\r\n"); out.write("\t<H"); out.print(i); out.write(">www.it315.org</H"); out.print(i); out.write(">\r\n"); } <%for (int i=1; i<5; i++) {%> <H<%=i%>>www.it315.org</H<%=i%>> <%}%> • 举例2: <%if(java条件表达式){%> 其他元素 <%}else{%> 其他元素 <%}%> IT资讯交流网 WWW.IT315.ORG
JSP声明 • 如果希望在JSP页面中为其转换成的Servlet定义成员变量和方法,那该怎么做呢? • JSP声明将Java代码封装在<%!和 %>之中,它里面的代码将被插入进Servlet的_jspService方法的外面,所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法 。 • 多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。 • JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。 • JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每条命令执行语句后面必须用分号(;)结束。 • 在一个JSP页面中可以有多个脚本片断(每个脚本片断代码嵌套在各自独立的一对<% 和 %>之间),在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。 IT资讯交流网 WWW.IT315.ORG
JSP声明实例 <%! static { System.out.println("loading Servlet!"); } private int globalVar = 0; public void jspInit() { System.out.println("initializing jsp!"); } %> <%! public void jspDestroy() { System.out.println("destroying jsp!"); } %> <% int localVar = 0; %> globalVar:<%= ++globalVar %><br> localVar:<%= ++localVar %> IT资讯交流网 WWW.IT315.ORG
EL表达式 • EL(Expression Language)表达式语言是JSP 2.0中新增加的一种可简化JSP开发的技术,它可以非常方便地访问JSP页面相关的数据和支持基本的算术、关系和逻辑运算。 • EL表达式的基本语法格式为“${表达式}”。 • 可以出现在JSP自定义标签和标准标签的属性值中,其计算结果将作为标签的属性值或属性值的一部分。 • EL表达式也可以出现在模版元素中,其计算结果将插入进当前的输出流中。 IT资讯交流网 WWW.IT315.ORG
EL表达式与JSP脚本表达式的比较(1) • 使用EL表达式可以非常方便地访问JSP页面相关的数据。 • 访问请求参数 JSP表达式:<%= reqeust.getParameter("user") %> EL表达式:${param.user} • 访问JavaBean及其中的嵌套属性 JSP表达式:<%CustomerBean custormBean = (CustomerBean)pageContext.findAttribute( "customerBean");%> <%= customerBean.getAddress().getCountry()%> EL表达式:${customerBean.address.country} • 在EL表达式中还可以直接使用${cookie.user}来访问名称为user的Cookie信息,在JSP脚本表达式中却无法实现这样的功能,虽然使用JSP脚本片断也可以实现这个功能,但是其程序代码却比较复杂。 IT资讯交流网 WWW.IT315.ORG
EL表达式与JSP脚本表达式的比较(2) • 如果表达式的计算结果为null,JSP脚本表达式将输出内容为“null”的字符文本,而EL表达式会将它强制转换成空字符串("")后再输出,而不是显示为“null”,这样的处理结果非常有用。 <form method="post"> user:<input type="text" name="user"><br> <input type="submit" value="register"> </form> <form method="post"> user:<input type="text" name="user" value="<%= request.getParameter("user") %>"> <br> <input type="submit" value="register"> </form> <form method="post"> user:<input type="text" name="user" value="${param.user}"> <br> <input type="submit" value="register"> </form> 动手体验:EL表达式将null输出为空字符串("")的好处 IT资讯交流网 WWW.IT315.ORG
EL表达式与JSP脚本表达式的比较(3) • 在EL表达式中还可以使用empty操作符来判断一个参数是否为null、某个集合或字符串中的内容是否为空。 • EL表达式还具有JavaScript等脚本语言的优点,能够对字符串、数字等各种类型的数据进行自动转换,摆脱了Java语言严格的数据类型限制,使得应用起来更加简单。 • EL表达式仅仅是专门为网页作者量身定做的一种数据访问语言,可以方便地访问和处理应用程序数据,但是它并不一种程序设计语言,不能替代Java语言的强大功能。 IT资讯交流网 WWW.IT315.ORG
JSP注释 • JSP注释的格式: <%-- 注释信息 --%> • JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。 动手体验: JSP注释与JSP页面中的Java注释和HTML注释的区别 总结: • 在JSP引擎看来,出现在JSP脚本元素中的Java注释属于Java代码的一部分,它们将被原封不动地插入进Servlet源文件中,但在Servlet源文件被编译成class文件时由Java编译程序忽略。 • 在JSP引擎看来,JSP页面中的HTML注释就是一段文本,其处理方式与普通的文本内容完全一样,都被转换成out.write语句输出到客户端。 • 由于HTML注释相当于一段普通文本,其中当然可以嵌入JSP的其他各种元素,JSP引擎依然会对这些嵌套的JSP元素进行解释处理,例如: <!--This page was loaded on <%=(new java.util.Date()).toLocaleString()%>--> IT资讯交流网 WWW.IT315.ORG
特殊字符序列的转义处理(1) • 由于三种JSP脚本元素的分界符都使用到了“<%”和“%>”,如果要在JSP模版元素和JSP脚本元素内部表示字面意义的“<%”和“%>”,需要进行转义处理。 • 由于EL表达式使用“${”和“}”作为分界符,在一些应用中,也需要对它们进行转义处理。 • EL表达式内的转义 EL表达式内的任何字符序列都不需要进行转义处理,${‘${’}和${“${”}都可直接输出 ${,${‘}’}和${“}”}都可直接输出 },这就好像${‘xyz’}和${“xyz”}的输出结果都是 xyz 一样的道理。 • 脚本元素内的转义 要在脚本元素内表达字面意义上的“%>”,必须用“%\>”进行转义。JSP引擎在生成servlet源文件时,将把脚本元素内部的“%\>”转换成“%>”。因为“%\>”在脚本元素内要被转义处理,如果要表达字面意义上的“%\>”,应该使用“%\\>”。 IT资讯交流网 WWW.IT315.ORG
特殊字符序列的转义处理(2) • JSP模版元素内的转义 要在JSP模版元素内表达字面意义上的“<%”,必须用“<\%” 进行转义。要表达字面意义上的“<\%”,应该使用“<\\%”。为了让JSP引擎不要把JSP模版元素内的字符序列“${”当作EL表达式的开始,在支持EL表达式的JSP页面中,“$”可以使用“\$”来表示,但这不是必须的。如果要表达字面意义上的“${”,这时候就必须使用“\${”。如果要达字面意义上的“\$”,必须使用“\\$”。 • JSP标签的属性内的转义 • 如果使用单引号(‘)将属性值部分引起来,那么属性值中的单引号要用“\’”表示。 • 如果使用双引号(“)将属性值部分引起来,那么属性值中的双引号要用“\””表示。 • 反斜杠(\)要用“\\”表示。 • 在支持EL表达式的JSP页面中,“$”可以使用“\$”来表示。 • “<%”要用“<\%” 表示。 • “%>”要用“%\>” 表示。 IT资讯交流网 WWW.IT315.ORG
如何查找JSP页面中的错误 动手体验:查找JSP页面中的错误 总结: • JSP页面中的JSP语法格式有问题,导致其不能被翻译成Servlet源文件,JSP引擎将提示这类错误发生在JSP页面中的位置(行和列)以及相关信息。 • JSP页面中的JSP语法格式没有问题,但被翻译成的Servlet源文件中出现了Java语法问题,导致JSP页面翻译成的Servlet源文件不能通过编译,JSP引擎也将提示这类错误发生在JSP页面中的位置(行和列)以及相关信息。 • JSP页面翻译成的Servlet程序在运行时出现异常,这与普通Java程序的运行时错误完全一样,Java虚拟机将提示错误发生在Servlet源文件中的位置(行和列)以及相关信息。 IT资讯交流网 WWW.IT315.ORG
JSP指令 • JSP指令简介 • page指令 • include指令 IT资讯交流网 WWW.IT315.ORG
JSP指令简介 • JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。 • JSP指令的基本语法格式: <%@ 指令 属性名="值" %> 举例:<%@ page contentType="text/html;charset=gb2312"%> 注意:属性名部分是大小写敏感的 • 在目前的JSP 2.0中,定义了page、include和taglib这三种指令,每种指令中又都定义了一些各自的属性。 • 如果要在一个JSP页面中设置同一条指令的多个属性,可以使用多条指令语句单独设置每个属性,也可以使用同一条指令语句设置该指令的多个属性。 第一种方式: <%@ page contentType="text/html;charset=gb2312"%> <%@ page import="java.util.Date"%> 第二种方式: <%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%> IT资讯交流网 WWW.IT315.ORG
Page指令 • page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。 • JSP 2.0规范中定义的page指令的完整语法: <%@ page [ language="java" ] [ extends="package.class" ] [ import="{package.class | package.*}, ..." ] [ session="true | false" ] [ buffer="none | 8kb | sizekb" ] [ autoFlush="true | false" ] [ isThreadSafe="true | false" ] [ info="text" ] [ errorPage="relative_url" ] [ isErrorPage="true | false" ] [ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] [ pageEncoding="characterSet| ISO-8859-1" ] [ isELIgnored="true | false" ] %> • 可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号分隔: <%@ page import="java.util.Date,java.sql.*,java.io.*"%> • 上面的语句也可以改写为使用多条page指令的import属性来分别引入各个包或类: <%@ page import="java.util.Date"%> <%@ page import="java.sql.*"%> <%@ page import="java.io.*"%> JSP 引擎自动导入下面的包: • java.lang.* • javax.servlet.* • javax.servlet.jsp.* • javax.servlet.http.* • errorPage属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前页面。 • 可以在web.xml文件中使用<error-page>元素为整个WEB应用程序设置错误处理页面,其中的<exception-type>子元素指定异常类的完全限定名,<location>元素指定以“/”开头的错误处理页面的路径。 • 如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。 • JSP引擎会根据page指令的contentType属性生成相应的调用ServletResponse.setContentType方法的语句。 • page指令的contentType属性还具有说明JSP源文件的字符编码的作用。 IT资讯交流网 WWW.IT315.ORG
Page指令相关细节 动手体验:JSP页面中的异常处理 • web.xml文件中的异常错误处理: • <error-page> • <exception-type>java.lang.ArithmeticException</exception-type> • <location>/jsp/dealError2.jsp</location> • </error-page> 多学两招:如何识别web.xml所遵循的Servlet规范的版本号 IT资讯交流网 WWW.IT315.ORG
include指令 • include指令用于通知JSP引擎在翻译当前JSP页面时将其他文件中的内容合并进当前JSP页面转换成的Servlet源文件中,这种在源文件级别进行引入的方式称之为静态引入,当前JSP页面与静态引入的页面紧密结合为一个Servlet。 • 语法: <%@ include file="relativeURL"%> 其中的file属性用于指定被引入文件的相对路径。 • 细节: • 被引入的文件必须遵循JSP语法,其中的内容可以包含静态HTML、JSP脚本元素、JSP指令和JSP行为元素等普通JSP页面所具有的一切内容。 • 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。 • 在将JSP文件翻译成Servlet源文件时,JSP引擎将合并被引入的文件与当前JSP页面中的指令元素(设置pageEncoding属性的page指令除外),所以,除了import和pageEncoding属性之外,page指令的其他属性不能在这两个页面中有不同的设置值。 IT资讯交流网 WWW.IT315.ORG
include指令(续) • 细节: • 除了指令元素之外,被引入的文件中的其他元素都被转换成相应的Java源代码,然后插入进当前JSP页面所翻译成的Servlet源文件中,插入位置与include指令在当前JSP页面中的位置保持一致。 • 引入文件与被引入文件是在被JSP引擎翻译成Servlet的过程中进行合并,而不是先合并源文件后再对合并的结果进行翻译。当前JSP页面的源文件与被引入文件的源文件可以采用不同的字符集编码,即使在一个页面中使用page指令的pageEncoding或contentType属性指定了其源文件的字符集编码,在另外一个页面中还需要用page指令的pageEncoding或contentType属性指定其源文件所使用的字符集 。 • Tomcat 5.x在访问JSP页面时,可以检测它所引入的其他文件是否发生了修改,如果发生了修改,则重新编译当前JSP页面 • file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件。 IT资讯交流网 WWW.IT315.ORG
include指令(续) • 假设myweb应用程序的根目录下有一个a.jsp文件,其一般的访问路径形式为: http://localhost:8080/myweb/a.jsp 在a.jsp页面中使用了如下语句引入b.jspf文件: <%@ include file=“b.jspf”%> 请问:这时候JSP引擎调用的b.jspf文件的完整URL路径为什么? 如果将a.jsp页面映射为如下地址: http://localhost:8080/myweb/dir1/a.html 请问:这时候JSP引擎调用的b.jspf文件的完整URL路径为: http://localhost:8080/myweb/b.jspf http://localhost:8080/myweb/dir1/b.jspf (√) (×) 动手体验:了解include指令的特性 IT资讯交流网 WWW.IT315.ORG
out隐式对象 • 在JSP页面中应使用out隐式对象来向客户端发送文本形式的实体内容。 • out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。 • JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。 • JSP页面中的out隐式对象相当于插入到ServletResponse.getWriter方法返回的PrintWriter对象前面的缓冲包装类对象。 • 只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中: • 设置page指令的buffer属性关闭了out对象的缓存功能 • 写入到out对象中的内容充满了out对象的缓冲区 • 整个JSP页面结束 IT资讯交流网 WWW.IT315.ORG
out隐式对象的工作原理图 IT资讯交流网 WWW.IT315.ORG
Out隐式对象实践 动手体验:了解out对象的相关特性 IT资讯交流网 WWW.IT315.ORG
pageContext对象 • pageContext对象简介 • 获得其他隐式对象 • 引入和跳转到其他资源 • 访问各个域范围中的属性 • pushBody与popBody方法 IT资讯交流网 WWW.IT315.ORG
pageContext对象简介 • pageContext对象是javax.servlet.jsp.PageContext类的实例对象,javax.servlet.jsp.PageContext类是javax.servlet.jsp.JspContext的子类。 • pageContext对象封装了当前JSP页面的运行信息,它提供了返回JSP页面的其他隐式对象的方法。 • pageContext对象是通过调用JspFactory.getPageContext方法返回的,getPageContext方法的完整语法如下: public PageContext getPageContext( javax.servlet.Servlet servlet, javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, java.lang.String errorPageURL, boolean needsSession, int buffer, boolean autoflush) • 在JSP页面中只需将pageContext对象传递给某个Java类的实例对象,在该Java对象中就可以访问和调用其他隐式对象的功能了。 • PageContext类中定义了一个setAttribute方法来将对象存储进pageContext对象内部的一个HashMap对象中,同时也定义了一个getAttribute方法来检索存储在该HashMap对象中的对象。 • PageContext类除了可以存储和检索自身中的属性对象外,还定义了可以存储和检索其他域范围内的属性对象的方法。 IT资讯交流网 WWW.IT315.ORG
获得其他隐式对象 • getException方法返回exception隐式对象 • getPage方法返回page隐式对象 • getRequest方法返回request隐式对象 • getResponse方法返回response隐式对象 • getServletConfig方法返回config隐式对象 • getServletContext方法返回application隐式对象 • getSession方法返回session隐式对象 • getOut方法返回out隐式对象 IT资讯交流网 WWW.IT315.ORG
引入和跳转到其他资源 • PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和RequestDispatcher.include方法的调用: • public void forward(java.lang.String relativeUrlPath) throws javax.servlet.ServletException,java.io.IOException • public void include(java.lang.String relativeUrlPath) throws javax.servlet.ServletException,java.io.IOException • public void include(java.lang.String relativeUrlPath,boolean flush) throws javax.servlet.ServletException,java.io.IOException • 传递给这些方法的资源路径都只能是相对路径,如果路径以“/”开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前JSP所映射到的访问路径。 动手体验:了解PageContext.forward方法的应用 IT资讯交流网 WWW.IT315.ORG