JSP简介
JSP(java Server Pages,java服务器页面)是Servlet的高级扩展。在JSP文件中,HTML代码与Java代码共同存在,HTML代码用于实现网页中静态内容的实现,Java代码用于实现网页中动态内容的显示。
一个JSP页面可以包括指令标识、HTML代码、JavaScript代码、嵌入的Java代码、注释和JSP动作标识的JSP文件
JSP脚本元素
JSP脚本元素是嵌套在"<%"、"%>"中的Java程序代码,JSP脚本元素主要包含以下3种类型: JSP Scriptlets、声明标识、JSP表达式。通过这三种类型,可以在JSP页面中像编写Java程序一样声明变量、定义函数或进行各种表达式运算。本文里代码片段会指代所有与Java有联动的代码片段,下面进行详细介绍:
1.JSP Scriptlets
JSP Scriptlets是一段在JSP页面中嵌入的Java代码或脚本代码。代码片段会在页面请求的处理期间被执行。
有关脚本代码:有些地方可能在提到JSP的脚本代码时会专门说Java代码和脚本代码,JSP Scriptlets主要会嵌入Java代码。在JSP页面中除了Java代码之外,可能还包含的其他脚本语言代码(尽管这在标准JSP中并不常见)。JSP本身不直接支持除Java之外的脚本语言,但可以通过JSP标签库(Tag Libraries)间接支持其他脚本或标记语言的行为。
JSP Scriptlets的语法格式如下:
<% java 代码(变量、方法、表达式等) %>
整体示例
<html>
<head>
<title>JSP Scriptlets</title>
</head>
<body>
<%
int a = 1, b = 2; //定义两个变量a,b
out.println(a+b);
%>
</body>
</html>
2.声明标识
JSP Scriptlets可以进行属性的定义也可以输出内容,但是不可以进行方法的定义。想要定义方法,可以使用声明标识。声明标识用于在JSP页面中定义全局变量或方法,可以被整个当前的JSP页面所访问。
声明标识的语法格式如下:
<%!
定义变量或方法等
%>
整体示例
<html>
<head>
<title>JSP声明语句</title>
</head>
<%!
public int print() { //定义print方法
int a = 1, b = 2; //定义两个变量a,b
return a+b;
}
%>
<body>
<%
out.println(print());
%>
</body>
</html>
3.JSP表达式
JSP表达式用于向页面输出信息,语法格式如下:
<%= 表达式 %>
表达式可以是任意完整的表达式,该表达式的最终结果会转换成一个字符串。将JSP表达式插入JSP页面的相应位置,对JSP表达式的运算结果进行输出。
整体示例
<html>
<head>
<title>JSP表达式</title>
</head>
<%!
int a =1,b = 2;//定义两个变量a、b
%>
<body>
<%=
a+b
%>
</body>
</html>
补充
1."<%!"、"<%="是一个完整的符号"!"、"="和"%"之间没有空格
2.“<%!%>”只能进行方法和属性的定义且为全局方法和属性(当前JSP内),不能进行输出。
3.通过声明标识(<%!%>)创建的变量和方法在当前JSP页面中有效,它的生命周期是从创建开始到服务器结束;JSP Scriptlets代码片段(<%%>)也是当前JSP页面有效,但它的生命周期是页面关闭后就会销毁。
JSP注释
1.代码片段中的注释
代码片段中的注释与Java中的注释相同
1.单行注释
//注释内容
2.多行注释
/*
*注释内容1
*注释内容2
........
*/
与Java中的标准一样,文档提示注释会以两个*开头
/**
*提示信息1
*提示信息2
......
*/
2.隐藏注释
在文件中添加的HTML注释虽然在浏览器页面中不显示,但通过开发者工具,在查看源代码时可以看到这些注释。为了安全和保密,JSP提供了隐藏注释,隐藏注释即便查看源代码也看不到。
格式
<%-- JSP隐藏注释 --%>
<!-- HTML注释 -->
3.动态注释
HTML注释对JSP嵌入的代码不起作用,可以利用这一点进行动态的HTML注释文本。
整体示例
<body>
<!-- <%=new Date()%> -->
</body>
最终结果为,在查看源代码时会显示当前JSP文件运行时的时间
JSP指令
1.page指令
page指令用于在JSP页面中,对页面的某些特性进行描述,例如页面的编码方式。格式为:
<%@ page 属性名1="属性值1" 属性名2="属性值2" ...... %>
page指令对整个页面都有效,与其书写的位置无关,但习惯上把page指令写在JSP页面的最前面。
page指令常见属性:
属性名称 | 取值范围 | 描述 |
---|---|---|
language | java | 指定JSP页面的脚本语言,无特殊环境,只可取且默认为Java |
import | 任何包名、类名 | 与Java中的import作用一致 |
session | true、false | 指定该JSP是否内置Session对象,默认true |
isErrorPage | true、false | 指定该页面是否为错误处理页面,默认false |
errorPage | 某个JSP页面的相对路径 | 指定一个错误页面,如果JSP程序抛出一个未捕获的异常,则转到该指定页面。 |
contentType | 有效的文档类型 | 指定当前JSP页面的MIME类型和字符编码 |
pageEncoding | 编码格式 | 指定页面编码格式,如UTF-8 |
补充:
1.session属性的值默认为true。JSP容器会自动导入这4个包: java.lang.*;java.servlet.*;javax.servlet.jsp.*;javax.servlet.http.*;
2.errorPage指定的页面中,必须是isErrorPage属性声明为true的错误处理页面
3.MiME类型指的是JSP页面响应内容的数据类型和字符编码,MIME类型由两部分组成:类型(如text、image、audio等)和子类型(如html、jpeg、png等),它们之间用斜杠(/)分隔
4.contentType补充:HTML格式为text/html;纯文本格式为text/plain;JPG图像为image/jpeg;Word文档为application/msword,更多可去搜索相关资料。
2.include指令
使用include,使得JSP页面包含另一个JSP页面。语法格式如下
<%@ include file="文件地址" %>
include只有file属性,用于指定目标文件的路径。该路径往往使用相对路径,且不以"/"开头。有几个需要注意的点:
1.被引入的文件必须遵循JSP语法(所有通常也是JSP文件)
2.被引入的文件,除了指令元素外,其他的元素都会被转换成相应的Java源代码,然后插入该当前JSP文件该include元素所在的位置。
3. file路径使用"/"开头,会表示相对于当前Web应用程序的根目录。且该file路径表示的为本地存储中源文件的路径,不是服务器运行时程序中的地址。
4.建议在应用include指令进行文件包含时,被包含的文件中的<html><body>等标签删除,不然容易使整个页面的层次结构发生冲突。
3.taglib指令
在JSP文件中可以通过taglib指令表示该页面中所使用的标签库,同时引用标签库并指定标签的前缀。具体格式:
<%@ taglib prefix="tagPrefix" uri="tagURI" %>
prefix:用于指定标签的前缀,该前缀不能命名为jsp、java、jspx、sun、servlet、sunw
url:用于指定标签库文件的存放位置。
JSP动作元素
JSP动作元素用于控制JSP行为,可以执行一些常见的JSP页面动作 ,实现多行Java代码才能够实现的效果。动作元素的样式一般为 <jsp:......>。
这里介绍三种最常用的JSP动作元素:包含文件和请求转发以及传递参数元素。
传递参数元素<jsp:param>
<jsp:param>
动作元素通常与 <jsp:include>
或 <jsp:forward>
一起使用,用于向被包含(include)或被转发(forward)的资源传递参数。这些参数可以作为请求属性(request attributes)或请求参数(query string parameters,但通常不是这种方式)传递给目标资源。然而,需要注意的是,<jsp:param>
实际上是通过设置请求属性来工作的,而不是直接作为查询字符串参数。
包含文件元素<jsp:include>
包含文件元素<jsp:include>用于向当前页面引入其他文件,该文件可以是静态文件也可以是动态文件。具体格式:
<jsp:include page="URL" flush="true|false">
page:用于指定被引入文件的相对路径
flush:用于指定是否将当前页面(使用包含元素的JSP文件,不是引入的文件)的输出内容刷新到客户端中 ,默认为false
动作元素<jsp:include>与指令include的区别:
处理时机
指令include在编译时就执行。当JSP页面被编译成Servlet时,include指定的文件的内容就直接插入到包含它的JSP页面中,这两个JSP文件在编译时就被合并成了一个单一的Servlet类。
元素<jsp:include>是一个执行时(请求处理时)的动作,指定的资源(如另一个JSP页面、Servlet或静态文件)会被动态的包含进来,两者相互独立编译,被动态合并。
参数传递
include指令:由于<%@ include %>是在编译时处理的,因此它不支持向被包含的资源传递参数。被包含的文件必须能够独立地访问其所需的所有数据。
<jsp:include>动作元素:<jsp:include>可以通过<jsp:param>子元素向被包含的资源传递参数。这些参数作为请求属性传递给目标资源,使其能够访问到这些数据。
独立性
include指令:由于被包含的内容在编译时就已经合并到了主JSP页面中,因此被包含的文件必须能够在编译时就被找到。如果主JSP页面和被包含的文件都需要访问相同的变量或方法,它们可能需要共享相同的上下文(如同一个Servlet或JSP文件内的声明)。
<jsp:include>动作元素:由于<jsp:include>是在请求处理时动态地包含资源的,因此被包含的资源可以更加独立。它们不需要在编译时就被找到,也不需要与主JSP页面共享相同的上下文。
缓存
include指令:由于被包含的内容在编译时就已经确定,如果包含的内容发生了变化,整个JSP页面都需要重新编译。
<jsp:include>动作元素:由于<jsp:include>是动态地包含资源的,如果只有被包含的资源发生了变化,那么只有该资源需要被重新处理,而不需要重新处理整个JSP页面。
flush属性
用于指定是否将当前页面(使用包含元素的JSP文件,不是引入的文件)的输出内容刷新到客户端中 ,默认为false。
为了方便说明,这里举例,先放两段代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>dynamicInclude page</title>
</head>
<body>
dynamicInclude.jsp内的中文
<br />
<jsp:include page="included.jsp" flush="true" />
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>include</title>
</head>
<body>
<%Thread.sleep(2000);%>//休眠2秒
included.jsp内的中文<br />
</body>
</html>
先将dynam中的包含元素的flush属性设置为true(默认为false),启动服务器访问daynam页面,会直接显示处dynam中的信息,而在两秒后会再显示处included中的信息。
然后将flush设置为flase,重启服务器再次打开dynam,此时需要等待两秒,然后dynam和included两个文件的信息会一起显示出来。
在调用被引入的资源时,往往会先加载完调用资源后才一起刷新到客户端,如果不想这样,需要将flush设置为true。
与<jsp:param一起使用>
<jsp:include>和<jsp:param>一起使用,param会向include引入的页面传递一个参数。然后需要在被引入的页面的文件里,使用相关方法(比如request.getAttribute()、request.getParameter()等)或者使用隐式对象来访问。具体形式:
<jsp:include>
<jsp:param name="paramName" value="paramValue" />
</jsp:include>
其中,name是传递过去的参数的名字,paramValue是其值。这里引用一个示例方便说明:
<html>
<head>
<title>home.jsp</title>
</head>
<%!
String str = "param";
%>
<body>
<hr/>
<jsp:include page="included.jsp">
<jsp:param name="num1" value="<%=str %>"/>
</jsp:include>
</body>
</html>
<html>
<head>
<title>include</title>
</head>
<body>
<%
String str1=request.getParameter("num1"); //取得参数num1的值
int m1=Integer.parseInt(str1); //将字符串转换成整型
%>
<%=m1%>
</body>
</html>
使用param对象访问
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Forward Example</title>
</head>
<body>
<%-- 这里我们直接使用jsp:forward来转发请求到target.jsp,并传递参数 --%>
<jsp:forward page="included.jsp">
<jsp:param name="username" value="JohnDoe"/>
<jsp:param name="age" value="30"/>
</jsp:forward>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Target Page</title>
</head>
<body>
<h2>Received Parameters:</h2>
<p>Username: ${param.username}</p>
<p>Age: ${param.age}</p>
</body>
</html>
请求转发元素<jsp:forward>
请求转发元素可以将当前请求转发到其他的Web资源。转发执行之后,当前页面将不再执行,而是执行该元素指定的目标页面。具体格式:
<jsp:forward page="relativeURL" />
其中,relativeURL就是目标Web资源的地址 。
该请求转发是在服务端完成的,浏览器不知道请求的页面。浏览器上端不会转到新的页面资源。
例:
<%@ page import="java.util.Date" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>forword page</title>
</head>
<body>
<jsp:forward page="welcome.jsp" />//转发到welcome.jsp
</body>
</html>
浏览器上端显示:
与<jsp:param>一起使用:
方式与 <jsp:include>一样,需要在目标文件里实现。
JSP隐式对象
概述
在开发中,有一些对象需要频繁使用。为了简化,JSP2.0规范中提供了隐式(又叫内置)对象,它们是JSP默认创建,可以直接在JSP页面中使用。由于每个隐式对象的用法都有很多,这里只做简单介绍。几个常见的隐式对象:
名称 | 描述 |
---|---|
out | 用于页面输出 |
request | 得到用户请求信息 |
response | 服务器向客户端的回应信息 |
config | 服务器配置,可以得到初始化参数 |
session | 用于保存用户的信息 |
application | 所有用户的共享信息 |
page | 指当前页面转换后的Servlet类的实例 |
pageContext | JSP的页面容器 |
exception | 表示JSP页面所发生的异常,在错误页中才起作用 |
param | 允许你以更简洁的方式访问请求参数 |
out对象
out对象的作用与ServletResponse.getWriter()返回的PrintWriter对象非常相似,都是用于向客户端发送文本内容,是JspWriter的实例对象。区别在于,out对象的类型为JspWriter,相当于待缓存功能的PrintWriter。
out对象与Servlet引擎提供的缓冲区之间的工作关系
在JSP页面中,通过out对象写入数据相当于将数据插入JspWriter对象的缓冲区,只有调用了ServletResponse.getWriter()方法,缓冲区中的数据才能真正写入Servlet引擎所提供的缓冲区中。
<%
out.println("out对象输入<br />");
response.getWriter().println("PrintWriter对象输入");
%>
运行结果
out对象通过print写入数据后,直到整个JSP页面结束,out对象中输入缓冲区的数据才真正写入Servlet引擎提供的缓冲区中,而PrintWriter则直接把内容写入Servlet引擎提供的缓冲区中。Servlet引擎按照缓冲区中数据的存放顺序来输出内容。所以可以看到Writer在先,out在后。
当然,out对象也并非不能直接写入Servlet引擎缓冲区。若out对象的缓冲区已满,此时就会直接写入引擎的缓冲区。所以我们可以在开头的声明里将缓冲区(buffer)设为0kb,就可以让out对象直接写入缓冲区了。
pageContext对象
pageContext对象可以代表当前JSP页面的运行环境,并提供一系列用于获取其他隐式对象的方法。获取隐式对象:
方法名 | 功能描述 |
---|---|
JspWriter getOut() | 获取out对象 |
Object getPage() | ... |
ServletRequest getRequest() | ... |
ServletResponse getResponse() | ... |
HttpSession getSession() | ... |
Exception getException() | ... |
ServletConfig getServletConfig() | ... |
ServletContext getServletContext() | ... |
pageContext对象存储数据,通过操作属性实现。pageContext操作属性的相关方法:
void setAttribute(String name,Object value,int scope):设置pageContext对象的属性
Object getAttribute(String name,int scope):获取pageContext对象的属性
void removeAttribute(String name,int scope):删除指定范围内名称为name的属性
void removeAttribute(String name):删除所有范围内名称为name的属性
Object findAttribute(String name):从4个域对象中查找名为name的属性
其中参数name指定的是属性名称,scope指定的是属性的作用范围。pageContext对象的作用范围有4个值:
pageContext.PAGE_SCOPE:表示页面范围
pageContext.REQUEST_SCOPE:表示请求范围
pageContext.SESSION_SCOPE:表示会话范围
pageContext.APPLICATION_SCOPE:表示Web应用程序范围
调用findAttribute()方法查找属性时,会按照page、request、session和application的顺序异常进行查找。如果找到,则返回属性的名称,否则返回null。
exception对象
exception是Exception类的实例对象,用于封装JSP中抛出的异常信息。需要注意的是exception只能在属性"isErrorPage"为"true"的页面中使用。
当前JSP文件的代码出现异常后,会将当前异常的对象传递到page指令中"errorPage"属性指定的资源,在该资源中对异常进行处理。(可以看前面JSP指令的Page指令)