JSP2 特性

时间:2021-06-22 15:45:20

JSP2 新特性

1、直接配置 JSP 属性

2、表达式语言

3、简化的自定义标签 API

4、Tag 文件语法

如果要使用 JSP2 语法,web.xml 文件必须使用 Servlet2.4 以上版本的配置文件。

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.1">
</web-app>

  

配置 JSP 属性

JSP 属性定义使用 <jsp-property-group/> 元素配置,主要包括以下 4 个方面。

1、是否允许使用表达式语言:使用 <el-ignored/> 元素确定,默认值为 false,即允许使用表达式语言

2、是否允许使用 JSP 脚本:使用 <scripting-invalid/> 元素确定,默认值为 false,即允许使用 JSP 脚本

3、声明 JSP 页面的编码:使用 <page-encoding/> 元素确定,配置该元素后,可以代替每个页面里 page 指令 contentType 属性的 charset 部分

4、使用隐式包含:使用 <include-prelude/> 和 <include-coda/> 元素确定,可以代替在每个页面里使用 include 编译指令来包含其他页面

(此处隐式包含的作用与 JSP 提供的静态包含的作用相似)

web.xml 的配置

<jsp-config>
<jsp-property-group>
<!-- 对哪些文件应用配置 -->
<url-pattern>/noscript/*</url-pattern>
<!-- 忽略表达式语言 -->
<el-ignored>true</el-ignored>
<!-- 页面编码字符集 -->
<page-encoding>UTF-8</page-encoding>
<!-- 不允许使用 java 脚本 -->
<scripting-invalid>true</scripting-invalid>
<!-- 隐式导入页面头 -->
<include-prelude>/inc/top.jsp</include-prelude>
<!-- 隐式导入页面尾 -->
<include-coda>/inc/bottom.jsp</include-coda>
</jsp-property-group>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>false</scripting-invalid>
</jsp-property-group>
<jsp-property-group>
<url-pattern>/inc/*</url-pattern>
<el-ignored>false</el-ignored>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>

  

表达式语言

表达式语言是一种简化的数据访问方式。使用表达式语言可以方便地访问 JSP 的隐含对象和 JavaBean 组件,在 JSP2 规范中,建议尽量使用表达式语言使 JSP 文件的格式一致,避免使用 Java 脚本。

表达式语言是 JSP2 的一个重要特性,它并不是一种通用的程序语言,而仅仅是一种数据访问语言,可以方便地访问应用程序数据,避免使用 JSP 脚本。

表达式语言的语法格式是:

${expression}

  

1、表达式语言支持的算术运算符和逻辑运算符

arithmeticOperator.jsp

<%@ page contentType="text/html" %>

<html>
<head>
<title>表达式语言 - 算术运算符</title>
</head>
<body>
<h2>表达式语言 - 算术运算符</h2>
<table border="1">
<tr>
<td><b>表达式语言</b></td>
<td><b>计算结果</b></td>
</tr> <!-- 直接输出常量 -->
<tr>
<td>\${1}</td>
<td>${1}</td>
</tr>
<!-- 计算加法 -->
<tr>
<td>\${1.2 + 2.3}</td>
<td>${1.2 + 2.3}</td>
</tr>
<!-- 计算加法 -->
<tr>
<td>\${1.2E4 + 1.3}</td>
<td>${1.2E4 + 1.3}</td>
</tr>
<!-- 计算减法 -->
<tr>
<td>\${-4 - 1.3}</td>
<td>${-4 - 1.3}</td>
</tr>
<!-- 计算乘法 -->
<tr>
<td>\${4 * 8}</td>
<td>${4 * 8}</td>
</tr>
<!-- 计算除法 -->
<tr>
<td>\${3 / 4}</td>
<td>${3 / 4}</td>
</tr>
<!-- 计算除法 -->
<tr>
<td>\${3 div 4}</td>
<td>${3 div 4}</td>
</tr>
<!-- 计算除法 -->
<tr>
<td>\${3 / 0}</td>
<td>${3 / 0}</td>
</tr>
<!-- 计算求余 -->
<tr>
<td>\${10 % 4}</td>
<td>${10 % 4}</td>
</tr>
<!-- 计算求余 -->
<tr>
<td>\${10 mod 4}</td>
<td>${10 mod 4}</td>
</tr>
<!-- 计算三目运算符 -->
<tr>
<td>\${(1 == 2) ? 3 : 4}</td>
<td>${(1 == 2) ? 3 : 4}</td>
</tr>
</table>
</body>
</html>

  

如果需要在支持表达式语言的页面中输出 "$" 符号,则在 "$" 符号前加转义字符 "\",否则系统以为 "$" 是表达式语言的特殊标记。

也可以在表达式语言中使用逻辑运算符:

logicOperator.jsp

<%@ page contentType="text/html" %>

<html>
<head>
<title>表达式语言 - 逻辑运算符</title>
</head>
<body>
<h2>表达式语言 - 逻辑运算符</h2>
数字之间的比较:
<table border='1'>
<tr>
<td><b>表达式语言</b></td>
<td><b>计算结果</b></td>
</tr> <!-- 直接比较两个数字 -->
<tr>
<td>\${1 < 2}</td>
<td>${1 < 2}</td>
</tr> <!-- 使用 lt 比较运算符 -->
<tr>
<td>\${1 lt 2}</td>
<td>${1 lt 2}</td>
</tr> <!-- 使用 > 比较运算符 -->
<tr>
<td>\${1 > (4 / 2)}</td>
<td>${1 > (4 / 2)}</td>
</tr> <!-- 使用 gt 比较运算符 -->
<tr>
<td>\${1 gt (4 / 2)}</td>
<td>${1 gt (4 / 2)}</td>
</tr> <!-- 使用 >= 比较运算符 -->
<tr>
<td>\${4.0 >= 3}</td>
<td>${4.0 >= 3}</td>
</tr> <!-- 使用 <= 比较运算符 -->
<tr>
<td>\${1 <= 2}</td>
<td>${1 <= 2}</td>
</tr> <!-- 使用 ge 比较运算符 -->
<tr>
<td>\${1 ge 2}</td>
<td>${1 ge 2}</td>
</tr> <!-- 使用 le 比较运算符 -->
<tr>
<td>\${1 le 2}</td>
<td>${1 le 2}</td>
</tr> <!-- 使用 == 比较运算符 -->
<tr>
<td>\${1 == 2}</td>
<td>${1 == 2}</td>
</tr> <!-- 使用 eq 比较运算符 -->
<tr>
<td>\${1 eq 2}</td>
<td>${1 eq 2}</td>
</tr> <!-- 使用 != 比较运算符 -->
<tr>
<td>\${1 != 2}</td>
<td>${1 != 2}</td>
</tr> <!-- 使用 ne 比较运算符 -->
<tr>
<td>\${1 ne 2}</td>
<td>${1 ne 2}</td>
</tr>
</table> <h2>字符之间的比较</h2>
<table>
<tr>
<td><b>表达式语言</b></td>
<td><b>计算结果</b></td>
</tr> <tr>
<td>\${'a' < 'b'}</td>
<td>${'a' < 'b'}</td>
</tr> <tr>
<td>\${'hip' > 'hit'}</td>
<td>${'hip' > 'hit'}</td>
</tr> <tr>
<td>\${'4' < 4}</td>
<td>${'4' < 4}</td>
</tr>
</table>
</body>
</html>

  

2、表达式语言的内置对象

使用表达式语言可以直接获取请求参数的值,可以获取页面中 JavaBean 的指定属性值,获取请求头及获取 page、request、session 和 application 范围的属性值等,这些都得益于表达式语言的内置对象。

表达式语言包含如下 11 个内置对象。

pageContext:代表该页面的 pageContext 对象,与 JSP 的 pageContext 内置对象相同

pageScope:用于获取 page 范围的属性值

requestScope:用于获取 request 范围的属性值

sessionScope:用于获取 session 范围的属性值

applicationScope:用于获取 application 范围的属性值

param:用于获取请求的参数值

paramValues:用于获取请求的参数值,与 param 的区别在于,该对象用于获取属性值为数组的属性值

header:用于获取请求头的属性值

headerValues:用于获取请求头的属性值,与 header 的区别在于,该对象用于获取属性值为数组的属性值

initParam:用于获取请求 web 应用的初始化参数

cookie:用于获取指定的 Cookie 的值

implicit-objects.jsp

<%@ page contentType="text/html" %>

<html>
<head>
<title>表达式语言 - 内置对象</title>
</head>
<body>
<h2>表达式语言 - 内置对象</h2>
请输入你的名字:
<!-- 通过表单提交请求参数 -->
<form action="implicit-objects.jsp" method="post">
<!-- 通过 ${param['name']} 获取请求参数 -->
你的名字 = <input type="text" name="name" value="${param['name']}" />
<input type="submit" value="提交" />
</form><br/> <%
session.setAttribute("user", "abc");
// 下面三行代码添加 Cookie
Cookie c = new Cookie("name", "awks");
c.setMaxAge(24 * 3600);
response.addCookie(c);
%> <table border="1">
<tr>
<td width="170"><b>功能</b></td>
<td width="200"><b>表达式语言</b></td>
<td width="300"><b>计算结果</b></td>
</tr> <tr>
<!-- 使用两种方式获取请求参数值 -->
<td>取得请求参数值</td>
<td>\${param.name}</td>
<td>${param.name}</td>
</tr>
<tr>
<td>取得请求参数值</td>
<td>\${param['name']}</td>
<td>${param['name']}</td>
</tr> <tr>
<!-- 使用两种方式获取请求头信息 -->
<td>取得请求头的值</td>
<td>\${header.host}</td>
<td>${header['host']}</td>
</tr>
<tr>
<!-- 使用两种方式获取请求头信息 -->
<td>取得请求头的值</td>
<td>\${header.host}</td>
<td>${header['host']}</td>
</tr> <!-- 获取 web 应用的初始化参数值 -->
<tr>
<td>取得初始化参数值</td>
<td>\${initParam.author}</td>
<td>${initParam.author}</td>
</tr> <!-- 获取 session 返回的属性值 -->
<tr>
<td>取得 session 的属性值</td>
<td>\${sessionScope.user}</td>
<td>${sessionScope.user}</td>
</tr> <!-- 获取指定 cookie 的值 -->
<tr>
<td>取得指定 cookie 的值</td>
<td>\${cookie['name'].value}</td>
<td>${cookie['name'].value}</td>
</tr>
</table>
</body>
</html>

  

3、表达式语言的自定义函数

表达式语言除了可以使用基本的运算符外,还可以使用自定义函数。通过自定义函数,能够大大加强表达式语言的功能。自定义函数的开发步骤非常类似于标签的开发步骤,定义方式也几乎一样,区别在于自定义标签直接在页面上生成输出,而自定义函数则需要在表达式语言中使用。

函数功能大大扩充了 EL 的功能,EL 本身只是一种数据访问语言,因此它不支持调用方法。如果需要在 EL 中进行更复杂的处理,就可以通过函数来完成。函数的本质是:提供一种语法允许在 EL 中调用某个类的静态方法。

自定义函数的开发步骤:

a、开发函数处理类:函数处理类就是普通类,这个普通类中包含若干个静态方法,每个静态方法都可定义成一个函数。实际上这个步骤也是可以忽略的 -- 完全可以直接使用 JDK 或其他项目提供的类,只要这个类包含静态方法即可。

Functions.java

package com.baiguiren;

public class Functions
{
// 对字符串进行反转
public static String reverse(String text)
{
return new StringBuffer(text).reverse().toString();
} // 统计字符串的个数
public static int countChar(String text)
{
return text.length();
}
}

  

b、使用标签库定义函数:定义函数的方法与定义标签的方法大致相似。在 <taglib.../> 元素下增加 <tag.../> 元素用于定义自定义标签:增加 <function.../> 元素只要三个子元素即可。

name:指定自定义函数的函数名

function-class:指定自定义函数的处理类

function-signature:指定自定义函数对应的方法

下面的标签库定义 (TLD) 文件将上面的 Functions.java 类中所包含的两个方法定义成两个函数。

<!-- 定义第一个函数 -->
<function>
<!-- 定义函数名: reverse -->
<name>reverse</name>
<!-- 定义函数的处理类 -->
<function-class>com.baiguiren.Functions<function-class>
<!-- 定义函数的实现方法 -->
<function-signature>java.lang.String reverse(java.lang.String)<function-signature>
</function>
<function>
<name>countChar</name>
<function-class>com.baiguiren.Functions</function-class>
<function-signature>int countChar(java.lang.String)<function-signature>
</function>

  

c、在 JSP 页面的 EL 中使用函数:一样需要先导入标签库,然后再使用函数。

<%@ page contentType="text/html" %>
<%@ taglib prefix="ruby" uri="/WEB-INF/mytaglib.tld" %> <html>
<head>
<title>使用自定义函数</title>
</head>
<body>
<h2>表达式语言 - 自定义函数</h2>
请输入一个字符串:
<form action="useFunctions.jsp" method="post">
字符串 = <input type="text" name="name" value="${param.name}">
<input type="submit" value="提交">
</form> <table border='1'>
<tr>
<td><b>表达式语言</b></td>
<td><b>计算结果</b></td>
</tr> <!-- 使用 reverse 函数 -->
<tr>
<td>\${ruby:reverse(param.name)}</td>
<td>${ruby:reverse(param.name)}</td>
</tr> <!-- 使用 countChar 函数 -->
<tr>
<td>\${ruby:countChar(param.name)}</td>
<td>${ruby:countChar(param.name)}</td>
</tr>
</table>
</body>
</html>

  

如上面程序中所示,导入标签库定义文件后(实际上也是函数库定义文件),就可以在表达式语言中使用函数定义库文件里定义的各函数了。

通过上面的介绍不难发现自定义函数的实质:就是将指定 Java 类的静态方法暴露成可以在 EL 中使用的函数,所以可以定义成函数的方法必须用 public static 修饰。

Tag File 支持

Tag File 是自定义标签的简化用法,使用 Tag File 可以无须定义标签处理类和标签库文件,但仍然可以在 JSP 页面中使用自定义标签。

以 Tag File 建立标签的步骤:

1、建立 Tag 文件,在 JSP 所支持 Tag File 规范下,Tag File 代理了标签处理类,它的格式类似于 JSP 文件。可以这样理解:如同 JSP 可以代替 Servlet 作为表现层一样,Tag File 则可以代替标签处理类。

Tag File 具有以下 5 个编译指令。

taglib:作用于 JSP 文件中的 taglib 指令效果相同,用于导入其他标签库

include:作用与 JSP 页面中的 include 指令效果相同,用于导入其他 JSP 或静态页面

tag:作用类似于 JSP 文件中的 page 指令,有 pageEncoding、body-content 等属性,用于设置页面编码等属性。

attribute:用于设置自定义标签的属性,类似于自定义标签处理类中的标签属性

variable:用于设置自定义标签的变量,这些变量将传给 JSP 页面使用

iterator.tag

<%@ tag pageEncoding="UTF-8" import="java.util.List" %>

<!-- 定义了 4 个标签属性 -->
<%@ attribute name="bgColor" %>
<%@ attribute name="cellColor" %>
<%@ attribute name="title" %>
<%@ attribute name="bean" %> <table>
<tr>
<td><b>${title}</b></td>
</tr> <!-- 取出 request 范围的 a 集合 -->
<%
List<String> list = (List<String>)request.getAttribute("a");
// 遍历输出 list 集合的元素
for (Object ele : list) {
%>
<tr>
<td bgColor="${bgColor}">
<%=ele%>
</td>
</tr>
<%
}
%>
</table>

  

Tag File 的命名必须遵守如下规则:tagName.tag。即 Tag File 的主文件名就是标签名,文件名后缀必须是 tag。将该文件存放在 Web 应用的某个路径下,这个路径相当于标签库的 URI 名。这里将其放在 /WEB-INF/tags 下,即此处标签库路径为 /WEB-INF/tags。

2、在页面中使用标签库时,需要先导入标签库,再使用标签。使用 Tag File 标签与普通自定义标签的用法完全相同,只是在导入标签时存在一些差异。由于此时的标签库没有 URI,只有标签库路径。因此导入标签时,使用如下语法格式:

<%@ taglib prefix="tagPrefix" tagdir="path" %>

其中,prefix 与之前的 taglib 指令的 prefix 属性完全相同,用于确定标签前缀;而 tagdir 用于指定标签文件的路径。

useTagFile.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %> <%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %> <html>
<head>
<title>迭代器 tag</title>
</head>
<body>
<h2>迭代器 tag file</h2>
<%
// 创建集合对象,保存到 request 的 a 属性
List<String> a = new ArrayList<String>();
a.add("疯狂 Java 讲义");
a.add("轻量级 Java EE 企业应用实战");
a.add("疯狂 Ajax 讲义");
// 将集合放入 request 范围
request.setAttribute("a", a);
%>
<h3>使用自定义标签</h3>
<tags:iterator bgColor="#99dd99" cellColor="#9999cc" title="迭代器标签" bean="a" />
</body>
</html>

  

TagFile 是自定义标签的简化。事实上,就如同 JSP 文件会编译成 Servlet 一样,Tag File 也会编译成标签处理类,自定义标签的后台依然由标签处理类完成,而这个过程由容器完成。

Tag File 中有如下几个内置对象:

request:与 JSP 脚本的 request 对象对应

response:与 JSP 脚本的 response 对象对应

session:与 JSP 脚本的 session 对象对应

application:与 JSP 脚本的 application 对象对应

config:与 JSP 脚本中的 config 对象对应

out:与 JSP 脚本中的 out 对象对应