Servlet,JSP(5)(JSP隐式对象和语法元素:指令、脚 本元素和动作)

1,JSP

版本:

 

Servlet有两个缺点是无法克服的:
1,写在Servlet中的所有HTML标签必须包含Java字符串,这使得处理HTTP响应报文的工作十分烦琐;
2,所有的文本和HTML标记是硬编码,导致即使是表现层的微小变化,如改变背景颜色,也需要重新编译。

JavaServer Pages(JSP)解决了上述两个问题。同时,JSP不会取代Servlet,相反,它们具有互补性。
一个JSP页面不同于一个Servlet的另一个方面是:前者不需要添加注解或在部署描述符中配置映射URL

补充:

可以用标准语法或XML语法编写JSP。
用XML语法编写的JSP页面被称为JSP文档。
但很少用XML语法编写JSP,不详述。
JSP页面本质上是一个Servlet。

JSP页面在JSP容器中运行,一个Servlet容器通常也是JSP容器。
例如,Tomcat就是一个Servlet/JSP容器。

当一个JSP页面第一次被请求时,Servlet/JSP容器主要做以下两件事情:

1转换JSP页面到JSP页面实现类
该实现类是一个实现javax.servlet.jsp.JspPage接口或子接口javax.servlet.jsp.HttpJspPage的Java类
JspPage是javax.servlet.Servlet的子接口,这使得每一个JSP页面都是一个Servlet。 该实现类的类名由Servlet
/JSP容器生成。如果出现转换错误,则相关错误信息将被发送到客户端。 (2)如果转换成功,Servlet/JSP容器随后编译该Servlet类,并装载和实例化该类,像其他正常的Servlet一样执行生命周期操作。

ps:总结:

jsp页面转换为servlet过程:
1,jsp转换为了servlet接口的子接口JspPage的子接口HttpJspPage的java类(即servlet类)。
2,编译该HttpJspPage类型的servlet。

jsp页面重复被请求时:

对于同一个JSP页面的后续请求,Servlet/JSP容器会先检查JSP页面是否被修改过。
如果是,则该JSP页面会被重新翻译、编译并执行。
如果不是,则执行已经在内存中的JSP Servlet。

解决:一个JSP页面的第一次调用的很耗时问题:

1配置应用程序,使所有的JSP页面在应用程序启动时被调用,而不是在第一次请求时调用。
2预编译JSP页面,并将其部署为Servlet

JSP自带的API包含4个包:

1,javax.servlet.jsp。
包含用于Servlet/JSP容器将JSP页面翻译为Servlet的核心类和接口。
其中的两个重要成员是JspPage和HttpJspPage接口。 所有的JSP页面实现类必须实现JspPage或HttpJspPage接口。 在HTTP环境下,实现HttpJspPage接口是显而易见的选择。 2,javax.servlet.jsp.tagext。包括用于开发自定义标签的类型。 3,javax.el。提供了统一表达式语言的API。 4,javax.servlet.jsp.el。提供了一组必须由Servlet
/JSP容器支持,以便在JSP页面中使用表达式语言的类
jsp api:
https://docs.oracle.com/javaee/7/api/index.html?javax/servlet/jsp/package-summary.html

注意:一般很少直接使用jspAPI,而是让容器自动调用

ps:总结:

减少jsp第一次请求编译过程的方式:
1,启动服务器编译jsp
2,主动将jsp直接编译成servlet

2,jsp转换servlet:

JSP页面可以包含模板数据和语法元素。

1语法元素是一些具有特殊意义的JSP转换符。
   3个语法元素(指令、脚本元素和动作)

2,除去语法元素外的一切是模板数据。
   模板数据会原样发送给浏览器。
   例如,JSP页面中的HTML标记和文字都是模板数据

补充:常用模板引擎

JSP ,velocity,freemark 

 一个名为welcome.jsp的JSP页面

<html>
<head><title>Welcome</title></head>
<body>
Welcome
</body>
</html>

