本篇接上一篇《JSP的学习(2)——语法知识一》,继续来学习JSP的语法。本文主要从JSP指令中的page指令,对其各个属性进行详细的学习:
JSP指令:
JSP指令是为JSP引擎而设计的,JSP指令不产生任何可见输出,只是告诉在转换成Servlet的过程中如何处理JSP页面中的其余部分。在JSP 2.0 规范*定义了三个指令:
1) page指令
2) include指令
3) taglib指令
taglib指令是导入标签库的指令,以后会介绍到。
JSP指令格式:
<%@ 指令(如page、include或taglib) 属性1="属性值" 属性2="属性值" … %>
例如:
<%@ page contentType = "text/html;charset=utf-8" %>
如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
例如:
<%@ page contentType = "text/html;charset=utf-8" %>
<%@ page import = "java.util.Date" %>
或者写成:
<%@ page contentType="text/html;charset=utf-8" import="java.util.Date" %>
page指令
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和良好习惯,page指令最好都放置在整个page页面的起始位置。
page指令包含以下属性(属性值为示例):
(1). language = “java ” 指示JSP页面如果嵌入的代码为Java代码。
(2). extends = “package.class” 指定当该JSP转换后的Servlet继承哪个类(通常不用动)。
(3). import = ”包名.类名”或者”包名.*” 等等格式,
其中JSP引擎会自动导入如下包:
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
正是因为这样,所以我们在JSP中使用像System,response,request这样的类或对象都不需要再另外导包。
使用多条page指令的“import”属性进行导入多个类或包,也可以在一条page指令的“import”属性中导入多个类或包,其中每个包或者类之间用逗号隔开,例如:
<%@ page import=" java.util.Date , java.util.* " %>
(4). session = “true”(默认值)或”false”
若在page指令中将“session”属性置为“true”,那么在JSP转换后的Servlet中将自动创建Session对象。
如果我们在page指令中指定“session”属性置为“true”,那么在Tomcat的【work】目录下JSP对应的 .java文件中就自动出现如下代码:
session = pageContext.getSession() ;
这时我们就可以在JSP脚步片断中直接使用session,如果在page指令中指定“session”属性置为“false”,那么就不能在JSP脚步片断中直接使用session,想使用就手动获取 (request.getSession())。
(5). buffer = “none” 或 ”8 kb”(默认值) 或 ”自定义值kb”
指定JSP页面是否需要缓冲。即我们直到JSP转换后的Servlet中包含大量的通过out对象进行输出,但输出的数据并非直接写给浏览器,而是直到缓冲满时才将数据发送回浏览器上。
(6). autoFlush = “true”(默认值) 或”false”
指定JSP页面是否自动刷新。
(7). isThreadSafe = “true”(默认值) 或”false”
JSP中的“isThreadSafe”属性如果设置为“false”,那么表示转换后的Servlet将会继承SingleThreadMode接口,以Singleton(单线程)模式运行,这种模式同一个时刻只允许一个实例,若多个用户同时访问该JSP,那么只有先访问者完全访问完该页面后,后访问者才能开始进行访问。
例:未设置“isThreadSafe”属性时:
设置“isThreadSafe”属性为“false”后:
而如果“isThreadSafe”属性设置为“true”,默认值也是“true”,那么表示转换后的Servlet以多线程方式运行,是线程安全的。
(8). info = “自定义信息…”
用于在JSP页面中定义一些说明,可以在Servlet中通过getServletInfo()方法获取通过page指令获取”info”的值。
(9). errorPage = “/ 相对URL ”
当JSP页面错误,或者其中的Java程序出错,抛出异常没有处理,那么在浏览器*问的JSP页面可以跳转到“errorPage”属性指定的某个页面,友好显示。
注意,”errorPage”属性的值是相对于web应用下的地址(给服务器端的地址,因为抛出异常的话是由服务器来处理跳转到哪个页面)。
例如:在web工程【JSPLearning】下,创建一个【exceptions】目录,并在该目录下新建一个“error.jsp”,同时记住将该JSP中的JSP指令中的“pageEncoding”改为支持中文格式的编码,内容如下:
<body>
对不起,你的页面内容有错。。。
</body>
在该web工程的【WebRoot】即根目录下创建一个“1.jsp”文件,写入一段JSP脚本片断:
<%
int x = 1;
out.write(1/0); //会抛出异常
%>
同时在该JSP的上部添加进JSP指令,这里直接写了属性:
errorPage = "/exceptions/error.jsp"
那么现在我们来访问这个web应用的“1.jsp”页面,可以看到:
会抛出我们没有处理的异常的JSP自动跳转到了我们在“errorPage”属性设置的页面,这样用户就不会看到那些“经典”的505页面和里面各种异常的说明了。
题外话:
当我们是个大项目时,里面会有很多个网页,当这些网页多起来后,如果对每个JSP网页都设置“errorPage”肯定是不切实际的。这时我们就可以在web.xml文件中设置错误处理页面。如果要将Tomcat中所有的web应用设置,就在Tomcat的【conf】文件下的web.xml文件中设置;如果只对某个web应用设置错误处理页面,就在该web应用中【WEB-INF】目录下的web.xml文件中设置。
在web.xml文件中使用<error-page>标签为整个web应用程序设置错误处理页面,其中<exception-type>子元素指定具体异常完整包名和异常名称,<location>标签指定以“/”开头的错误处理页面的路径(也是以web应用为根目录的路径,即服务器端的路径)。
我们对上面的例子进行重新改写,将包含“errorPage”属性的page指令从1.jsp中删除,由于我们知道在1.jsp文件中我们的JSP脚本片断会抛出ArithmeticException异常,因此记下这个异常及异常的包名路径,之后需要添加到<exception-type>标签中。
接着我们我们到web工程【JSPLearning】中的【WEB-INF】目录下的web.xml文件,添加下面几句代码:
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/exceptions/error.jsp</location>
</error-page>
完成上面的工作之后,当访问该web应用下的某个资源(不管是JSP还是Servlet等等),只要会抛出ArithmeticException这个异常,服务器会立马将资源跳转到指定这个异常的错误处理页面,在我们的例子中是/exceptions/error.jsp,再次访问1.jsp还是看到同样的效果:
这样就完成了在一个web应用中进行全部资源的错误处理页面的配置,当然这点有一个不足的地方就是使用这种方法必须指明会发生何种错误异常(<exception-type>必须指明)。但如果使用<error-code>就可以免去这种烦扰,后面会说到。
另外一个,采用这种方法时,如果浏览器,比如说IE,在其【工具】--->【Internet选项】中,选择【高级】,找到一个【显示友好HTTP错误信息】,如下图所示:
通常这个选项浏览器默认是勾选上的,这会有一个什么问题呢,就是采用在web.xml文件中配置<error-page>这元素时,如果我们的错误处理页面中的内容太少,不足1024字节,那么在浏览器是无法正常跳转到错误处理页面的,比如说我们刚才的/exceptions/error.jsp中将<body>标签内容就设置为:ERROR!,内容够少了吧,那么我们重新打开浏览器来访问1.jsp:
可以看到无法看到错误处理页面。
两种解决方式:1,将【Internet选项】中的【显示友好HTTP错误信息】钩去除;2,在/exceptions/error.jsp错误处理页面中将内容添加超过1024字节(多添加点很容易就超过了)。以上两种方法都可以重新看到错误处理页面。
上面说到在<error-page>中可以设置<exception-type>这个子元素,但是我们必须给定明确的异常,毕竟麻烦。但是在<error-page>中还可以设置<error-code>这个子元素,这个元素用来表明当浏览器访问遇到错误响应码时应该访问哪些页面,有哪些错误的响应码呢? !!眼熟吗,T_T!
我们继续以上面的web工程【JSPLearning】为例,在之前的【exceptions】目录下新建一个error404.jsp,添加自定义内容。
接着我们继续在该web工程的web.xml中添加如下代码:
<error-page>
<error-code>404</error-code>
<location>/exceptions/error404.jsp</location>
</error-page>
当我们访问一个在web应用中不存在的资源时,服务器就会帮我们跳转到这个出现404错误而设置的错误处理页面,友好显示:
可以看到,这样就比指定特别异常要方便的多,当然指定某个特定异常自然有其作用的地方,这些都要靠实际情况来考虑。
题外话讲多了,不过这都是对开发有帮助的技巧。这里最后说明一点,如果在某个页面中设置了“errorPage”属性的page指令,那么在web.xml文件中设置的<error-page>两种形式都对其没有作用,也就是说JSP页面只先认page指令的“errorPage”属性。
(10). isErrorPage = “true” 或”false”(默认值)
结合上一点,当我们将某个JSP页面设置为错误处理页面,那么我们最好将该页面设置page指令的“isErrorPage”属性,并置其为“true”。
这么做有什么好处呢?当这个错误处理JSP页面之后被转换成Servlet后,在这个Servlet中会自动生成一个异常对象exception,该对象封装了之前错误访问的一些信息。记住,如果在错误处理页面中没有设置page指令的“isErrorPage”属性或者说为”false”的话,那么转换之后的Servlet是不会有这个exception对象的。
那么我们还是以上面的web工程【JSPLearning】为例,当我们为/exceptions/error.jsp这个JSP设置了page指令的“isErrorPage”属性:
<%@ page isErrorPage="true" %>
让浏览器访问一次有错误代码的1.jsp使得浏览器跳转到错误处理页面后,我们到Tomcat的【work】目录下查看 error_jsp.java文件,我们会发现在error_jsp这个类中的_jspService()方法中多出了对exception对象的定义,这是没有设置“isErrorPage”为”true”的JSP转换Servlet所没有的:
这个exception对象同out对象,page对象等,都是可以在JSP中直接使用的,切记这个对象一定是在那些声明了“isErrorPage”为”true”的JSP中直接使用。
(11). contentType = “ MIME类型/对应类型 [(;chrset=某个编码表)可选] ”
在page指令中的“contentType”属性告诉JSP引擎(或Tomcat)该JSP页面的类型,例如:
<%@ page contentType="text/html; charset=ISO-8859-1" %>
在JSP转换到Servlet时,会根据page指令中的“contentType”属性生成相应的调用ServletResponse.setContentType(…)方法语句。
“contentType”属性是用来通知浏览器以什么码表来解码打开JSP(其实是Servlet)中的内容。
这个属性可以用来解决JSP中可能出现的乱码问题,这个问题我们以后会讨论到。
(12). pageEncoding = “某个编码表”
该page指令的属性“pageEncoding”指定服务器以什么码表将JSP文件翻译成.java文件中的内容。当设置了这个“pageEncoding”属性之后,其实也默认将“contentType”属性中的编码表设置的和它一样,所以总结来说我们只需设置“pageEncoding”属性即可。
(13). isELIgnored = “true” 或 “false”(默认值)
告诉JSP引擎(或Tomcat)该JSP页面是否忽略EL表达式。默认值为“false”即JSP均支持EL表达式。