# 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代码
- 用于简化书写
---
@@@@@@@@@@@@@@@@@@@@@@@@@ jsp原理(课程截图)
- 本质: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.指令名称分类
1. **`page`**:配置JSP页面的
- `contentType`:等同于response.setContentType(""),`text/html;charset=utf-8`
1. 设置响应体的mime类型以及字符集
2. 设置当前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" %>
```
2. **`include`**:页面包含的。导入页面的资源文件【比如很多页面共享一些标签,可以使用这个进行导入】
```
<%@include file=top.jsp"" %>
```
3. **`taglib`**:导入标签库资源,后面介绍
```
<%@ taglib prefix="c" url="http://java.sun.com/jsp/jstl/core" %>
```
> prefix:前缀,自定义的导入的标签库的命名空间,最好使用约定俗称的前缀
## 三、注释
1. HTML注释,只能注释html代码片段
```
<!-- -->
```
2. jsp注释:可以注释所有【推荐使用】
```
<%-- --%>
```
## 四、JSP内置对象:【需要记住】
1. 在jsp中不需要获取和创建,可以直接使用的对象:tomcat在编译.jsp文件是会提前将一个对象进行创建,然后才把.jsp中的对象放到对应的位置!
2. 一共有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()`之前。
@@@@@@@@@@@@@@@@@@@@ response.getWriterout.write
## 五、EL表达式
> Expression Language 表达式语言;替换和简化jsp页面中java代码的编写;【**建议在域中存的名字与对象的名字一样**】
### 1、语法及注意事项
- 语法
```
${表达式}
```
- 注意事项:jsp默认支持el表达式。如果要忽略el表达式,如下方式
- 【**使用转义字符**】:**`\${表达式}`**
- 【不推荐使用】设置jsp中page指令中:**`isELIgnored="true"`** 忽略当前jsp页面中所有el表达式
### 2.【功能】运算符号
1. 算数运算符: `+`、` -`、` *`、`\(或者div)`、`%(mod)`
2. 比较运算符:`>`、 `<`、 `>=`、 `<=`、 `==`、 `!=`
3. 逻辑运算符:`&&(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)}
```
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集合的值
1. 【对象】:**`${域名称.键名.属性名}`**:本质上会去调用对象的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>
```
2. 【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>
```
3. 【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个隐式对象。
1. pageContent:可以获取jsp其他八个内置对象
- **`${pageContext.request.contextPath}`**:动态获取虚拟目录。
```
<%= "虚拟路径:" + request.getContextPath() %> <br>
<!-- 无效,获取不到,requestScope只能获取request域中的数据,
不能通过他获取非域内值的其他对象 -->
${requestScope.contextPath} <br>
<!-- 正确写法【注意,是调用属性名,截取了get后面的字符串】 -->
${pageContext.request.contextPath}
```
## 六、JSTL
> **作用**:用于简化和替换jsp页面上的java代码
### 1.使用步骤
1. 导入jstl相关的jar包【`web/WEB-INF/lib/`】
- `javax.servlet.jsp.jstl.jar`
- `jstl-impl.jar`
2. 引入标签库:taglib指令:写在页面上面,前缀取名取一个约定俗成的**`c`**
```
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
```
3. 使用标签
### 2.常用的jstl标签
#### 1. `if`: 相当于java代码的`if`语句
1. 属性:
- **`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`语句
1. 使用`choose`标签声明,相当于`switch`声明
2. 使用`when`标签做判断,相当于`case`
3. 使用`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语句
1. 完成重复的操作`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>
```
2. 遍历容器`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>
```
## 七、案例:列表查询
1. 需求:用户信息的增删改查操作
2. 设计:
1. 技术选型:Servlet+JSP+MySQL+JDBCTemplate+Duird+BeanUtilS+tomcat
2. 数据库设计:
```
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)
);
```
3. 开发:
1. 环境搭建【架构师的事】
1. 创建数据库环境
2. 创建项目,导入需要的jar包
2. 编码
4. 测试
5. 部署运维
思路介绍
@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 列表查询操作案例.png
|
|