JSP:EL:JSTL
为了提升用户体验,在WEB-INF下的web.xml配置全局错误配置
404
/404.jsp
500
/500.jsp
- 概念: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 lis1 = new ArrayList<>();
List lis2 = new ArrayList<>(); lis2.add("lis2");
Map hm1 = null;
Map 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}
${not empty lis2}
${empty hm1}
${! empty hm2}
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 }
${ requestScope.name }
${ sessionScope.name }
${ applicationScope.name }
${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}
${pageScope.user.age}
${pageScope.user.gender}
${pageScope.user.birthday}
${pageScope.user.strBir}
- 【List集合】:
${域名称.键名[索引]}
如果角标越界了,内部优化,不会把错抛出来,当前页面不会抛错
<%
User user1 = new User("小伟",22,"male",new Date());
ArrayList
- 【Map集合】:
${域名称.键名.key名称}
-
${域名称.键名["key名称"]}
,(有点像python的字典)
<%
User user2 = new User("小翔",24,"male",new Date());
HashMap map = new HashMap<>();
map.put("name", "小鹏");
map.put("user2", user1);
session.setAttribute("map", map);
%>
${sessionScope.map.name}
${sessionScope.map["name"]}
${sessionScope.map.user2.name}
${sessionScope.map["user2"].strBir}
4.隐式对象:
el表达式中有11个隐式对象。
- pageContent:可以获取jsp其他八个内置对象
-
${pageContext.request.contextPath}
:动态获取虚拟目录。
-
<%= "虚拟路径:" + request.getContextPath() %>
${requestScope.contextPath}
${pageContext.request.contextPath}
六、JSTL
作用:用于简化和替换jsp页面上的java代码
1.使用步骤
- 导入jstl相关的jar包【
web/WEB-INF/lib/
】javax.servlet.jsp.jstl.jar
jstl-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);
%>
12345
上山打老虎
2. choose
:相当于java代码的switch
语句
- 使用
choose
标签声明,相当于switch
声明 - 使用
when
标签做判断,相当于case
- 使用
otherwise
标签做其他情况的声明,相当于default
<%
request.setAttribute("number", 3);
%>
1
2
3
4
no match!
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" %>
i:${i} s.index:${s.index} s.count:${s.count}
- 遍历容器
List
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);
%>
${s.index} ${s.count} ${str}
practice:在request域中有一个存有User对象的List集合。需要使用jstl+el将聚合数据展示到jsp页面的表格table中。
<%
ArrayList 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);
%>
${s.index + 1}
${user.name}
${user.age}
${user.gender}
${user.strBir}
${s.index + 1}
${user.name}
${user.age}
${user.gender}
${user.strBir}
七、案例:列表查询
- 需求:用户信息的增删改查操作
- 设计:
- 技术选型: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包
- 编码
- 环境搭建【架构师的事】
- 测试
- 部署运维