welcome.jsp页面在第一次请求时被翻译成名为welcome_jsp的Servlet。

你可以在Tomcat工作目录下的子目录中找到生成的Servlet,
该Servlet继承自org.apache.jasper. runtime.HttpJspBase,
(这是一个抽象类,
继承自javax.servlet.http.HttpServlet并实现javax.servlet.jsp.HttpJspPage)
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class welcome_jsp extends org.apache.jasper.runtime.HttpJspBase
                         implements org.apache.jasper.runtime.JspSourceDependent{
private static final javax.servlet.jsp.JspFactory _jspxFact ory =javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long>、getDependants() { return _jspx_dependants; }
public void _jspInit() { _el_expressionfactory =_jspxFactory.getJspApplicationContext(getServletConfig().getServletContext())
.getExpressionFactory();
_jsp_instancemanager
=org.apache.jasper.runtime.InstanceManagerFactory .getInstanceManager(getServletConfig()); }
public void _jspDestroy() {}
public void _jspService(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException {
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;
try { response.setContentType("text/html"); pageContext = _jspxFactory.getPageContext(this, request,response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
out.write(
"<html>\n"); out.write("<head><title>Welcome</title></head>\n"); out.write("<body>\n"); out.write("Welcome\n"); out.write("</body>\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){

out
= _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
} }
finally { _jspxFactory.releasePageContext(_jspx_page_context); }}}

ps:有点奇怪,为什么有重复的对象引用比如:out 和 _jspx_out ???

补充:

JSP页面的主体是_jspService方法。
这个方法被定义在HttpJspPage,并被HttpJspBase的service方法调用。

下面的代码来自HttpJspBase类:
public final void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException,IOException {
   _jspService(request, response);
}

3,注释:

JSP支持两种不同的注释格式:

1)JSP注释。该注释记录页面中做了什么。
2)HTML/XHTML注释。这些注释将会发送到浏览器上。
JSP注释以“<%--”开始,以“--%>”结束。
下面是一个例子:
<%-- retrieve products to display --%> JSP注释不会被发送到浏览器端,也不会被嵌套。 HTML/XHTML注释语法如下: <!-- [comments here] --> 一个HTML/XHTML注释不会被容器处理,会原样发送给浏览器。
HTML/XHTML注释的一个用途是用来确定JSP页面本身。 <!-- this is /jsp/store/displayProducts.jspf --> 尤其是在运行有多个JSP片段的应用时,会特别有用。 是哪一个JSP页面或片段产生了相应的HTML片段。

4,隐式对象

Servlet容器会传递几个对象给它运行的Servlet。

例如,可以通过Servlet的service方法拿到HttpServletRequestHttpServletResponse对象,
以及可以通过init方法访问到ServletConfig对象。
可以通过调用HttpServletRequest对象的getSession方法访问到HttpSession对象。

JSP隐式对象(9个):

对象                        类型
request         javax.servlet.http.HttpServletRequest
response        javax.servlet.http.HttpServletResponse
out             javax.servlet.jsp.JspWriter
session         javax.servlet.http.HttpSession
application     javax.servlet.ServletContext
config          javax.servlet.ServletConfig
pageContext     javax.servlet.jsp.PageContext
page            javax.servlet.jsp.HttpJspPage  (表示当前页面,一般用不到)
exception       java.lang.Throwable

4.1,request

该隐式对象代表Servlet/JSP容器传递给Servlet服务方法的HttpServlet Request对象。

<%
String userName = request.getParameter("userName");
%>

4.2,pageContext

