1、EL表达式
- EL表达式介绍:Expression Language (表达式语言),目的是替代JSP页面中的复杂代码
- EL表达式语法:${变量名}
下面通过一个实例来了解EL表达式的用法:
我们首先在一个JSP页面(1.jsp)中定义一个表单,其中有用户名和年龄两个输入框,表单数据会通过request对象提交到一个Servlet(ELServlet)
<!--1.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>表单提交</title>
</head>
<body>
<form action="/EL/ELServlet" method="post">
用户名: <input type="text" name="username" />
<br>
年龄:<input type="text" name="age" />
<input type="submit" value="提交" />
</form>
</body>
</html>
接着在ELServlet中获取表单值,转发到2.jsp并通过EL表达式显示出来
//ELServlet.java
@WebServlet(name = "ELServlet", urlPatterns = "/ELServlet")
public class ELServlet extends HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
doGet(request, response);
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
//获取表单内的username和age属性
String username = request.getParameter("username");
String age = request.getParameter("age");
//将获取的数据保存到request
request.setAttribute("username", username);
request.setAttribute("age", age);
//转发跳转到showEL.jsp通过EL表达式取出request中的username和age数据
request.getRequestDispatcher("/2.jsp").forward(request, response);
}
}
<!--2.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>通过EL表达式取数据</title>
</head>
<body>
姓名:${username}
<br>
<br>
年龄:${age}
</body>
</html>
效果如下,获取数据成功!
这里可能有人会有疑问,EL表达式只能获取request对象里存放的数据吗?——答案当然是否定的。
现在假设 EL表达式的大括号中只有属性名username时,会依次去四个作用域 page、request、session和application 中进行查找,看是否有属性名为username的属性。如果page没找到属性,就去 request 查找,如果request找到了这个属性,那么就不再接着进行查找了。
所以如果我们在上面的例子中,同时给page和request都设置一个key为username的参数,那么最终2.jsp页面显示的就是page中的key为username的值了。
但是我们这样做的话看起来不够直观,所以可以在输出的时候指定作用范围。每个作用域都对应一个 EL 中的名称,如下所示:
- page——>pageScope
- request——>requestScope
- session——>sessionScope
- application——>applicationScope
所以我们如果要跳过page直接输出request中的同名参数的话,就可以这么做
${requestScope.username}
之前的内容是将作用域中的字符串取出,除此之外,还可以将自定义类的对象存储到作用域中,并通过EL表达式直接取出。
假设我们有一个自定义类User,属性包含账号username和密码password,在Servlet中实例化一个新的User对象,账号为xwx617,密码为123456,并将这个对象存储到request对象中,转发到xxx.jsp,通过EL表达式取出对象中的账号和密码属性。
//Servlet
User user = new User("xwx617", "123456");
request.setAttributes("user", user);
request.getRequestDispatcher("xxx.jsp").forward(request, response);
//xxx.jsp
...
...
<body>
<!--以下三种写法效果一致-->
用户名:${user.username}
密码:${user.password}
用户名:${requestScope.user.username}
密码:${requestScope.user.password}
用户名:${user["username"]}
密码:${user["password"]}
</body>
我们可以发现第三种形式用到了[]的形式,这种形式通常用在key中含有特殊字符的时候,例如如果username改为user-name,那么就必须使用用户名:${user["user-name"]}
而不能使用点符号。
2、JSTL
- JSTL:JSP标签标签库(JavaServerPages Standard Tag Library)
- 与EL表达式的关系:JSTL通常与EL表达式合作完成JSP页面的编写
为什么要使用JSTL标签?
- 在jsp中不建议直接书写Java代码(规范性问题)
- EL表达式虽然可以解决“不用书写Java代码”问题,但对于复杂的数据(如数组、集合等)取值会很麻烦
- 使用JSTL标签配合EL表达式能很好的解决取复杂类型数据的问题,简化代码书写
JSTL常用标签:
下面通过实例来学习这些标签的用法:
首先我们需要向项目中加入JSTL的jar包,注意jar包不仅要加入到ide项目中,还需要加入到WEB-INF/lib中,具体细节可以参考我的另一篇博客:Java Web零碎知识点及常见问题
其次我们需要在JSP文件开头声明<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
,其中prefix属性可以自定义。
(1)set、out、remove标签的用法(假设request域中已经有一个key为user值为张三的数据):
注意到每个标签的开头都有一个c,这个c就是我们在JSP文件开头声明的prefix属性的值。
<!--3.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>JSTL常用标签</title>
</head>
<body>
<!--set、out、remove标签-->
<!--set标签主要是向指定的域中存放数据-->
<!--向request域中存放名为user的数据张三-->
<c:set var="user" value="张三" scope="request"/>
<hr>
<!--out标签主要是输出显示数据-->
<c:out value="${requestScope.user}"/>
<hr>
<!--remove标签用来移除域中存放的数据-->
<c:remove var="user" scope="request"/>
<c:out value="${requestScope.user}"/>
</body>
</html>
效果如下:
(2)if和choose标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>JSTL中的if和choose标签</title>
</head>
<body>
<!--if标签
test属性:接判断的条件,如果为true,则执行标签体中的内容
-->
<c:set var="age" value="12" scope="request" />
<c:if test="${requestScope.age==12}">
您的年龄为12岁
</c:if>
<hr>
<hr>
<!--choose标签:相当于if else,必须和when以及otherwise标签配套使用-->
<!--若test值为true就执行when包裹体中的内容,否则就执行otherwise中的内容,在HTML页面上就是显示与不显示的效果-->
<c:choose>
<c:when test="${age==12}">
您的年龄为12岁
</c:when>
<c:otherwise>
您的年龄不为12岁
</c:otherwise>
</c:choose>
</body>
</html>
效果如下:
(3)forEach标签
先创建一个Servlet,用来进行数据的存储
@WebServlet(name = "JSTLELServlet", urlPatterns = "/JSTLELServlet")
public class JSTLELServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建一个List集合存放数据
Map<String,Object> dataMap1 = new HashMap<>();
dataMap1.put("shopName", "联想笔记本");
dataMap1.put("address", "北京");
dataMap1.put("price", "4999.99");
Map<String,Object> dataMap2 = new HashMap<>();
dataMap2.put("shopName", "神州笔记本");
dataMap2.put("address", "南京");
dataMap2.put("price", "3999");
List<Map<String,Object>> list = new ArrayList<>();
list.add(dataMap1);
list.add(dataMap2);
//将List保存到request作用域中
request.setAttribute("list", list);
//在5.jsp中取出request中存放的List
request.getRequestDispatcher("/5.jsp").forward(request, response);
}
}
完成5.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>通过JSTL加TL表达式迭代List集合</title>
</head>
<body>
<table border="1px" cellspacing="0px">
<tr>
<td>商品名称</td>
<td>产地</td>
<td>价格</td>
</tr>
<c:forEach items="${requestScope.list}" var="map">
<tr>
<td>${map.shopName}</td>
<td>${map.address}</td>
<td>${map.price}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
可以看到,我们使用forEach标签将list集合中的数据循环输出成表格中的每个td。items属性的值就是集合或者数组,var属性的值就是集合中单个元素。
效果如下:
这就是JSTL和EL表达式的结合,非常方便,不需要在JSP页面上镶嵌Java代码。