JSP:EL:JSTL
为了提升用户体验,在WEB-INF下的web.xml配置全局错误配置
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
- 概念:Java Server Page:Java服务器页面
- 一个特殊的页面,可以定义html标签,也可以定义java代码
- 用于简化书写

- 本质:Servlet 的实现类:将jsp转换成.java文件并编译成对应的.class文件【tomcat下的work目录(运行时产生的资源文件)】
-
生成的类是 继承自org.apache.jasper.runtime.HttpJspBae继承自HttpServlet
-
一、jsp的脚本:JSP定义java代码的方式
在IDEA控制台上复制Using CATALINA_BASE后面的路径,打开它,找到work目录,点点点,就可以找到对应项目生成的.java和.class文件了
-
<% 代码 %>: 定义的java代码正在service方法中。service可以写啥,里面就可以写啥 -
<%= 代码 %>: 定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本就可以定义什么 -
<%! 代码 %>: 【基本不用】定义的java代码在jsp转换后java类的成员位置
二、指令
作用: 配置JSP页面,导入资源文件
1.格式
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
2.指令名称分类
-
page:配置JSP页面的-
contentType:等同于response.setContentType(""),text/html;charset=utf-8- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
-
import:导包 -
errorPage:当前页面发生异常后,会自动跳转到指定的错误页面【避免用户看到报错信息,不友好!】 -
isErrorPage:标识当前页面是否也是错误页面【用于写日志】。标识之后就可以使用内置对象exception,-
true:是,可以使用内置对象exception;显示错误原因<%= exception.getMessage() %> -
false:否。默认值。不可以使用内置对象exception
-
-
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" language="java" buffer="16kb" %>
<%@ page isErrorPage="true" %>
-
include:页面包含的。导入页面的资源文件【比如很多页面共享一些标签,可以使用这个进行导入】
<%@include file=top.jsp"" %>
-
taglib:导入标签库资源,后面介绍
<%@ taglib prefix="c" url="http://java.sun.com/jsp/jstl/core" %>
prefix:前缀,自定义的导入的标签库的命名空间,最好使用约定俗称的前缀
三、注释
- HTML注释,只能注释html代码片段
<!-- -->
- jsp注释:可以注释所有【推荐使用】
<%-- --%>
四、JSP内置对象:【需要记住】
- 在jsp中不需要获取和创建,可以直接使用的对象:tomcat在编译.jsp文件是会提前将一个对象进行创建,然后才把.jsp中的对象放到对应的位置!
- 一共有9个内置对象。
| 变量名 | 真实类型 | 作用 |
|---|---|---|
| pageContext | PageContext | 【域对象】当前页面共享数据,还可以获取其他八个内置对象,pageContext.getXxx()
|
| request | HttpServletRequest | 【域对象】一次请求访问的多个资源(转发getRequestDispatcher) |
| session | HttpSession | 【域对象】一次会话的多个请求间的共享数据 |
| application | ServletContext | 【域对象】所用用户间共享数据 |
| response | HttpServletResponse | 响应对象 |
| page | Object | 当前页面(Servlet)的对象,this的引用 |
| out | JspWriter | 输出对象,数据输出到页面上 |
| config | ServletConfig | Servlet的配置对象 |
| exception | Throwable | 异常对象,需要提前使用指令<%@ page isErrorPage="true" %>
|
1.out: 字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
response.getWriter()与out.write()的区别
tomcat服务器真正给客户端做出响应之前,会先找
response.getWriter.write()的缓冲区数据,然后在找out.write()缓冲区数据;response.getWriter().write数据输出永远在out.write()之前。