pageContext用于javax.servlet.jsp.PageContext它提供了有用的上下文信息,并通过其自说明的方法来访问各种Servlet相关对象,
如getRequest、getResponse、getServletContext、getServletConfig和getSession。
但在脚本中不是非常有用的,因为可以更直接地通过隐式对象来访问request、response、session和application。 PageContext中提供了另一组有趣的方法: 用于获取和设置属性的方法,即getAttribute方法和setAttribute方法。
属性值可被存储在4个范围之一: 页面、请求、会话和应用程序。 页面范围是最小范围,这里存储的属性只在同一个JSP页面可用。 请求范围是指当前的ServletRequest中。 会话范围指当前的HttpSession中。 应用程序范围指应用的ServletContext中。 PageContext的setAttribute方法签名如下:
public abstract void setAttribute(java.lang.String name, java.lang.Object value, int scope) 其中,scope的取值范围为PageContext对象的最终静态int值:
PAGE_SCOPE、REQUEST_ SCOPE、SESSION_SCOPE和APPLICATION_SCOPE。 若要保存一个属性到页面范围,可以直接使用setAttribute重载方法:
public abstract void setAttribute(java.lang.String name, java.lang.Object value)
如下脚本将一个属性保存到ServletRequest中:
<% //product is a Java object pageContext.setAttribute("product", product,PageContext.REQUEST_SCOPE); %>

同样效果的Java代码如下: <% request.setAttribute("product", product); %>

4.3,out

隐式对象out引用了一个javax.servlet.jsp.JspWriter对象,
这类似于你在调用HttpServlet Response的getWriter方法时得到java.io.PrintWriter。 可以通过调用它的print方法将消息发送到浏览器。 例如: out.println(
"Welcome");

隐式对象的例子

implicitObjects.jsp页面
<%@page import="java.util.Enumeration"%>
<html>
<head><title>JSP Implicit Objects</title></head>
<body>
<b>Http headers:</b><br/>
<%
for (Enumeration<String> e = request.getHeaderNames();
e.hasMoreElements(); ){
String header = e.nextElement();
out.println(header + ": " + request.getHeader(header) +
"<br/>");
}
%>
<hr/>
<%
out.println("Buffer size: " + response.getBufferSize() +
"<br/>");
out.println("Session id: " + session.getId() + "<br/>");
out.println("Servlet name: " + config.getServletName() +
"<br/>");
out.println("Server info: " + application.getServerInfo());
%>
</body>
</html>
View Code
该页面产生了如下内容:
Http headers:
host: localhost:8080
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8)
AppleWebKit/534.50.2 (KHTML, like Gecko) Version/5.0.6
Safari/533.22.3
accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/
*;q=0.8
accept-language: en-us
accept-encoding: gzip, deflate
connection: keep-alive
Buffer size: 8192
Session id: 561DDD085ADD99FC03F70BDEE87AAF4D
Servlet name: jsp
Server info: Apache Tomcat/7.0.14
View Code

注意,在默认情况下,JSP编译器会将JSP页面的内容类型设为text/html

如果要使用不同的类型,则需要通过调用response.setContentType()或者使用页面指令来设置内容类型。
例如,下面就是将内容类型设置为text/json:
response.setContentType("text/json");

5,指令

指令是JSP语法元素的第一种类型。
它们指示JSP转换器如何翻译JSP页面为Servlet。
JSP 2.2定义了多个指令,但page和include最重要,其他 taglib、tag、attribute以及variable。

5.1,page指令

可以使用page指令来控制JSP转换器转换当前JSP页面的某些方面例如,可以告诉JSP用于转换隐式对象out的缓冲器的大小、内容类型,以及需要导入的Java类型,等等。

page指令的语法如下:

<%@ page attribute1="value1" attribute2="value2" ... %>
@和page间的空格不是必须的attribute1、attribute2等是page指令的属性

如下是page指令属性列表:

import定义一个或多个本页面中将被导入和使用的java类型。
例如:import="java.util.List"将导入List接口。
可以使用通配符“*”来引入整个包,类似import="java.util.*"可以通过在两个类型间加入“,”分隔符来导入多个类型,如
import="java.util.ArrayList、java.util.Calendar、java.io.PrintWriter"
此外,JSP默认导入如下包:java.lang、javax.servlet、javax.servlet.http、javax.servlet.jsp。

