A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 哈哈大圣 中级黑马   /  2018-12-27 09:09  /  850 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

# 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



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马