## JSP
### JSP 概念和原理
JSP,Java Server Pages,即 Java 服务器端页面,可以理解为是一种特殊的页面,其中既可以书写 HTML 标签内容,又可以写 Java 代码,JSP 可以简化书写,例如在之前的案例中,如果想通过 Servlet 对 HTML 的展示内容作出修改,必须在输出流中书写 HTML 标签和内容,这无疑是非常复杂的。
JSP 的本质就是一个 Servlet,当客户端访问一个 JSP 资源时,服务器会解析该请求,找到是否有该 JSP 资源,如果有,服务器会将该 JSP 转换为 `.java` 文件,编译该 `.java` 文件生成 `.class` 字节码文件,然后虚拟机加载字节码文件进内存,由该类(一个 Servlet)提供访问,其中所有 HTML 标签内容都会由该类通过输出流写入页面。
### JSP 定义 Java 代码
JSP 中有三种方式定义 Java 代码
1. `<% java代码 %>`,使用该脚本定义的代码相当于 `service()` 方法中的代码,`service()` 方法中可以定义什么,该脚本中就可以定义什么
2. `<%! java代码 %>`,使用该脚本定义的代码转换后会出现在 Java 类成员的位置
3. `<%= java代码 %>`,使用该脚本定义的代码转换后会输出到页面上,也就是相当于输出语句中的内容
### JSP 指令
JSP 指令写在 JSP 页面最上方,用于配置 JSP 页面和导入资源文件,格式为 `<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>`
常用指令
1. `page` 用于配置页面
1. `contentType`,等同于 `response.setContentType()`,设置响应体的 MIME 类型和字符集
2. `import` 导包
3. `errorPage` 表示如果,当前页面发生异常,会自动跳转到指定的错误页面
4. `isErrorPage` 标识当前页面是否是错误页面,如果是错误页面才可以使用内置对象 `exception`
例如
```java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
```
2. `include` 用于导入其他 JSP 页面资源,例如
```java
<%@include file="top.jsp"%>
```
3. `taglib` 导入资源
1. `prefix` 自定义的前缀
2. `uri` 资源的路径
例如,导入 JSTL 标准标签库
```java
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
```
### JSP 的内置对象
所谓内置对象,就是在 JSP 中无需创建或获取,可以直接使用的对象,共 9 个
|变量名|真实类型|作用|
|---|---|---|
|`pageContext`|`PageContext`|当前页面共享数据,获取其他 8 个内置对象|
|`request`|`HttpServletRequest`|一次请求(转发)中共享数据|
|`session`|`HttpSession`|一次会话中共享数据|
|`application`|`ServletContext`|所有用户间共享数据|
|`response`|`HttpServletResponse`|Http 响应对象|
|`page`|`Object`|当前页面(Servlet)对象,相当于 `this`|
|`out`|`JspWriter`|将数据输出到页面上,类似 `response.getWriter()`|
|`config`|`ServletConfig`|Servlet 的配置对象|
|`exception`|`Throwable`|异常对象|
注意 `response.getWriter().write()` 和 `out.write()` 的区别:在 Tomcat 服务器真正给客户端做出响应之前,会先找 `response` 缓冲区数据,再找`out` 缓冲区数据,也就是说无论 `response.getWriter().write()` 和 `out.write()` 两条语句在 JSP 中定义的位置如和,`response.getWriter().write()` 数据输出永远在 `out.write()` 之前
## EL 表达式
### 概念
EL,Expression Language,即表达式语言,用于替换和简化 JSP 页面中的 Java 代码的编写。一条 EL 的语法格式为 `${ 表达式 }`,JSP 默认支持 EL,EL 前加 `\` 进行转义则可以忽略该 EL 表达式,让页面将其当做普通文本输出
### EL 的基本运算
EL 支持最基本的算术运算符、比较运算符、逻辑运算符(与或非),用法与 Java 类似,不再赘述,同时还有一个特殊的空运算符 `empty`,用于判断数组、字符串、集合对象是否为 `null` 或者长度为 0,如果要取反,使用 `not empty` 即可,例如 `${empty list}` 表示 list 是否为 `null` 或长度为 0,`${not empty str}` 表示 str 是否不为 `null` 且长度大于 0
### EL 获取值
* EL 表达式只能获取值,而不能改写或者调用对象的方法
* EL 表达式默认只能从域对象中获取值,其基本语法为 `${域名称.键名}`,即从指定域中获取指定键的值
|域名称|JSP内置对象|
|---|---|
|`pageScope`|`pageContext`|
|`requestScope`|`request`|
|`sessionScope`|`session`|
|`applcationScope`|`application` (`ServletContext`)|
例如,在 `request` 域中存储了键值对 `name=zhangsan`,要获取该值,使用表达式 `${requestScope.name}` 即可,还有一种简单写法 `${键名}`,也就是省略域名称,表示一次从最小的域中查找是否有该键,直到找到为止
* 获取对象的属性值
使用 `${域名称.键名.属性名}`,这里的本质是调用对象的 `getter` 方法,注意对象属性和字段(成员变量)的区别
* 获取 List 集合的元素
使用 `${域名称.键名[索引]}`
* 获取 Map 集合中的元素
使用 `${域名称.键名.map_key}` 或者 `${域名称.键名[map_key]}`
* 获取 JSP 内置对象
EL 中的隐式对象 `pageContext` 即 JSP 的 `pageContext`,可以用来获取 JSP 其他内置对象,例如,常用的动态获取项目虚拟目录功能(用于填写提交表单的路径或者 `` 标签的 `href`),`${pageContext.request.contextPath}`
## JSTL
JSTL,Java Server Pages Tag Library,即 JSP 标准标签库,是由 Apache 组织提供的开源的免费的 JSP 标签,用于简化和替换 JSP 页面上的 Java 代码
要使用 JSTL 首先要在项目导入 JSTL 相关 jar 包,然后使用 `taglib` 指令在 JSP 页面头部引入标签库,`<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>`
### 常用标签
1. `if` 标签:相当于 Java 的 `if` 语句
* `test` 属性,是必须属性,接受一个布尔表达式,如果表达式为 `true`,则显示标签体内容,否则不显示,所以一般来说 `test` 属性会配合 EL 表达式一起使用
2. `choose` 标签,相当于 Java 的 `switch` 语句
* 使用 `when` 标签作判断,相当于 `case`
* 使用 `otherwise` 标签做其他情况的声明,相当于 `default`
例如,现在 `request` 域有一个键值对 `request.setAttribute("num",3)`,使用 `choose` 标签展示对应的信息
```java
星期一
星期二
星期三
星期四
星期五
星期六
星期天
输入有误
```
3. `foreach` 标签,相当于 Java 的增强 for 循环
* `items` 属性,表示要遍历的字符串、List、Map 等容器
* `var` 属性,表示临时变量
* `begin` 属性,表示循环遍历的初始值
* `end` 属性,表示循环遍历的结束值
* `step` 属性,表示循环遍历的临时变量的增长步长
* `varStatus` 属性,表示循环状态
* `index` 子属性,表示本次迭代从 `0` 开始的索引
* `count` 子属性,表示本次迭代从 `1` 开始的次数
例如,现在 `request` 域有一个 List 集合 `request.setAttribute("list",list)`,使用 `foreach` 标签动态展示集合中的数据到表格中,`list` 中存储 `User` 实体类的对象
```java
${s.count}
${user.name}
${user.age}
```
## 参考
* [黑马 JavaWeb](https://www.bilibili.com/video/BV1J4411877m)

JSP、EL表达式、JSTL