一、JSP入门
1. 简介和原理
讲解
什么是JSP
- JSP:Java Server Page,Java服务器端页面技术,是Sun公司提供的一套规范。表面上是HTML+Java,但是JSP的本质是Servlet
- JSP和Servlet的对比:
- JSP:擅长页面显示的内容;不擅长于功能逻辑的处理
- Servlet:擅长于功能逻辑的处理;不擅长于页面显示的内容
response.getWriter().print()
- 实际开发中,是Servlet和JSP配合:业务功能逻辑给Servlet处理,页面显示给JSP处理
JSP的运行原理
- 了解JSP的运行原理(运行过程)
- JSP必须要部署在服务器软件里:由服务器软件把JSP文件,翻译转换成Servlet,实际运行的是Servlet的代码
- JSP的运行过程:
- jsp文件----翻译—>java文件(Servlet)----编译---->class文件
- 当我们访问一个jsp时,本质是Tomcat调用了Servlet的class程序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E1WHUi50-1583053503570)(img/1568014888554-1580788148522.png)]
- 服务器软件什么时候会把JSP翻译成Servlet?第一次访问时
小结
- 了解JSP的概念
- Java服务端页面技术。表面上看是HTML+Java,本质是Servlet
- JSP和Servlet对比:
- JSP擅长页面显示,不擅长处理逻辑
- Servlet擅长处理逻辑,不擅长页面显示
- 理解JSP的运行原理
- JSP不能使用浏览器直接打开,必须要部署到服务器软件上:由服务器软件把JSP翻译成Servlet,我们访问JSP,本质访问的是Servlet
- 一个JSP,什么时候会被服务器软件翻译成Servlet?第一次访问时
2. 基本语法
讲解
JSP里嵌套Java代码
表达式 | 作用 | 翻译成Servlet |
---|---|---|
<%=Java表达式%> | 把Java表达式结果输出到浏览器上,显示出来 | service方法里的:out.print(Java表达式) |
<% Java代码块 %> | 通常用于写if判断、for循环等逻辑代码 | service方法里的:Java代码块 |
<%! Java声明 %> | 声明成员变量、成员方法 | Servlet类里的: 成员变量、成员方法 |
嵌套Java表达式:<%=Java表达式 %>
- 用于把Java表达式的结果,显示到页面上
<%-- 输出显示当前日期 --%>
<%=new Date().toString()%>
嵌套Java代码片段:<% Java代码片段 %>
- 通常用于写if判断、for循环等逻辑代码
<%
//循环输出10次 红色的“hello”
for (int i = 0; i < 10; i++) {
%>
<font color="red">hello</font>
<%
}
%>
嵌套Java声明:<%! Java声明 %>
- 声明的是Servlet类的成员变量或者成员方法
<%!
public int add(int a, int b){
return a+b;
}
%>
<%=add(1, 2)%>
JSP的注释
<%-- JSP的注释,可以注释JSP文件里的一切内容 --%>
小结
- JSP里嵌套Java代码的三种方式
<%=Java表达式 %>
:把Java表达式的结果,输出显示到页面上<% Java代码块 %>
:可以写多行Java代码,通常用于逻辑处理,比如:if、for<%! Java声明 %>
:用于声明一些成员变量和成员方法
- JSP里注释的语法:
<%-- JSP注释 --%>
二、EL表达式
1. EL简介和基本语法
讲解
- EL:Expression Language,EL表达式。目的是用于:代替
<%=Java表达式 %>
,向页面输出显示内容 - 基本语法:
${表达式内容}
- 作用:
- 可以从域中获取数据显示到页面上,用于代替
<%=Java表达式 %>
- 可以进行数据运算
- 可以从域中获取数据显示到页面上,用于代替
小结
2. EL从域中获取数据
讲解
语法:
PageContext:${pageScope.key} <!-- 从pageContext里取key对应的数据,显示到页面上 -->
request: ${requestScope.key} <!-- 从request里取key对应的数据,显示到页面上 -->
session: ${sessionScope.key} <!-- 从session里取key对应的数据,显示到页面上 -->
ServletContext:${applicationScope.key} <!--从ServletContext里取key对应的数据,显示到页面上 -->
${key} <!-- 从四个域对象, 按从小到大的顺序,查找key对应的数据 -->
${key[索引].key}
:- 根据索引找,使用
[索引]
。 .key
可以是获取键值对里key对应的值,也可以是方法getKey()
的值
- 根据索引找,使用
示例:
1. 从域中取简单值
<%
request.setAttribute("user", "tom_req");
session.setAttribute("user", "tom_session");
application.setAttribute("user","tom_app");
%>
1. 从request域里获取use:${requestScope.user}
2. 从sessoin域里获取user:${sessionScope.user}
3. 从ServletContext域里获取user:${applicationScope.user}
4. 简化写法(从四个域中,按从小到大的顺序查找user):${user}
2. 从域中取JavaBean的值:
- 语法:
${JavaBean对象.属性名}
<%
Address address = new Address("广东", "深圳市");
User user = new User("小王", 20, address);
request.setAttribute("user", user);
%>
1. 获取user的姓名:${user.name}
2. 获取user的地址的省:${user.address.province}
public class Address {
private String province;
private String city;
public Address(String province, String city) {
this.province = province;
this.city = city;
}
//get/set...
}
public class User {
private String name;
private Integer age;
private Address address;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public User(String name, Integer age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
//get/set...
}
3. 从域中取集合的数据:
- 语法:
${集合[索引]}
<%
Address address1 = new Address("广东", "深圳市");
User user1 = new User("小王", 20, address1);
Address address2 = new Address("广西", "南宁市");
User user2 = new User("老王", 45, address2);
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
request.setAttribute("users", userList);
%>
1. 获取第1个user的姓名:${users[0].name}
2. 获取第2个user的地址的省:${users[1].address.province}
4. 从域中取map的数据:
- 语法:
${map.key}
<%
Address address1 = new Address("广东", "深圳市");
User user1 = new User("小王", 20, address1);
Address address2 = new Address("广西", "南宁市");
User user2 = new User("老王", 45, address2);
Map<String, User> map = new HashMap<>();
map.put("u1", user1);
map.put("u2", user2);
request.setAttribute("userMap", map);
%>
1. 获取u1的姓名:${userMap.u1.name}
2. 获取u2的地址的省:${userMap.u2.address.province}
小结
- EL从指定域里取数据
- 从request域里取:
${requestScope.key}
- 从session域里取:
${sessionScope.key}
- 从ServletContext域里取:
${applicationScope.key}
- 从request域里取:
- EL取域数据的简单写法:
${key}
- 从四个域对象中,按照从小到大的顺序(pageContext->request->session->servletContext),查找key对应的值
- EL取JavaBean对象的name属性值:
${JavaBean对象.属性名}
- EL取Map容器里key的值:
${map.key}
- EL取数组/集合里索引i的值:
${数组[i]}
拓展
- 域对象在不同环境里的对象名称
PageContext域 | ServletRequest域 | HttpSession域 | ServletContext域 | |
---|---|---|---|---|
JSP里的对象名称 | pageContext | request | session | application |
EL里的对象名称 | pageScope | requestScope | sessionScope | applicationScope |
3. EL可以进行数据运算
讲解
语法
- 基本数学运算:
+, -, *, /, %
- 比较运算:
>,<,>=,<=,==,!=
或者gt, lt, ge, le, eq, ne
- 逻辑运算:
&&, ||, !
或者and, or, not
- 判空:
empty
:容器类对象,里边没有内容,就是空的;null
和""
是空的0
:非空5
:非空"hello"
:非空""
:空null
:空空集合
:空的集合里有内容
:非空空Map
:空的Map里有内容
:非空
- 三元运算:
判断条件 ? 结果为true的值 : 结果为false的值
示例
<%
//数据准备
request.setAttribute("number", 10);
request.setAttribute("str", "hello");
request.setAttribute("list1", new ArrayList<>());
List<String> list2 = new ArrayList<>();
list2.add("");
request.setAttribute("list2",list2);
request.setAttribute("map1", new HashMap<>());
%>
- 基本数学运算:+, -, *, /, %
1+1 = ${1+1} <br>
number+1 = ${number+1}
<hr>
- 比较运算:>,<,>=,<=,==,!= 或者 gt, lt, ge, le, eq, ne <br>
number > 5? ${number > 5} <br>
str是"hello"? ${str == "hello"}
<hr>
- 逻辑运算:&&, ||, ! 或者 and, or, not<br>
number是5~15之间吗?${number>=5 && number<=15}, ${number>=5 and number<=15}
<hr>
- 判空:empty <br>
- 三元运算:判断条件?结果为true的值:结果为false的值<br>
0是空吗? ${empty 0?"是空":"不是空"} <br>---------不是空
""是空吗? ${empty ""?"是空":"不是空"} <br>--------是空
null是空吗? ${empty null?"是空":"不是空"} <br>------是空
list1是空吗?${empty list1?"是空":"不是空"} <br>-----是空
list2是空吗?${empty list2?"是空":"不是空"} <br>-----不是空
map1是空吗? ${empty map1?"是空":"不是空"} <br>------是空
小结
- 基本数学运算:
+,-,*,/,%..
- 比较运算:
>,<,>=,<=,==,!=
或者gt,lt,ge,le,eq,ne
- 逻辑运算:
&&,||,!
或者and, or, not
- 判空:
empty
- 三元运算:
条件?true的值:false的值
4. 拓展
- 如果项目里有项目路径,动态获取:
request.getContextPath()
- 在JSP里的解决方案:
- 使用
<%=Java表达式%>
:<%=request.getContextPath()%>
,得到项目路径 - 使用EL表达式的写法:
${pageContext.request.contextPath}
,得到项目路径
- 使用
三、JSTL标签库
讲解
JSTL简介
- JSTL:JSP Standard Tag Library, JSP标准标签库。提供了一些标签,这些标签有逻辑功能,比如:if判断、forEach循环等等。可以用来代替JSP里
<% Java代码片段 %>
- JSTL标签库包含5个子库,但是目前还用的上的只剩一个:core核心库,提供了if判断和循环遍历的标签
JSTL引入
-
引入jar包
-
在JSP里引入要使用标签库:在JSP里page指令下增加代码
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
小结
-
在JSP里要使用JSTL标签库:
- 导入jar包
- 在JSP里引入 要使用的标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2. JSTL的标签使用
目标
- 能够使用JSTL的
if
标签进行判断 - 能够使用JSTL的
forEach
标签进行循环遍历
讲解
JSTL标签本身不具备:从域里取数据、进行数据运算的能力
如果需要取数据或者进行运算:需要使用EL配合完成
3.1 c:if
标签
-
作用:用来进行判断的
-
语法:
<c:if test="判断条件,使用EL表达式进行判断"> 如果判断为true,这里的内容会生效;如果为false,这里内容相当于不存在 </c:if>
-
示例:
<c:if test="${age < 18}"> <span style="color:red;">未成年</span> </c:if> <c:if test="${age >= 18}"> <span style="color:green;">已成年</span> </c:if>
3.2 c:forEach
标签
-
作用:用来进行循环遍历的
-
基本for循环
- 语法:
- 注意:变量的值,被保存到了
PageContext
对象里(是最小的域对象,EL要获取${pageScope.key}
)
- 注意:变量的值,被保存到了
for(int i=0; i<=10; i++){ // i:定义的一个变量,变量名是i // 0:循环的开始值 // 10:循环的结束值 // i++:循环的步长,每次循环加几 }
<c:forEach var="变量名" begin="变量开始值" end="变量结束值" step="步长,每次循环加几"> 当前值是:${变量名} </c:forEach>
- 示例:
<c:forEach var="i" begin="1" end="10" step="1"> <span style="color:red;">${i}</span> </c:forEach>
- 语法:
-
增强for循环
- 语法:
for(String str:list){ //str:定义的一个变量,名称是str //list:被循环遍历的对象 }
<c:forEach items="循环遍历的对象,使用EL表达式获取到" var="变量名" varStatus="状态变量名"> 当前对象:${变量名}, 当前序号:${状态变量名.count}, 当前索引:${状态变量名.index}, 当前是否第一个:${状态变量名.first}, 当前是否最后一个:${状态变量名.last} </c:forEach>
- 示例:
<table border="1" width="500px" cellspacing="0"> <tr> <th>序号</th> <th>索引</th> <th>姓名</th> <th>年龄</th> </tr> <!-- 把域里的用户信息,循环显示到表格里。每个用户是一行 --> <c:forEach items="${userList}" var="user" varStatus="vs"> <tr> <td>${vs.count}</td> <td>${vs.index}</td> <td>${user.name}</td> <td>${user.age}</td> </tr> </c:forEach> </table>