session:值为True,本页面加入会话管理;值为False则相反。
默认值为True,访问该页面时,若当前不存在javax.servlet.http.HttpSession实例,则会创建一个buffer以KB为单位,定义隐式对象out的缓冲大小。
必须以KB后缀结尾。
默认大小为8KB或更大(取决于JSP容器)。
该值可以为none,这意味着没有缓冲,所有数据将直接写入PrintWriter。
autoFlush默认值为True。 若值为True,则当输出缓冲满时会自写入输出流。 而值为False,则仅当调用隐式对象的flush方法时,才会写入输出流。因此,若缓冲溢出,则会抛出异常。 isThreadSafe定义该页面的线程安全级别。 不推荐使用 JSP 参数,因为使用该参数后,会生成一些Servlet容器已过期的代码。 info返回调用容器生成的Servlet类的getServletInfo方法的结果errorPage定义当出错时用来处理错误的页面isErrorPage标识本页是一个错误处理页面contentType定义本页面隐式对象response的内容类型,默认是text
/html。 pageEncoding定义本页面的字符编码,默认是ISO-8859-1 isELIgnored配置是否忽略EL表达式。EL是Expression Language的缩写。 language定义本页面的脚本语言类型,默认是Java,这在JSP 2.2中是唯一的合法值。 extends定义JSP实现类要继承的父类。这个属性的使用场景非常罕见,仅在非常特殊理由下使用。 deferredSyntaxAllowedAsLiteral定义是否解析字符串中出现“#{”符号,默认是False。 “{# ”是一个表达式语言的起始符号。 trimDirectiveWhitespaces定义是否不输出多余的空格/空行,默认是False

5.2,include指令

可以使用include指令将其他文件中的内容包含到当前JSP页面。
一个页面中可以有多个include指令。
若存在一个内容会在多个不同页面中使用或一个页面不同位置使用的场景,则将该内容模块化到一个include文件非常有用。

include指令的语法如下:

<%@ include file="url"%>
其中,@和include间的空格不是必须的,URL为被包含文件的相对路径, 若URL以一个斜杠(/)开始,则该URL为文件在服务器上的绝对路径,否则为当前JSP页面的相对路径。
JSP转换器处理include指令时,将指令替换为指令所包含文件的内容。
换句话说,如果编写在清单3.4的copyright.jspf文件,以及主文件清单3.5的main.jsp页面:

清单3.4 copyright.jspf文件
<hr/>
&copy;2015 BrainySoftware
<hr/>

清单3.5 main.jsp页面
<html>
<head><title>Including a file</title></head>
<body>
This is the included content: <hr/>
<%@ include file="copyright.jspf"%>
</body>
</html>

则在main.jsp页面中应用include指令和如下页面的效果是一样的:
<html>
<head><title>Including a file</title></head>
<body>
This is the included content: <hr/>
<hr/>
&copy;2015 BrainySoftware
<hr/>
</body>
</html>

如上示例中,为保证include指令能正常工作,copyright.jspf文件必须同main.jsp位于相同的目录。
按照惯例,以JSPF为扩展名的文件代表JSP fragement。
虽然JSP fragement现在被称为JSP segment,但为保证一致性,JSPF后缀名依然被保留。
View Code

注意,include指令也可以包含静态HTML文件。

6,脚本元素

一个脚本程序是一个Java代码块,以<%符号开始,以%>符号结束。

 使用脚本程序(scriptletTest.jsp)

<%@page import="java.util.Enumeration"%>
<html>
<head><title>Scriptlet example</title></head>
<body>
<b>Http headers:</b><br/>
<%-- first scriptlet --%>
<%
  for (Enumeration<String> e = request.getHeaderNames();
       e.hasMoreElements(); ){
     String header = e.nextElement();
     out.println(header + ": " + request.getHeader(header) +
          "<br/>");
  }
  String message = "Thank you.";
%>
<hr/>
<%-- second scriptlet --%>
<%
  out.println(message);
%>
</body>
</html>

定义在一个脚本程序中的变量可以被其后续的脚本程序使用。

1)表达式(ps:输出返回值)

