1. 产生背景
声明一个用于存储用户信息的 JavaBean
public class User {
private String id; // 用户id
private Bank bank; // 银行信息
// 省略 get set
}
public class Bank {
private String name; // 银行名称
private String number; // 银行卡号
}
我们可以使用 JSP 标准动作获取用户的 id
<jsp:getProperty name="user" property="id"/>
但如果我们想要获取用户的银行卡号时,JSP 标准动作中没有提供这种嵌套式访问机制,所以要想实现这个功能,就只能在 JSP 页面中通过 Java 代码来获取。
在 MVC 设计模式中,JSP 只是视图,视图的任务就是显示响应,而不是在 JSP 中做任何关于程序控制和业务逻辑的事情。所以在 JSP 页面中应该尽可能少的、或者是完全不出现 Java 代码。
在 JSP 2.0 之后,可以使用 EL (Expression Language) 表达式来处理这样的的问题。EL 表达式提供了在 JSP 中简化表达式的方法,目的是为了尽量减少 JSP 页面中的 Java 代码,使得 JSP 页面的处理程序编写起来更加简洁,便于开发和维护。
2. 组成部分
2.1 EL 表达式语法
${ expression }
expression 指定要输出的内容,可以是字符串或 EL 运算符组成的表达式
2.2 EL 运算符
上面的语法中讲到 EL 运算符,接下来我们来看一下有哪些运算符,这样大家对于 ${ expression } 的中 expression 可以写哪些内容心里有个底,后面的内容我们会对这些运算符进行运用,并对注意点逐个进行验证!
2.2.1 算术运算符
| 算术运算符 | 说明 |
|---|---|
| + | 加 |
| - | 减 |
| * | 乘 |
| / 或 div | 除 |
| % 或 mod | 取余 |
+在 EL 表达式中只作为算术运算符,而不能当作字符串连接符
2.2.2 关系运算符
| 关系运算符 | 说明 |
|---|---|
| == 或 eq | 等于 |
| != 或 ne | 不等于 |
| < 或 lt | 小于 |
| > 或 gt | 大于 |
| <= 或 le | 大于等于 |
| >= 或 ge | 小于等于 |
2.2.3 逻辑运算符
| 逻辑运算符 | 说明 |
|---|---|
| && 或 and | 与运算 |
| || 或 or | 或运算 |
| ! 或 not | 非运算 |
2.2.4 条件运算符
| 条件运算符 | 说明 |
|---|---|
| ? : | ? 前面的条件表达式为 true 时,执行 : 前面表达式,否则执行 : 后面的表达式 |
2.2.5 取值运算符
| 取值运算符 | 说明 |
|---|---|
| . | 访问对象中的属性 |
| [] | 访问对象中的属性 访问数组或集合 动态获取变量的值 |
当属性名包含
-、.、,等特殊符号时,只能使用[]运算符
2.2.6 验证运算符
| 验证运算符 | 说明 |
|---|---|
| empty | 以下几种情况返回 truenull长度为零的 String无元素的集合或数组 |
2.3 从四大域中访问数据
四大域指的就是 pageContext、request、session、application,当我们没有使用 2.4 节中的内置对象时,都是从四大域中访问数据
${ varName }的执行流程
2.3.1 访问基本数据类型
<%
pageContext.setAttribute("id", 1);
request.setAttribute("age", 18);
session.setAttribute("name", "zhangfei");
application.setAttribute("weight", 75.5);
%>
${ id } <br>
${ age } <br>
${ name } <br>
${ weight } <br>
执行结果
当不同域中存在相同的属性 name,就会按照上面的流程获取
<%
pageContext.setAttribute("name", "pageContext");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>
${ name }
访问到的是 pageContext 域中的值
接下来我们注释掉 pageContext
<%
// pageContext.setAttribute("name", "pageContext");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>
${ name }
执行结果
当我们注释掉 request 时,访问到的是 session,当注释掉 session 之后,访问到 application,那全部都注释掉,会是什么结果呢?
<%
// pageContext.setAttribute("name", "pageContext");
// request.setAttribute("name", "request");
// session.setAttribute("name", "session");
// application.setAttribute("name", "application");
%>
我们可以发现,使用 EL 表达式访问四大域中的数据时,会依次从 pageContext、request、session、application 中获取数据,获取不到时不展示。
那有没有办法从指定域中获取数据呢?有的,2.4.2 节我们会介绍。
接下来我们来使用一下算术运算符,关系运算符、逻辑运算符使用方法类似,就不做演示了
<%
request.setAttribute("name", "zhangfei");
%>
${ name + 1 }
会出现 java.lang.NumberFormatException,验证了我们之前所说的 + 在 EL 表达式中只作为算术运算符,而不能当作字符串连接符
使用整型属性进行算术运算
<%
request.setAttribute("age", 18);
%>
${ age + 1 }
结果正确
接下来使用一下条件表达式
<%
request.setAttribute("name", "zhangfei");
%>
${ name.equals("zhangfei") ? "yes" : "no" }
2.3.2 访问对象
新建 User 类
public class User {
private int age;
private String name;
// 省略 get set
}
这里有个注意点,User 类不能放在默认包(src)下,不然会出现
Classes from the default package must not be referenced from JSP file
我们可以使用取值运算符 . [] 获取对象中的属性
<%
User user = new User(18, "zhangfei");
session.setAttribute("user", user);
%>
${ user.name } <br>
${ user.["name"] } <br>
还可以使用 [] 动态获取变量的值
<%
request.setAttribute("var", "name");
%>
${ user[var] }
由于 Java 的标识符不能包含 -、. 、, 等特殊符号,介绍取值运算符时讲到的注意事项等到使用 Map 集合时再验证!
2.3.3 访问数组或集合
我们可以使用取值运算符 [] 访问数组或集合
<%
List<String> list = new ArrayList<>();
list.add("C");
list.add("Java");
list.add("C++");
request.setAttribute("list", list);
String[] array = new String[]{"C", "Java", "C++"};
session.setAttribute("array", array);
%>
${ list[0] } <br>
${ array[1] } <br>
执行结果
接下来我们使用一下验证运算符
<%
request.setAttribute("object", null);
request.setAttribute("str1", "");
request.setAttribute("str2", "value");
request.setAttribute("arr1", new String[]{});
request.setAttribute("arr2", new String[]{"element"});
request.setAttribute("list1", new ArrayList<>());
request.setAttribute("list2", Collections.singleton("element"));
%>
${ empty object } <br>
${ empty str1 } <br>
${ empty str2 } <br>
${ empty arr1 } <br>
${ empty arr2 } <br>
${ empty list1 } <br>
${ empty list2 } <br>
访问 Map 集合
<%
Map<String, String> map = new HashMap<>();
map.put("o.name", "zhangfei");
request.setAttribute("map", map);
%>
${ map.o.name }
获取不到值,这时因为属性名中存在特殊字符 .,这时需要使用 [] 运算符访问数据
<%
Map<String, String> map = new HashMap<>();
map.put("o.name", "zhangfei");
request.setAttribute("map", map);
%>
${ map["o.name"] }
2.4 从内置对象中访问数据
内置对象可以分为六类,分别是:
- JSP
- 作用域
- 请求参数
- 请求头
- Cookie
- 初始化参数
除了 pageContext 内置对象,其他内置对象本质上是一个 Map 类
2.4.1 JSP
- pageContext
(1)本质
javax.servlet.jsp.PageContext
(2)使用
比较常见的用法是获取项目路径
${ pageContext.request.contextPath }
2.4.2 作用域
- pageScope
- requestScopre
- sessionScope
- applicationScope
(1)本质
pageContext.getAttribute(var);
request.getAttribute(var);
session.getAttribute(var);
application.getAttribute(var);
(2)使用
还是使用上面的例子,但是这次我们从指定域中获取数据
<%
pageContext.setAttribute("name", "pageContext");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>
${ pageScope.name } <br>
${ requestScope.name } <br>
${ sessionScope.name } <br>
${ applicationScope.name } <br>
2.4.3 请求参数
- param
- paramValues
(1)本质
request.getParameter(var);
request.getParameterValues(var);
(2)使用
param.html
<form action="param.jsp" method="POST">
姓名:<input type="text" name="userName"> <br>
爱好:<input type="checkbox" name="hobby" value="C">C
<input type="checkbox" name="hobby" value="Java">Java
<input type="checkbox" name="hobby" value="C++">C++ <br>
<input type="submit" value="提交">
</form>
param.jsp
${ param.userName } <br>
${ paramValues.hobby[0] } <br>
运行结果
2.4.4 请求头
- header
- headerValues
(1)本质
request.getHeader(var);
request.getHeaders(var);
(2)使用
${ header.Host } <br>
${ headerValues.Cookie[0] }
2.4.5 Cookie
- cookie
(1)本质
Cookie[] cookies = request.getCookies();
Map<String, Cookie> map = new HashMap<>();
for (Cookie cookie : cookies) {
map.put(cookie.getName(), cookie);
}
(2)使用
${ cookie.JSESSIONID.name } <br>
${ cookie.JSESSIONID.value } <br>
2.4.6 initParam
- initParam
(1)本质
servletContext.getInitParameter(var)
(2)使用
在 web.xml 中配置初始化参数
<web-app>
<context-param>
<param-name>key1</param-name>
<param-value>value1</param-value>
</context-param>
<context-param>
<param-name>key2</param-name>
<param-value>value2</param-value>
</context-param>
</web-app>
initParam.jsp
${ initParam.key1 } <br>
${ initParam.key2 } <br>