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 对象对应