每个表达式都会被JSP容器执行,并使用隐式对象out的打印方法输出结果表达式以“<%=”开始,并以“%>”结束。
Today is <%=java.util.Calendar.getInstance().getTime()%>

注意,表达式无须分号结尾。

JSP容器首先执行java.util.Calendar.getInstance().getTime(),并将计算结果传递给out.print(),
这与如下脚本程序的效果一样: Today
is <% out.print(java.util.Calendar.getInstance().getTime()); %>

2)声明(即全局成员)

可以声明能在JSP页面中使用的变量和方法。
声明以“<%!”开始,并以“%>”结束。

declarationTest.jsp声明了一个getTodaysDate的方法

<%!
public String getTodaysDate() {
return new java.util.Date();
}
%>
<html>
<head><title>Declarations</title></head>
<body>
Today is <%=getTodaysDate()%>
</body>
</html>
在JSP页面中,一个声明可以出现在任何地方,并且一个页面可以有多个声明。

可以使用声明来重写JSP页面,实现类的init和destroy方法

通过声明jspInit方法,来重写init方法。
通过声明jspDestroy方法,来重写destory方法。
这两种方法说明如下: jspInit。这种方法类似于 javax.servlet.Servlet 的 init方法。 JSP 页面在初始化时调用jspInit。 不同于init方法,jspInit没有参数。 还可以通过隐式对象config访问ServletConfig对象。 jspDestroy。这种方法类似于Servlet的destroy方法,在JSP页面将被销毁时调用。

lifeCycle.jsp页面演示了如何重写jspInit和jspDestroy

<%!
public void jspInit() {
System.out.println("jspInit ...");
}
public void jspDestroy() {
System.out.println("jspDestroy ...");
}
%>
<html>
<head><title>jspInit and jspDestroy</title></head>
<body>
Overriding jspInit and jspDestroy
</body>
</html>

lifeCycle.jsp页面会被转换成如下Servlet:

package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class lifeCycle_jsp extends org.apache.jasper.runtime.HttpJspBase
        implements org.apache.jasper.runtime.JspSourceDependent
{
public void jspInit() {
System.out.println("jspInit ...");
}
public void jspDestroy() { System.out.println("jspDestroy ..."); }
private static final javax.servlet.jsp.JspFactory _jspxFact ory =javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; }
public void _jspInit() { _el_expressionfactory =_jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).
getExpressionFactory(); _jsp_instancemanager
= org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); }
public void _jspDestroy() { }
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)throws java.io.IOException, javax.servlet.ServletException { 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; try {
response.setContentType(
"text/html"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\n"); out.write("<html>\n"); out.write("<head><title>jspInit and jspDestroy" + "</title></head>\n"); out.write("<body>\n"); out.write("Overriding jspInit and jspDestroy\n"); out.write("</body>\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) { } if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context) ;}}}

注意生成的Servlet类中的jspInit和jspDestroy方法。
现在可以用如下URL访问lifeCycle.jsp:

http://localhost:8080/app03a/lifeCycle.jsp
第一次访问页面时,可以在控制台上看到“jspInit...”,
以及在Servlet/JSP容器关闭时看到“jspDestory...”。

3)禁用脚本元素

随着JSP 2.0对表达式语言的加强,
推荐:在JSP页面中用EL访问服务器端对象且不写Java代码。
因此,从JSP 2.0起,
可以通过在部署描述符中的<jsp-property-group>定义一个scripting-invalid元素,来禁用脚本元素
<jsp-property-group> <url-pattern>*.jsp</url-pattern> <scripting-invalid>true</scripting-invalid> </jsp-property-group>

7,动作

动作是第三种类型的语法元素,它们被转换成Java代码来执行操作,如访问一个Java对象或调用方法。

本节仅讨论所有JSP容器支持的标准动作。
除标准外,还可以创建自定义标签执行某些操作

7.1,useBean

