标准标签库 和 EL表达式
关于标签库 和 EL表达式:
- 网页中的Java代码不方便维护,经常出现 空指针异常,不友好。
- SUN提供了自定义标签技术,用于替代Java代码。每个厂商都设计了自己标签。 标签无法通用。自定义标签语法复杂,实现繁琐成本高。
- Apache组织设计了“标准标签库 JSTL” 实现了绝大部分企业需要用的标签功能。 目前企业基本上都使用标准标签库解决问题。
使用标准标签库 和 EL表达式
EL 表达式
EL 表达式有标准标签库一起诞生, 与JSTL配合使用
- 自动化工作:可以在pageContext,request,session,application中子弹寻找 “attribute”
- 自动调用 get方法
- 自动处理空值
HelloWorld:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38<%@ page
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
import="java.util.*,entity.*"
%>
<%
//代表在Servlet中向 request 对象添加的数据
request.setAttribute("message", "Hello World!");
Emp emp = new Emp(1, "Tom", 1, null, 1, 1000,100);
request.setAttribute("emp", emp);
request.setAttribute("text", null);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL EL表达式演示</title>
</head>
<body>
<h1>EL表达式演示</h1>
<h2>Java 代码输出数据</h2>
<%
//定义变量,利用getAttribute寻获数据
String message =
(String)request.getAttribute("message");
Emp one = (Emp) request.getAttribute("emp");
String text=(String)request.getAttribute("text");
%>
<p>利用java表达式输出数据: <%=message%>
<%=one.getEname()%> <%=text%> </p>
<h2>EL表达式输出信息</h2>
<p>自动寻获 ${message},
自动调用get方法 ${emp.ename}
自动处理空 ${text} </p>
</body>
</html>
EL 语法
好处是: 简洁! 写的少,做的多
可以访问对象的 getXxx() 方法
1
obj.name 就是访问了 obj.getName()
可以访问数组、List集合的元素
1
2arr[下标]
list[下标]可以访问map
1
2map.key 得到 value
map['key'] 得到value以上方式的符合使用,无需类型转换
1
2list[1].ename
map.east.ename
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46<%@ page
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
import="java.util.*,entity.*"
%>
<%
int[] arr1 = {5,1,5,6};
String[] arr2 = {"Tom","Jerry"};
Emp[] arr3 = {new Emp(1, "光头强", 1, null, 1,100,10),
new Emp(1,"李大嘴",1,null,1,100,10)};
List<String> list1 = new ArrayList<String>();
list1.add("沉鱼落雁");
list1.add("明眸善睐");
List<Emp> list2 = new ArrayList<Emp>();
list2.add(new Emp(3,"擎天柱",1,null,1,10,1));
list2.add(new Emp(4,"大黄蜂",1,null,1,20,5));
Map<String, Emp> map=new HashMap<String, Emp>();
map.put("east", new Emp(6,"黄老邪",1,null,1,50,1));
map.put("north", new Emp(7,"洪七公",1,null,1,40,2));
request.setAttribute("arr1", arr1);
request.setAttribute("arr2", arr2);
request.setAttribute("arr3", arr3);
request.setAttribute("list1", list1);
request.setAttribute("list2", list2);
request.setAttribute("map", map);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL EL表达式演示2</title>
</head>
<body>
<h1>EL表达式演示2</h1>
<p>arr1: ${arr1[0]} ${arr1[1]} </p>
<p>arr2: ${arr2[0]} ${arr2[1]} </p>
<p>arr3: ${arr3[0].ename} ${arr3[0].empno}</p>
<p>list1: ${list1[0]}</p>
<p>list2: ${list2[0].ename}</p>
<p>map: ${map.east.ename} ${map['east'].ename}</p>
</body>
</html>
JSTL
使用步骤:
导包
1
2
3
4
5<dependency>
<artifactId>jstl</artifactId>
<groupId>jstl</groupId>
<version>1.2</version>
</dependency>在JSP 导入标签库
1
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
使用JSP标签
1
2<c:out value="${message}"></c:out>
out 标签用于输出信息, 自动替换特殊符合,相对输出安全
HelloWorld案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<%@ page
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
import="java.util.*,entity.*"
%>
<!-- 导入 core 核心标签库,使用前缀是c -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
request.setAttribute("message", "<Hello World!>");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSTL 演示</title>
</head>
<body>
<h1>JSTL演示</h1>
<!-- out 将信息输出到网页中 -->
<p><c:out value="${message}"></c:out></p>
<p>${message}</p>
<!-- JSTL 标签和 EL 表达式都是在服务器上处理的 -->
</body>
</html>
JSTL 有哪些常用标签:
JSTL标签的设计目的:用于取代浏览器的中的用于显示信息的Java代码
- out标签,用于输出数据,相对于EL表达式输出,out标签进行了特殊字符替换
for 循环标签: 1 计次循环, 2 集合遍历
1
2
3
4
5
6
7
8<c:forEach begin="1" end="5" step="2" var="i">
<p>${i}</p>
</c:forEach>
<ul>
<c:forEach items="${list}" var="emp" >
<li>${emp.empno}, ${emp.ename}</li>
</c:forEach>
</ul>if标签 单路分支标签
1
2
3<c:if test="${active>=100}">
<span style="color:red">赚钱了</span>
</c:if>多路分支标签
- choose
- when
- otherwise
1 | <c:choose> |
- import 包含标
1
<c:import url="footer.jsp"></c:import>
重要:JSP、JSP中的脚本、JSP中的指令(包含)、EL、JSTL、等都是在服务器端执行的。 执行结束以后将生成HTML发送到浏览器显示结果。
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77<%@ page
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
import="java.util.*,entity.*"
%>
<!-- 导入 core 核心标签库,使用前缀是c -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSTL 演示</title>
</head>
<body>
<h1>JSTL演示</h1>
<h2>forEach 标签</h2>
<!-- begin: 开始, end:结束 step: 步子 var:变量名
如下案例:从1开始循环, 每次增加2, 到5结束循环-->
<c:forEach begin="1" end="5" step="2" var="i">
<p>${i}</p>
</c:forEach>
<h2>集合的遍历</h2>
<%
//在实际开发中,如下数据应该在Servlet中生成
List<String> names = new ArrayList<String>();
names.add("佟湘玉");
names.add("白展堂");
names.add("莫小贝");
names.add("李大嘴");
request.setAttribute("names", names);
List<Emp> list=new ArrayList<Emp>();
list.add(new Emp(1, "霸波奔", 1, null, 1, 100,10));
list.add(new Emp(2, "奔波霸", 1, null, 1, 200,10));
request.setAttribute("list", list);
%>
<!-- forEach 遍历集合 -->
<ul>
<c:forEach items="${names}" var="name">
<li>${name}</li>
</c:forEach>
</ul>
<h2>遍历对象集合</h2>
<ul>
<c:forEach items="${list}" var="emp" >
<li>${emp.empno}, ${emp.ename}</li>
</c:forEach>
</ul>
<h2>if 标签</h2>
<!-- if 标签只能实现单路分支 -->
<%
request.setAttribute("active", 100);
%>
<c:if test="${active>=100}">
<span style="color:red">赚钱了</span>
</c:if>
<h2>多路分支标签</h2>
<!-- 多路分支包含其他情形,相当于else
choose 选择 when:当,当xxx的时候,otherwise其他情况 -->
<c:choose>
<c:when test="${active>=200}">
<span style="color:red">赚大了</span>
</c:when>
<c:when test="${active>=100}">
<span style="color:red">赚钱了</span>
</c:when>
<c:otherwise>
<span style="color:green">赔本了</span>
</c:otherwise>
</c:choose>
<h2>包含标签</h2>
<!-- 其功能与 jsp:include 一样 -->
<c:import url="footer.jsp"></c:import>
</body>
</html>
利用JSTL和EL重构 list-emp2.jsp:
导入标签库:
1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
更新头部组件包含
1
2
3
4
5<!-- Main Header 包含子页面 -->
<c:import url="/WEB-INF/include/header.jsp"/>
<!-- Left side 包含子页面 -->
<c:import url="/WEB-INF/include/left-side.jsp"/>更新集合遍历输出表格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<c:forEach items="${list}" var="emp">
<tr>
<td>${emp.empno}</td>
<td><c:out value="${emp.ename}"/></td>
<td>${emp.mgr}</td>
<td>${emp.hiredate}</td>
<td>${emp.deptno}</td>
<td>${emp.salary}</td>
<td>${emp.comm}</td>
<!-- onclick中出现"return false" 则会阻止事件
-点击事件的响应 -->
<td><a onclick="return confirm('真的删除?吗?')"
href="delete?empno=${emp.empno}"
class="btn btn-danger btn-xs"
><i class="fa fa-fw fa-remove"></i></a>
<a href="edit-emp?empno=${emp.empno}"
class="btn btn-success btn-xs"><i
class="fa fa-fw fa-edit"></i></a></td>
</tr>
</c:forEach>更新尾部组件包含
1
2
3
4
5<!-- Main Footer 包含 -->
<c:import url="/WEB-INF/include/footer.jsp"/>
<!-- Control Sidebar 包含 -->
<c:import url="/WEB-INF/include/sidebar.jsp"/>
利用JSTL和EL重构 add-emp.jsp:
导入JSTL
1
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
替换头部包含标签
1
2
3
4<!-- Main Header 包含子页面 -->
<c:import url="/WEB-INF/include/header.jsp"/>
<!-- Left side 包含子页面 -->
<c:import url="/WEB-INF/include/left-side.jsp"/>替换Java代码
1
2
3
4
5
6
7
8
9<select class="form-control" id="mgr" name="mgr">
<c:forEach items="${mgrs}" var="mgr">
<!-- 客户端选中员工名,发送到服务器是对应的员工号
value属性是发送到服务器上的值 -->
<option value="${mgr.empno}">
<c:out value="${mgr.ename}"/>
</option>
</c:forEach>
</select>替换尾部包含
1
2
3
4<!-- Main Footer 包含 -->
<c:import url="/WEB-INF/include/footer.jsp"/>
<!-- Control Sidebar 包含 -->
<c:import url="/WEB-INF/include/sidebar.jsp"/>
利用JSTL和EL重构 edit-emp.jsp:
导入JSTL
1
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
替换头部包含标签
1
2
3
4<!-- Main Header 包含子页面 -->
<c:import url="/WEB-INF/include/header.jsp"/>
<!-- Left side 包含子页面 -->
<c:import url="/WEB-INF/include/left-side.jsp"/>替换Java代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104<!-- Horizontal Form -->
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">添加新员工信息</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form class="form-horizontal"
method="post" action="update-emp">
<div class="box-body">
<div class="form-group">
<label for="empno"
class="col-sm-2 control-label">员工号</label>
<div class="col-sm-10">
<input type="text" class="form-control"
id="empno" name="empno" placeholder="员工号"
value="${emp.empno}"
readonly="readonly" >
</div>
</div>
<div class="form-group">
<label for="ename"
class="col-sm-2 control-label">姓名</label>
<div class="col-sm-10">
<input type="text" class="form-control"
id="ename" name="ename" placeholder="姓名"
value="<c:out value="${emp.ename}"/>">
</div>
</div>
<div class="form-group">
<label for="mgr"
class="col-sm-2 control-label">领导</label>
<div class="col-sm-10">
<select class="form-control" id="mgr" name="mgr">
<c:forEach items="${mgrs}" var="mgr">
<!-- 客户端选中员工名,发送到服务器是对应的员工号
value属性是发送到服务器上的值 -->
<c:choose>
<c:when test="${emp.mgr == mgr.empno}">
<option value="${mgr.empno}"
selected="selected">
<c:out value="${mgr.ename}"/>
</option>
</c:when>
<c:otherwise>
<option value="${mgr.empno}">
<c:out value="${mgr.ename}"/>
</option>
</c:otherwise>
</c:choose>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="hiredate"
class="col-sm-2 control-label">入职日期</label>
<div class="col-sm-10">
<input type="date" class="form-control"
id="hiredate" name="hiredate"
placeholder="入职日期"
value="${emp.hiredate}">
</div>
</div>
<div class="form-group">
<label for="deptno"
class="col-sm-2 control-label">部门编号</label>
<div class="col-sm-10">
<input type="text" class="form-control"
id="deptno" name="deptno"
placeholder="部门编号"
value="${emp.deptno}">
</div>
</div>
<div class="form-group">
<label for="salary"
class="col-sm-2 control-label">薪资</label>
<div class="col-sm-10">
<input type="number" class="form-control"
id="salary" name="salary"
placeholder="薪资"
value="${emp.salary}">
</div>
</div>
<div class="form-group">
<label for="comm"
class="col-sm-2 control-label">提成</label>
<div class="col-sm-10">
<input type="number" class="form-control"
id="comm" name="comm"
placeholder="提成"
value="${emp.comm}">
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-info pull-right">保存</button>
</div>
<!-- /.box-footer -->
</form>
</div>
<!-- /.box -->替换尾部包含
1
2
3
4<!-- Main Footer 包含 -->
<c:import url="/WEB-INF/include/footer.jsp"/>
<!-- Control Sidebar 包含 -->
<c:import url="/WEB-INF/include/sidebar.jsp"/>
显示老板名字问题
重构 ListEmpServlet
1
2
3
4
5
6
7//创建集合,缓存全部的员工号和员工名
Map<Integer, String> names = new HashMap<>();
for (Emp emp : list) {
names.put(emp.getEmpno(), emp.getEname());
}
//打桩测试 ...
request.setAttribute("names", names);重构 list-emp2.jsp
1
<td><c:out value="${names[emp.mgr]}"/></td>
测试
路径问题
Web编程时候有3套路径体系
- 浏览器视角的Web路径
- Java Web 用于程序的路径体系
- 本地操作系统文件路径体系
- ContextPath路径: Java web应用程序部署在Web服务器时候的部署文件夹。
- 浏览器视角的路径与Java WEB路径相差了一个ContextPath路径
- 将Java Web路径映射到浏览器视角的Web路径有多种解决方案:
- 使用相对路径
- 书写简单,当页面移动显示位置时候会css等资源加载失败出现404错误
- 利用 <c:url> 标签解决
- <c:url> 标签就是解决将Java WEB路径转化为 浏览器视角绝对路径而设计的标签
- 这个标签使用比较繁琐
- 利用EL表达式在路径前面添加ContextPath,这种方式简洁方便。
- 在Servlet中将 contextPath保存到request中叫 root
- 在页面中将所有 html 标签路径修改为 ${root}/…
案例, 将全部emp功能移动到 /emp 中, 目的是为了后续增加权限管理功能
- 更新全部功能的URL
修改 员工列表功能:
修改web.xml
1
2
3
4
5
6
7
8
9
10<servlet>
<description></description>
<display-name>ListEmpServlet</display-name>
<servlet-name>ListEmpServlet</servlet-name>
<servlet-class>day05.ListEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListEmpServlet</servlet-name>
<url-pattern>/emp/list</url-pattern>
</servlet-mapping>此时查看网页/emp/list会看到很多 404 错误,导致很多css、js文件没有加载,因为路径上增加了一层emp造成了浏览器视角路径错误,找不到对应资源了。
更新 ListEmpServlet, 将contextPath添加到request中,命名为root
1
2
3
4//将context路径保存request中, 用于将
//Java WEB目录映射到 浏览器视角WEB目录
String contextPath = request.getContextPath();
request.setAttribute("root", contextPath);更新 list-emp2.jsp 将全部html标签中的路径更新为 ${root}/
1
2
3
4
5
6
7
8
9
10
11
12
13
14<link rel="stylesheet" href="${root}/bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="${root}/bower_components/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="${root}/bower_components/Ionicons/css/ionicons.min.css">
<link rel="stylesheet" href="${root}/dist/css/AdminLTE.min.css">
<link rel="stylesheet" href="${root}/dist/css/skins/skin-blue.min.css">
...
<!-- jQuery 3 -->
<script src="${root}/bower_components/jquery/dist/jquery.min.js"></script>
<!-- Bootstrap 3.3.7 -->
<script src="${root}/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- AdminLTE App -->
<script src="${root}/dist/js/adminlte.min.js"></script>更新 header.jsp
1
2
3
4
5<img src="${root}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image">
...
<img src="${root}/dist/img/user2-160x160.jpg" class="user-image" alt="User Image">
...
<img src="${root}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image">更新 left-side.jsp
1
<img src="${root}/dist/img/user2-160x160.jpg" class="img-circle" alt="User Image">
测试 /emp/list