一、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}
  • 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引入
  1. 引入jar包
  2. 在JSP里引入要使用标签库:在JSP里page指令下增加代码
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

小结

  • 在JSP里要使用JSTL标签库:
  1. 导入jar包
  2. 在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>

小结