文章目录
学习目标
JSTL
中常见的Core
标签库EL
中的常见隐式对象- 什么是
JavaBean
,什么是EL
表达式和JSTL
标签库
一、知识点:初始JavaBean
JavaBean
是一个
软件组件:在开发中可以重复使用,本质是一个Java
类
编码规范:具有一个公共的、无参的构造方法,对属性提供公共的setter
方法或getter
方法
- 访问
JavaBean
的属性
JavaBean
中的属性是以方法定义的形式出现的
例如JavaBean
中包含一个String
类型的属性name
,在JavaBean
中至少有getName()
和setName()
方法中的一个
如果一个属性只有getter
方法,则该属性为只读属性,
如果一个属性只有setter
方法,则该属性为只写属性,
如果一个属性既有getter
方法,又有setter
方法,则该属性为读写属性,
如果属性的类型为boolean
,它的命名方式应该使用is/set
而不是get/set
。
通过具体的案例来实现一个JavaBean
程序
public class Worker {
private String sid;
private String name;
private int age;
private boolean married;
//只读属性
public String getSid() {
return sid;
}
//只写属性
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//boolean类型是is/set
public boolean isMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
}
- BeanUtils工具
简介:Apache 软件基金会提供了一套简单、易用的 API ---- BeanUtils工具。
支持动态访问Java对象的属性。
(需要注意的是,BeanUtils 工具包还需要一个logging包来配合使用,logging包中包装了各种日志API的实现。)
BeanUtils类的常用方法
void populate(Object bean, Map<String, ? extends Object> properties)
根据指定的键值对为相应的JavaBean
属性设置值。- 写属性值
void setProperty(Object bean, String name, Object value)
第一个参数是对哪一个bean
进行操作,第二参数是属性名
,第三个参数是设置属性的值
设置指定的属性值,传入的类型要求能转换成相应属性的类型。 - 读属性值
String getProperty(Object bean, String name)
第一个参数是bean
对象,第二个参数是属性名,获取属性值
返回指定bean
指定属性的值,返回值类型为String
类型
实验1 使用BeanUtils读写属性
代码:
public class BeanUtilsDemo {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
//属性的写入
Person p1 = new Person();
BeanUtils.setProperty(p1, "name", "jack");
BeanUtils.setProperty(p1, "age", 9);
System.out.println(p1);
Person p2 = new Person();
BeanUtils.setProperty(p2, "fullInfo", "tom-3");
System.out.println(p2);
//属性的读取
String nameOfP1 = BeanUtils.getProperty(p1, "name");
String ageOfP1 = BeanUtils.getProperty(p1, "age");
System.out.println("p1: name = " + nameOfP1 + ", age = " + ageOfP1);
String nameOfP2 = BeanUtils.getProperty(p2, "name");
String ageOfP2 = BeanUtils.getProperty(p2, "age");
System.out.println("p1: name = " + nameOfP2 + ", age = " + ageOfP2);
//使用map的数据写属性
Map<String, Object> map = new HashMap<>();
map.put("name", "jerry");
map.put("age", 10);
Person p3 = new Person();
BeanUtils.populate(p3, map);
System.out.println(p3);
}
}
实验结果:
实验2 将请求参数封装到对象中
二、知识点:EL 表达式
1. 简介
- EL(Expression Language) 数据访问语言
- 可以代替Java表达式
<%=%>
以及部分Java程序片段<% %>
- EL表达式的语法是以
${
开始,以}
结束的,具体格式为${表达式}
例子:实验3
2. EL中的标识符
- 不能以数字开头
- 不能是EL中的保留字,如
and、or、gt
- 不能是EL隐式对象,如
pageContext
- 不能包含单引号、双引号、减号和正斜线等特殊字符:
'、"、-、/
- 合法的EL标识符:
username,username123,user_name,_username
不合法的:123username,or,user"name,pageContext
3. EL中的保留字
保留字就是编程语言里事先定义好并赋予了特殊含义的单词
EL中的保留字有:and,eq,gt,true,instanceof,or,ne,le,false,empty,not,It,ge,null,div,mod
例子:
通过EL表达式,${001}
没取出来,${x002}
取到了
4. EL中的变量
EL表达式中的变量就是一个基本的存储单元,EL表达式可以将变量映射到一个对象上。
EL表达式中的变量不用事先定义就可以直接使用。如:${product}
就可以访问变量product的值。
5. EL中的常量
布尔常量:两个值true和false
整形常量、浮点数常量、字符串常量、Null常量
6. EL中的运算符
- 点运算符
用于访问JSP页面中的某些对象的属性,格式为${customer.name}
- 方括号运算符
用于访问JSP页面中某些对象的属性,当获取的属性名中包含一些特殊符号,如-或?
等,就只能用方括号运算符来访问该属性
格式为:${user["My-name"]}
- 逻辑运算符:
&&、||、!
- empty运算法
判读某个对象是否为null,结果为布尔类型。格式:${empty var}
7. EL隐式对象
pageContext对象、Web域相关对象
EL主要是为了展示数据,所以它的隐式对象都和数据相关。
pageScope/requestScope/SessionScope/applicationScope
代表4个域对象,都可以用来保存数据
- pageContext对象:
(只要有pageContext对象,其他的jsp中的对象都可以通过get方法拿到。)
实验3 EL表达式的初步使用
servlet得到数据,交给jsp,jsp把数据展示出来
代码:
@WebServlet("/userinfo")
public class UserInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = "li4";
String newpassword = "123";
int times = 5;//已经登录的次数
String grade = "B";
/*
把数据交给jsp展示
save data
*/
//方法1:把数据保存到域对象reuqest中
//req.setAttribute("username",username);
//方法2:把数据放到域对象session中
req.getSession().setAttribute("username", username);
req.setAttribute("newpwd", newpassword);
req.setAttribute("times", times);
req.setAttribute("grade", grade);
//请求转发
RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/el01/userinfo.jsp");
dispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
用户名:<%=session.getAttribute("username")%><br/>
密码:<%=request.getAttribute("newpwd")%><br/>
登录次数:<%=request.getAttribute("times")%><br/>
等级:<%=request.getAttribute("grade")%><br/>
<hr/>
通过el表达式取数据:<br/>
用户名:${username}<br/>
密码:${newpwd}<br/>
次数:${times}<br/>
等级:${grade}<br/>
</body>
</html>
实验结果:
实验4 EL隐式对象 - pageContext
步骤:
- 创建pageContext.jsp文件
- 使用jsp表达式,取出请求中的URI
- 使用EL表达式,取出请求中的URI
- 使用EL表达式,获得响应头、服务器信息、Servlet注册名
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%--使用jsp表达式的方法--%>
<%=((HttpServletRequest) pageContext.getRequest()).getRequestURI()%>><br>
<%--使用el表达式的方法--%>
请求URI为:${pageContext.request.requestURI}<br>
Content-Type响应头:${pageContext.response.contentType}<br>
服务器信息为:${pageContext.servletContext.serverInfo}<br>
Servlet注册名为:${pageContext.servletConfig.servletName}<br>
</body>
</html>
实验结果:
实验5 EL隐式对象 - 域对象相关
步骤:
- 创建scopes.jsp文件
- 在四个域中都放入数据
- 分别把四个域里的数据取出来
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<% pageContext.setAttribute("userName", "zhang3");%>
<% request.setAttribute("userName", "li4");%>
<% session.setAttribute("userName", "wang5");%>
<% application.setAttribute("userName", "zhao6");%>
表达式\${pageScope.userName}的值为:${pageScope.userName}<br>
表达式\${requestScope.userName}的值为:${requestScope.userName}<br>
表达式\${sessionScope.userName}的值为:${sessionScope.userName}<br>
表达式\${applicationScope.userName}的值为:${applicationScope.userName}
<br>
表达式\${userName}的值为:${userName}
</body>
</html>
实验结果:
把pageContent注释掉
把request和pageContent都注释掉
把session也注释掉,还是有wang5的信息,因为session中的数据只要写入,数据就一直在
EL 其他隐式对象
param对象用于获取请求参数的某个值
paramValues对象返回请求参数所有值组成的数组
header对象用于获取请求头字段的某个值
headerValues对象用于返回请求头字符的所有值组成的数组
cookie对象获取客户端的Cookie信息
initParam对象获取web.xml文件中的一些初始化参数
步骤:
- 创建param.jsp文件
代码:
param.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<form action="paramTest.jsp">
user: <input type="text" name="user-name"><br>
hobby:<input type="text" name="hobby"><br>
hobby:<input type="text" name="hobby">
<input type="submit">
</form>
</body>
</html>
paramTest.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
${param["user-name"]}
<hr>
${param.hobby}
<hr>
${paramValues.hobby[0]} - ${paramValues.hobby[1]}
</body>
</html>
实验结果:
访问网页,并输入信息:http://localhost:8080/javabean_war_exploded/param.jsp
点击提交后,进入网页:http://localhost:8080/javabean_war_exploded/paramTest.jsp?user-name=aaa&hobby=学习&hobby=打球
三、知识点:JSTL
1. 什么是JSTL
Sun
公司制定的一套标准标签库(JavaServer Pages Standard Tag Library
),简称JSTL
。- 这个标签库由5个不同功能的标签库共同组成:
这5
个标签库分别指定了不同的URI
以及建议使用的前缀。
2. JSTL中的Core标签库
<c:out>
标签可以将一段文本内容或表达式的结果输出到客户端。
没有标签体的情况
<c:out value="value" [default="defaultValue"] [escapeXml="{true|false}"]/>
有标签体的情况,在标签体中指定输出的默认值
<c:out value="value" [excapeXml="{true|false}"]>
defaultValue
</c:out>
value
属性:用于指定输出的文本内容
default
属性:指定当value属性为null时所输出的默认值。
escapeXml
属性:用于指定是否将>、<、&、'、" 等特殊字符进行HTML编码转换后再进行输出,默认值为true。
<c:if>
用于完成JSP页面中的条件判断
没有标签体的情况
<c:if test="testCondition" var="result"
[scope="page|request|session|application"]/>
有标签体的情况,在标签体中指定要输出的内容
<c:if test="testCondition" var="result"
[scope="page|request|session|application"]>
body content
</c:if>
将test的测试结果保存在var中。
当test的值为true时,就显示body content的内容,如果为false,就不显示。
[]
中的内容可以省略
<c:choose>
标签,用于指定多个条件选择的组合边界,它必须与<c:when>
、<c:otherwise>
标签一起使用。<c:choose>
标签没有属性,在它的标签体中只能嵌套一个或多个<c:when>
标签和零个或一个<c:otherwise>
标签。
语法格式:
<c:choose>
Body content(<when> and <otherwise> subtags)
</c:choose>
<c:when>
标签,只有一个test属性,布尔类型。
如果test
属性是true
,执行标签体的内容:
<c:when test="testCondition">Body content</c:when>
<c:otherwise>
标签,没有属性,它必须作为<c:choose>
标签最后分支出现。
当所有<c:when>
标签的test
条件都不成立时,才执行和输出otherwise
标签体的内容:
<c:otherwise>conditional block</c:otherwise>
<c:forEach>
标签,用于迭代集合对象
中的元素,如Set
、List
、Map
、数组等,并且能重复执行标签体中的内容。
(不带中括号的,是必须要有的)
标签体中的内容body content会循环出现在页面上
items指定要迭代的集合对象,如set、list、map、数组等
通过var访问集合中的每个元素
varStatus访问当前var的状态
begin从哪个开始,end从哪个结束,step步长
迭代包含多个对象的集合:
<c:forEach [var="varName"] items="collection"
[varStatus="varStatusName"]
[begin="begin"][end="end"][step="step"]>
body content
</c:forEach>
---
迭代指定范围内的集合:
<c:forEach [var="varName"]
[varStatus="varStatusName"]
begin="begin" end="end" [step="step"]>
body content
</c:forEach>
实验6:JSTL - out 的使用
如果value属性是空值,就显示default中的内容
步骤:
- 创建01_out.jsp文件
- 引入标签库
<%@ taglib %>
- 添加内容,使用
c:out
标签输出内容 - 如果没有值显示
default
的内容:unknown user
- 在URL中配置userName的值,刷新就显示了userName的值
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<c:out value="${param.userName}" default="unknown user"/>
</body>
</html>
实验结果:
登录网站:http://localhost:8080/jstl_war_exploded/01_out.jsp
得到的结果:
在域名中指定userName
的值:http://localhost:8080/jstl_war_exploded/01_out.jsp?userName=zhang3
,得到的结果:
实验7: JSTL - if 的使用
步骤:
- 创建02_if.jsp文件
- 引入标签库
- 编写代码
- 根据请求参数,判断用户是新用户还是老用户
- 分别使用<c:out>和<c:if>判断
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<c:out value="${param.count > 0 ? '老用户':'新用户'}"/>
<c:if test="${param.count > 0}">
老用户
</c:if>
<c:if test="${!(param.count > 0)}">
new用户
</c:if>
</body>
</html>
实验结果:
访问网页:http://localhost:8080/jstl_war_exploded/02_if.jsp
在URL中设置count=2,访问网页:http://localhost:8080/jstl_war_exploded/02_if.jsp?count=2
实验8: jstl - choose - when - otherwise
步骤:
- 创建文件:03_choose.jsp
- 引入标签库:
<taglib core>
- 在
<c:choose>
中写内容 <c:when>
测试条件设置为成绩- 最后写
<c:otherwise>
- 当满足第一个条件时(分数大于70),就输出第一个条件的内容
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<c:choose>
<%-- <c:when test="${param.score >= 70}">xxx</c:when>--%>
<c:when test="${param.score >= 90}">优秀</c:when>
<c:when test="${param.score >= 80}">良好</c:when>
<c:when test="${param.score >= 60}">及格</c:when>
<c:otherwise>不及格</c:otherwise>
</c:choose>
</body>
</html>
实验结果:
设置分数为90,访问网页:http://localhost:8080/jstl_war_exploded/03_choose.jsp?score=90
设置分数为50,访问网页:http://localhost:8080/jstl_war_exploded/03_choose.jsp?score=50
将score>=70
那行注释打开,
设置的分数只要大于70,就显示下图
此时,设置分数为60时,显示
实验9: jstl - forEach
1. 指定范围
步骤:
- 创建文件04_forEach_01.jsp
- 引入标签库:
<taglib core>
- 使用
<c:forEach>
循环展示标签体内容 - 用EL表达式展示x,x就是变化的数据3、4、5…
status
可以通过点号.
显示它的一些属性:count\index\first\last\step
count
从1开始;first
是否是第一个;index
因为begin
是3,所以index
从3开始,step
步长- 查看结果
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<c:forEach begin="3" end="9" var="x" varStatus="status" step="2">
${status.count}, ${status.index}, ${status.first}, ${status.last}, ${status.step}
hello, ${x} <br>
</c:forEach>
</body>
</html>
实验结果:
2. 数组
步骤:
- 创建文件 05_forEach_02_array.jsp
- 引入标签库:
<taglib core>
- 使用
<% %>
定义数组(一般是通过java
代码将数组传给jsp
) - 使用
<c:forEach>
遍历数组,items
中写jsp
表达式 - 标签体中用
EL
表达式输出 - 查看结果
代码:
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%
String[] fruits = {"apple", "orange", "grape", "banana"};
%>
<c:forEach items="<%=fruits%>" var="fruit" begin="1" end="3" step="2" varStatus="status">
水果: ${fruit}:
${status.count}, ${status.index}, ${status.first}, ${status.last}, ${status.step}
<br>
</c:forEach>
</body>
</html>
实验结果:
3. list
步骤:
- 创建文件 06_forEach_03_list.jsp
- 引入标签库:
<taglib core>
- 定义一个List,调用add添加一些user
- 使用
<c:forEach>
遍历list,items指定list,使用var获得每个元素 - 标签体使用EL表达式输出var元素、status的内容
代码:
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%
List userList = new ArrayList();
userList.add("zhang3");
userList.add("li4");
userList.add("wang5");
userList.add("tom");
%>
<c:forEach items="<%= userList%>" var="user" varStatus="status">
用户: ${user}
${status.count}, ${status.index}, ${status.first}, ${status.last}, ${status.step}
<br/>
</c:forEach>
</body>
</html>
实验结果:
4. map
步骤:
- 创建文件 07_forEach_04_map.jsp
- 引入标签库:
<taglib core>
- 定义一个Map,key为Stirng,value为Integer。使用put添加数据
- 使用<c:forEach>标签遍历map
代码:
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("zhang3", 33);
map.put("li4", 44);
map.put("wang5", 55);
%>
<c:forEach items="<%=map%>" var="item">
用户:${item.key} -> ${item.value} <br>
</c:forEach>
</body>
</html>
实验结果:
Servlet + Jsp 结合实践
步骤:
- 创建students.html页面,呈现一张表格
- 创建一个students.jsp页面
- 创建bean文件夹,在下面创建文件User.java
- 创建controller文件夹,在下面创建文件QueryStudents.java,在其中添加用户信息,并将数据请求转发给jsp
- 在students.jsp文件中,使用jstl的forEach展示动态数据
- 访问网页:http://localhost:8080/jstl_war_exploded/QueryStudents,查看实验结果
代码:
students.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>序号</td>
<td>索引</td>
<td>姓名</td>
<td>年龄</td>
<td>是否是第一个</td>
<td>是否是最后一个</td>
</tr>
<c:forEach items="${data}" var="student" varStatus="status">
<tr>
<td>${status.count}</td>
<td>${status.index}</td>
<td>${student.name}</td>
<td>${student.age}</td>
<td>${status.first}</td>
<td>${status.last}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
User.java
package bean;
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
QueryStudents.java
package controller;
import bean.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/QueryStudents")
public class QueryStudents extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<User> students = new ArrayList<>();
students.add(new User("zhang3", 33));
students.add(new User("li4", 44));
students.add(new User("wang5", 55));
students.add(new User("zhao6", 66));
students.add(new User("tom", 77));
//请求转发
req.setAttribute("data", students);
req.getRequestDispatcher("students.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}