第六章:EL表达式和JSTL
OVERVIEW
一、JavaBean
在软件开发时一些数据和功能需要在很多地方使用,为了方便将它们进行移植,sun公司提出了一种JavaBean技术。使用JavaBean技术可以对这些数据和功能进行封装,做到一次编写到处运行。
1.什么是JavaBean
JavaBean是Java开发语言中一个可以重复使用的软件组件,其本质上就是一个Java类,其遵循:
- 必须具有一个public无参的构造方法,这个构造方法可以是编译器自动产生的默认构造方法。
- 提供public的
setter()
方法和getter()
方法(私有属性),让外部程序设置和获取JavaBean属性。
package c7p1;
public class Book {
private double price;
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
注意:以上定义Book类实际上属于一个典型的JavaBean,没有定义构造方法但Java编译器在编译时自动生成一个默认的构造方法。
2.访问JavaBean的属性
在面向对象时经常会使用到类的属性,类的属性指的是类的成员变量。
在JavaBean中同样也有属性但其与成员变量不是一个概念,而是以方法定义的形式出现且命名必须遵循一定规范。
例如,在JavaBean中包含一个String类型的属性name,那么在JavaBean中必须至少包含getName()
和setName()
方法中的一个:
public String getName() {...}
public void setName(String name) {...}
- 如果一个属性只有getter方法,则该属性为只读属性。
- 如果一个属性只要setter方法,则该属性为只写属性。
- 如果属性两个方法都有,则该属性为读写属性。
注意:如果属性类型为boolean类型,则用is/set代替get/set的方式进行命名。
public boolean isMarried() {...} public void setMarried(boolean married) {...}
3.BeanUtils工具
通过调用JavaBean属性对应的setter与getter方法访问属性不总是可靠的,因此动态访问Java对象的属性是十分必要的。
动态访问Java对象的属性可以通过BeanUtils工具实现,BeanUtils工具中封装了许多类其中最核心的是org.apache.commons.beanutils包下的BeanUtils类:
方法声明 | 功能描述 |
---|---|
static void populate(Object bean, Map<String, ?extends Object> properties) | 根据指定名称/值对为相应的JavaBean属性设置值 |
static void setProperty(Object bean, String name, Object value) | 设置指定的属性值,传入的类型要求能转换成相应的属性类型 |
static String getProperty(Object bean, String name) | 返回指定bean指定属性的值,返回值类型为String类型 |
🚩具体使用如下:
package c7p2;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package c7p2;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import org.apache.commons.beanutils.BeanUtils;
public class BeanUtilsDemo {
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Person p = new Person();
//1.使用BeanUtils为属性赋值
BeanUtils.setProperty(p, "name", "Jack");
BeanUtils.setProperty(p, "age", 18);
//2.使用BeanUtils获取属性值
String name = BeanUtils.getProperty(p, "name");
String age = BeanUtils.getProperty(p, "age");
System.out.println(name + " " + age);
//3.创建map集合,用于存放属性及其属性值
HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("name", "Tonny");
hashMap.put("age", 18);
//4.使用populate()方法为对象的属性赋值
BeanUtils.populate(p, hashMap);
//5.打印赋值后的对象信息
System.out.println(p.getName() + " " + p.getAge());
}
}
成功使用BeanUtils中的setProperty()
、getProperty()
和populate()
方法操作了name和age两个属性,为其赋值并打印输出。
二、EL表达式
为获取Servlet域对象中存储的数据,在JSP2.0规范提供了EL表达式(Expression Language,一种简单的数据访问语言),简化开发难度。
1.EL表达式
EL语言可简化JSP页面的书写,因此在JSP的学习中掌握EL十分有必要:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
使用JSP表达式:<br />
用户名:<%=request.getAttribute("username") %><br />
用户名:<%=request.getAttribute("password") %><br />
<hr />
使用EL表达式:<br />
用户名:${username}<br />
用户名:${password}<br />
</body>
</html>
总结:从jsp页面代码中可以看出EL表达式确实一定程度上简化了jsp代码
值得注意的是,当域对象的值不存在时使用EL表达式返回的值为空字符串,而使用Java方式获取的值为null(报空指针异常)不安全。
2.EL语法:
(1)EL基础语法:
标识符:
EL中的表达式可以为任意的大小写字母、数字和下划线组成,但仍需要注意:
- 不能以数字开头、不能是EL中的保留字(and、or、gt…)、不能是EL隐式对象(pageContext…)
- 不能包含单引号、双引号、减号和正斜杠等特殊字符
正确答案:D
EL变量&常量:
EL表达式中的变量就是一个基本的存储单元,EL表达式可以将变量映射到一个对象上,如下所示:
${product}
EL表达式中的常量可分为布尔常量、整型常量、浮点数常量、字符串常量、Null常量
EL常量 | 说明 |
---|---|
布尔常量 | true、false |
整型常量 | Long.MIN_VALUE-Long.MAX_VALUE(-263~263-1) |
浮点数常量 | Double.MIN_VALUE-Double.MAX_VALUE(4.9E-324~1.8E308) |
字符串常量 | "ab'4c\"d5\\e" 表示的字符串为ab'4c"d5\e ,单引号不需要转义 |
Null常量 | 用于表示变量引用的对象为空,只有一个值null |
运算符:
EL表达式支持简单的运算(+、-、*、/、mod、div等),以下只摘录两种比较特殊的运算符:
点运算符(.):
EL中的点运算符可用于访问JSP页面中某些对象的属性,如JavaBean对象、List集合、Array数组等:
${customer.name}
解释:用于访问customer对象中的name属性
方括号运算符([ ]):
EL中的方括号运算符与点运算符相同,用于访问JSP页面中某些对象的属性(当获取的属性名中包含一些特殊符号时,如-
、?
等就只能使用方括号表达式)
${user["My-Name"]}
总结:实际上方括号运算符比点运算符使用范围更广
注意:
- 点运算符和 方括号运算符可互换:
${student.name}
==${student["name"]}
- 点运算符和 方括号运算符可结合使用:${users[0].userName}用于访问集合or数组中的第1个元素的userName属性。
(2)EL隐式对象:
在学习JSP技术时曾学习过隐式对象的应用,在EL技术中同样提供了11个隐式对象,如下:
注意:不要将JSP中的隐式对象与EL表达式中的混淆,只有pageContext对象是它们共有的,其他隐式对象毫不相关。
pageContext可以获取其他10个隐式对象,
pageScope、requestScope、sessionScope、applicationScope是用于获取指定域的隐式对象,
param和paramValues是用于获取请求参数的隐式对象,
header和headerValues是用于获取HTTP请求消息头的隐式对象,
cookie是用于获取Cookie信息的隐式对象,initParam是用于获取Web应用初始化信息的隐式对象。
正确答案:C
web域相关对象:
在web开发中PageContext、HttpServletRequest、HttpSession和ServletContext四个对象内部都定义了一个Map集合可存放数据,
这些Map集合有作用范围,在EL表达式中为了获取指定域对象中的数据,提供了pageScope、requestScope、sessionScope和applicationScope4个隐式对象:
${pageScope.userName}
${requestScope.userName}
${sessionScope.userName}
${applicationScope.userName}
注意:在使用EL表达式获取某个域中的属性时,可不用这些隐式对象来指定查找域直接引用属性名即可(默认以page、request、session、application的顺序进行查找)
param和paramValues对象:
在JSP页面中经常需要获取客户端传递的请求参数,EL中提供了param和paramValues两个隐式对象获取客户端访问JSP页面传递的参数:
param对象用于获取请求参数的某个值(Map类型),与request.getParameter()
方法相同(参数不存在返回空字符串 not null)
${param.num}
paramValues对象用于获取请求参数的所有值(数组),如果要获取请求参数的第1个值:
${paramValues.num[0]}
注意:如果一个请求参数有多个值,那么在使用param获取请求参数时,则返回请求参数的第1个值。
Cookie对象:
在JSP开发中经常需要获取客户端的Cookie信息,在EL表达式中提供了Cookie隐式对象(代表所有Cookie信息的Map集合)。
Map集合中元素的键为各个Cookie的名称,值则为对应的Cookie对象,具体如下:
获取cookie对象的信息:${cookie.userName}
获取cookie对象的名称:${cookie.userName.name}
获取cookie对象的值:${cookie.userName.value}
三、JSTL
为了降低JSP页面的复杂度、增强代码的重用性,sun公司还制定了一套标准标签库JSTL。
1.JSTL概念
从JSP1.1规范开始,JSP就支持使用自定义标签降低了JSP页面的复杂度,增强了代码的重用性。
sun公司推出了一套标准标签库JSTL(JavaServlet Pages Standard Tag Library),由5个不同功能的标签库共同组成:
标签库 | 标签库URI | 前缀 |
---|---|---|
Core | http://java.sun.com/jsp/jstl/core | c |
I18N | http://java.sun.com/jsp/jstl/fmt | fmt |
SQL | http://java.sun.com/jsp/jstl/sql | sql |
XML | http://java.sun.com/jsp/jstl/xml | x |
Functions | http://java.sun.com/jsp/jstl/functions | fn |
2.JSTL中的Core标签库
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>