useBean将创建一个关联Java对象的脚本变量。
这是早期分离的表示层和业务逻辑的手段。
随着其他技术的发展,如自定义标签和表达语言,现在很少使用useBean方式
useBeanTest.jsp页面是一个示例,
它创建一个java.util.Date实例,并赋值给名为today的脚本变量,然后在表达式中使用。

useBeanTest.jsp页面
<html>
<head>
<title>useBean</title>
</head>
<body>
<jsp:useBean id="today" class="java.util.Date"/>
<%=today%>
</body>
</html>

在Tomcat中,上述代码会被转换为如下代码:

java.util.Date today = null;
today = (java.util.Date) _jspx_page_context.
getAttribute("today",javax.servlet.jsp.PageContext.REQUEST_SCOPE);
if (today == null) { today = new java.util.Date(); _jspx_page_context.setAttribute("today", today,javax.servlet.jsp.PageContext.REQUEST_SCOPE); }

7.2,setProperty和getProperty

setProperty动作可对一个Java对象设置属性,而getProperty则会输出Java对象的一个属性。

getSetPropertyTest.jsp展示如何设置和输出定义在Employee类实例的firstName属性。

Employee类
package app03a;
public class Employee {
private String id;
private String firstName;
private String lastName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

getSetPropertyTest.jsp页面
<html>
<head>
<title>getProperty and setProperty</title>
</head>
<body>
<jsp:useBean id="employee" class="app03a.Employee"/>
<jsp:setProperty name="employee" property="firstName" value="Abigail"/>
First Name: 
<jsp:getProperty name="employee" property="firstName"/> </body> </html>

7.3,include

include动作用来动态地引入另一个资源。
可以引入另一个JSP页面,也可以引入一个Servlet或一个静态的HTML页面。

jspIncludeTest.jsp页面使用include动作来引入menu.jsp页面。

jspIncludeTest.jsp页面
<html>
<head>
<title>Include action</title>
</head>
<body>
<jsp:include page="jspf/menu.jsp">
<jsp:param name="text" value="How are you?"/>
</jsp:include>
</body>
</html>

include指令和include动作区别:

对于include指令,资源引入发生在页面转换时,即当JSP容器将页面转换为生成的Servlet时。
而对于include动作资源引入发生在请求页面时。 因此,使用include动作是可以传递参数的,而include指令不支持。 第二个不同是,include指令对引入的文件扩展名不做特殊要求
但对于include动作,若引入的文件需以JSP页面处理,则其文件扩展名必须是JSP若使用.jspf为扩展名,则该页面被当作静态文件

7.4,forward

forward将当前页面转向到其他资源。

下面代码将从当前页转向到login.jsp页面:

<jsp:forward page="jspf/login.jsp">
<jsp:param name="text" value="Please login"/>
</jsp:forward>

8,错误处理

JSP提供了很好的错误处理能力。
除了在Java代码中可以使用try语句,还可以指定一个特殊页面。
当应用页面遇到未捕获的异常时,用户将看到一个精心设计的网页解释发生了什么,而不是一个用户无法理解的错误信息。

page指令的isErrorPage属性(属性值必须为True)来标识一个JSP页面是错误页面

<%@page isErrorPage="true"%>
<html>
<head><title>Error</title></head>
<body>
An error has occurred. <br/>
Error message:
<%
out.println(exception.toString());
%>
</body>
</html>

其他需要防止未捕获的异常的页面使用page指令的errorPage属性来指向错误处理页面。

buggy.jsp页面就使用了错误处理程序。
buggy.jsp页面
<%@page errorPage="errorHandler.jsp"%>
Deliberately throw an exception
<%
Integer.parseInt("Throw me");
%>
运行的buggy.jsp页面会抛出一个异常,不会看到由Servlet/JSP容器生成错误消息。
相反,会看到errorHandler.jsp页面的内容。

 ps:总结:3个语法元素:指令、脚本元素和动作

指令:相当于一种配置的参数
脚本:相当于拼接进入java类
动作:相当于方法的占位符

 

posted @ 2018-11-04 15:58  假程序猿  阅读(450)  评论(0)    收藏  举报