五、EL表达式
Expression Language 表达式语言;替换和简化jsp页面中java代码的编写;【建议在域中存的名字与对象的名字一样】
1、语法及注意事项
- 语法
${表达式}
- 注意事项:jsp默认支持el表达式。如果要忽略el表达式,如下方式
- 【使用转义字符】:
\${表达式} - 【不推荐使用】设置jsp中page指令中:
isELIgnored="true"忽略当前jsp页面中所有el表达式
- 【使用转义字符】:
2.【功能】运算符号
- 算数运算符:
+、-、*、\(或者div)、%(mod) - 比较运算符:
>、<、>=、<=、==、!= - 逻辑运算符:
&&(and)、||(or)、!(not)
${3 + 4} ${3 - 4} ${3 / 4} ${3 div 4} ${3 % 4} ${3 mod 4}
${3 > 4} ${3 < 4} ${3 >= 4} ${3 <= 4} ${3 == 4} ${3 != 4}
${4 >= 3 && 3 <= 6 and 1 >= 0 || 1 == 1 or 2 == 2 and !(3 < 2) and not(3 == 4)}
- 空运算符:
empty- 用于判断字符串、集合、数组对象是否为null或者长度是否为0
-
${empty list}:判断字符串、集合、数组对象是否为null或者长度为0 -
${not empty str}:判断字符串、集合、数组对象是否不为null并且长度>0
<%
List<String> lis1 = new ArrayList<>();
List<String> lis2 = new ArrayList<>(); lis2.add("lis2");
Map<String, String> hm1 = null;
Map<String, String> hm2 = new HashMap<>(); hm2.put("hm2", "hm2");
pageContext.setAttribute("lis1", lis1); pageContext.setAttribute("lis2", lis2);pageContext.setAttribute("hm1", hm1);pageContext.setAttribute("hm2", hm2);
%>
${empty lis1} <br> <!-- 获取值的语法2,从小域到大域找 -->
${not empty lis2} <br>
${empty hm1} <br>
${! empty hm2} <br>
3.【功能:重要】获取值的语法
el表达式只能从域对象中获取值
1.${域名称.键名}:从指定域中获取指定键的值
| 域名称 | 原始对象 | 范围 |
|---|---|---|
| pageScope | pageContext | 最小,当前页面 |
| requestScope | request | 小,一次请求与响应之间Attribute
|
| sessionScope | session | 大,一次会话之间 |
| application | application | 最大,整个项目运行周期 |
举例:在request域中存储了name=张三 ,获取方式:${requestScope.name}
2.${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止
1、2的案例如下
<%
pageContext.setAttribute("name", "pageContext");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>
${ pageScope.name } <br>
${ requestScope.name }<br>
${ sessionScope.name }<br>
${ applicationScope.name }<br>
<hr>
${name}
3.获取对象、List集合、Map集合的值
- 【对象】:
${域名称.键名.属性名}:本质上会去调用对象的getter方法【实现原理:javaBean规范获取属性名+反射】
通过javabean对象的属性来获取【属性名】:setter或者getter方法,去掉set或者get,再将剩余部分首字母小写这个就是对象的属性【如果有对应的成员变量,属性名一般和对应的成员变量名相同】.比如:
getName() -> Name -> name
【逻辑视图】:可以根据需求自定义其他功能性的getter与setter方法,这些方法没有对应的成员变量,一般用于返回特定格式的数据
<%
// User是一个javaBean类,添加了一个String getStrBir()方法,使用
// return new SimpleDateFormat("yyyy年MM月dd日").format(this.birthday)
// 返回字符串形式的Date类型的Birthday成员变量
User user = new User();
user.setName("小明");
user.setAge(22);
user.setGender("male");
user.setBirthday(new Date());
pageContext.setAttribute("user", user);
%>
${pageScope.user.name} <br>
${pageScope.user.age} <br>
${pageScope.user.gender} <br>
${pageScope.user.birthday} <br>
${pageScope.user.strBir} <br>
- 【List集合】:
${域名称.键名[索引]}
如果角标越界了,内部优化,不会把错抛出来,当前页面不会抛错
<%
User user1 = new User("小伟",22,"male",new Date());
ArrayList<Object> list = new ArrayList();
list.add("hello");
list.add(user1);
request.setAttribute("list", list);
%>
${requestScope.list} <br>
${requestScope.list[0]} <br>
${requestScope.list[100]} <br> <!-- 不会抛错 -->
${requestScope.list[1].name} <br>
${requestScope.list[1].strBir} <br>
- 【Map集合】:
${域名称.键名.key名称}-
${域名称.键名["key名称"]},(有点像python的字典)
<%
User user2 = new User("小翔",24,"male",new Date());
HashMap<String, Object> map = new HashMap<>();
map.put("name", "小鹏");
map.put("user2", user1);
session.setAttribute("map", map);
%>
${sessionScope.map.name} <br>
${sessionScope.map["name"]} <br>
${sessionScope.map.user2.name} <br>
${sessionScope.map["user2"].strBir} <br>
4.隐式对象:
el表达式中有11个隐式对象。
- pageContent:可以获取jsp其他八个内置对象
-
${pageContext.request.contextPath}:动态获取虚拟目录。
-
<%= "虚拟路径:" + request.getContextPath() %> <br>
<!-- 无效,获取不到,requestScope只能获取request域中的数据,
不能通过他获取非域内值的其他对象 -->
${requestScope.contextPath} <br>
<!-- 正确写法【注意,是调用属性名,截取了get后面的字符串】 -->
${pageContext.request.contextPath}
六、JSTL
作用:用于简化和替换jsp页面上的java代码
1.使用步骤
- 导入jstl相关的jar包【
web/WEB-INF/lib/】javax.servlet.jsp.jstl.jarjstl-impl.jar
- 引入标签库:taglib指令:写在页面上面,前缀取名取一个约定俗成的
c
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 使用标签
2.常用的jstl标签
1. if: 相当于java代码的if语句
- 属性:
-
test:必须属性,接受boolean表达式,如下- 如果为
true: 显示if标签体内容,如果为false,则不显示标签提内容 - 一般情况下,test属性值会结合el表达式一起使用。【根据el获取的值进行逻辑判断】
- 如果为
-
注意:c:if标签没有else情况,想要else情况,只有逻辑上再定义一个c:if标签
<%
int i = 3;
request.setAttribute("i", i);
%>
<c:if test="${requestScope.i div 2 == 0}">
<h1>12345</h1>
</c:if>
<c:if test="${requestScope.i div 2 != 0}">
<h1>上山打老虎</h1>
</c:if>
2. choose:相当于java代码的switch语句
- 使用
choose标签声明,相当于switch声明 - 使用
when标签做判断,相当于case - 使用
otherwise标签做其他情况的声明,相当于default
<%
request.setAttribute("number", 3);
%>
<c:choose>
<c:when test="${number==1}">1</c:when>
<c:when test="${number==2}">2</c:when>
<c:when test="${number==3}">3</c:when>
<c:when test="${number==4}">4</c:when>
<c:otherwise>no match!</c:otherwise>
</c:choose>
3.foreach:相当于java代码的for语句
- 完成重复的操作
for(int i = 0; i < 10; i ++) {}
- 属性:
- begin:开始值
- end:结束值
- var:临时变量
- step:步长
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始 ????初始值好像和begin一样!
- count:循环次数,从1开始
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach begin="1" end="10" var="i" step="3" varStatus="s">
i:${i} s.index:${s.index} s.count:${s.count} <br>
</c:forEach>
- 遍历容器
List<User> list; for(User user:list) {}
- 属性:
- items:容器对象
- var:容器中元素的临时变量
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始
- count:循环次数,从1开始
<%
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
request.setAttribute("list", list);
%>
<c:forEach items="${list}" var="str" varStatus="s">
${s.index} ${s.count} ${str}<br>
</c:forEach>
practice:在request域中有一个存有User对象的List集合。需要使用jstl+el将聚合数据展示到jsp页面的表格table中。
<%
ArrayList<User> list = new ArrayList<>();
list.add(new User("小明", 22, "male", new Date()));
list.add(new User("小祥", 24, "male", new Date()));
list.add(new User("小伟", 21, "male", new Date()));
list.add(new User("小成", 22, "male", new Date()));
request.setAttribute("list", list);
%>
<table cellspacing="2px" border="1px">
<tbody>
<c:forEach items="${requestScope.list}" var="user" varStatus="s">
<c:if test="${s.index % 2 == 0}">
<tr style="background-color: darkcyan">
<td>${s.index + 1}</td>
<td>${user.name}</td>
<td>${user.age}</td>
<td>${user.gender}</td>
<td>${user.strBir}</td>
</tr>
</c:if>
<c:if test="${s.index % 2 != 0}">
<tr style="background-color: white">
<td>${s.index + 1}</td>
<td>${user.name}</td>
<td>${user.age}</td>
<td>${user.gender}</td>
<td>${user.strBir}</td>
</tr>
</c:if>
</c:forEach>
</tbody>
</table>
七、案例:列表查询
- 需求:用户信息的增删改查操作
- 设计:
- 技术选型:Servlet+JSP+MySQL+JDBCTemplate+Duird+BeanUtilS+tomcat
- 数据库设计:
create database day17; -- 创建数据库
use day17; -- 使用数据库
create table user( -- 创建表
id int primary key auto_increment,
name varchar(20) not null,
gender varchar(5),
age int,
address varchar(32),
qq varchar(20),
email varchar(50)
);
- 开发:
- 环境搭建【架构师的事】
- 创建数据库环境
- 创建项目,导入需要的jar包
- 编码
- 环境搭建【架构师的事】
- 测试
- 部署运维