# JavaWeb学习
**Repository Path**: BY-KK/javaweb
## Basic Information
- **Project Name**: JavaWeb学习
- **Description**: 此仓库用来学习javaweb相关知识
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 1
- **Created**: 2022-02-26
- **Last Updated**: 2022-04-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# JavaWeb学习
## 介绍
此仓库用来学习javaweb相关知识
预计花费13h
**JavaEE** **项目的三层架构**

# 2.26(Servlet\JSP)
## Servlet
### 1、什么是Servlet
- 1、Servlet 是 JavaEE 规范之一。规范就是接口
- 2、Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
- 3、Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
### 2、通过URL地址到Servlet程序的过程

### 3、Servlet的生命周期
1. 执行 Servlet 构造器方法
2. 执行 init 初始化方法
第一、二步,是在第一次访问,的时候创建 Servlet 程序会调用。
3. 执行 service 方法
第三步,每次访问都会调用。
4. 执行 destroy 销毁方法
第四步,在 web 工程停止的时候调用。
### 4、Servlet类的继承体系

### 5、ServletContext类
#### a)什么是ServletContext
- ServletContext 是一个接口,它表示 Servlet 上下文对象
- 一个 web 工程,只有一个 ServletContext 对象实例。
- ServletContext 对象是一个域对象。
- ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。
> 什么是域对象?
>
> > 域对象是可以Map 一样存取数据的对象,叫域对象。
> >
> > 这里的域指的是存取数据的操作范围,整个 web 工程。
| | 存数据 | 取数据 | 删除数据 |
| :--------: | :-----: | :----: | :-----: |
| Map | put() | get() | remove() |
| 域对象 | serAttribute() | getAttribute() | removeAttribute() |
#### b)ServletContext类的四个作用
- 1、获取 web.xml 中配置的上下文参数 context-param
- 2、获取当前的工程路径,格式: /工程路径
- 3、获取工程部署后在服务器硬盘上的绝对路径
- 4、像 Map 一样存取数据
### 6、HTTP协议
#### a)什么是HTTP协议
什么是协议?
协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。
所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。
HTTP 协议中的数据又叫报文。
#### b)请求的HTTP协议格式
客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫响应。
请求又分为 GET 请求,和 POST 请求两种
##### i、GET请求
- 1、请求行
- (1) 请求的方式 GET
- (2) 请求的资源路径[+?+请求参数]
- (3) 请求的协议的版本号 HTTP/1.1
- 2、请求头
- key : value 组成不同的键值对,表示不同的含义
##### ii、POST请求
- 1、请求行
- (1) 请求的方式 POST
- (2) 请求的资源路径[+?+请求参数]
- (3) 请求的协议的版本号 HTTP/1.1
- 2、请求头
- key : value 不同的请求头,有不同的含义
- 3、请求体 ===>>> 就是发送给服务器的数据
##### iii、常用的请求头的说明
**Accept**: 表示客户端可以接收的数据类型
**Accpet-Languege**: 表示客户端可以接收的语言类型
**User-Agent:** 表示客户端浏览器的信息
**Host**: 表示请求时的服务器 ip 和端口号
##### iv、 哪些是GET请求,哪些是POST请求
GET 请求有哪些:
1. form 标签 method=get
2. a 标签
3. link 标签引入 css
4. Script 标签引入 js 文件
5. img 标签引入图片
6. iframe 引入 html 页面
7. 在浏览器地址栏中输入地址后敲回车
POST 请求有哪些:
1. form 标签 method=post
#### c)响应的HTTP协议格式
- 1、响应行
- (1) 响应的协议和版本号
- (2) 响应状态码
- (3) 响应状态描述符
- 2、响应头
- (1) key : value 不同的响应头,有其不同含义
- 3、响应体 ---->>> 就是回传给客户端的数据

#### d)常用的响应码说明
**200** 表示请求成功
**302** 表示请求重定向(明天讲)
**404** 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
**500** 表示服务器已经收到请求,但是服务器内部错误(代码错误)
#### e)MIME类型说明
MIME 是 HTTP 协议中数据类型。
MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小
类型”,并与某一种文件的扩展名相对应。
| 文件 | 文件格式 | MIME类型 |
| :----------------: | :---------: | ------------------------ |
| 超文本标记语言文本 | .html,.htm | text/html |
| 普通文本 | .txt | text/plain |
| RTF文本 | .rtf | application/rtf |
| GIF图形 | .gif | image/gif |
| JPEG图形 | .jpeg,.jpg | image/jpeg |
| au声音文件 | .au | audio/basic |
| MIDI音乐文件 | .mid,.midi | audio/midi,audio/x-midi |
| RealAudio音乐文件 | .ra,.ram | audio/x-pn-realaudio |
| MPEG文件 | .mpg,.mpeg | video/mpeg |
| AVI文件 | .avi | video/x-msvideo |
| GZIP | .gz | application/x-gzip |
| TAR | .tar | application/x-tar |
### 7、HttpServletRequest类
#### 7.1、HttpServletRequest类有什么用
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
#### 7.2、HttpServletRequest类的常用方法
| 方法 | 描述 |
| :----------------------: | :--------------------------------------------: |
| getRequestURI() | 获取请求的资源路径 |
| getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
| getRemoteHost() | 获取客户端的IP地址 |
| getHeader() | 获取请求头 |
| getParameter(String arg) | 获取请求的参数 |
| getParameterValues() | 获取请求的参数(多个值的时候用,例如checkbox) |
| getMethod() | 获取请求的方式GET或POST |
| setAttribute(key,value) | 设置域数据 |
| getAttribute(key) | 获取域数据 |
| getRequestDispatcher() | 获取请求转发对象 |
#### 7.3、如何解决乱码问题
doGet请求的中文乱码问题解决:
```java
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
```
post请求中的中文乱码解决:
```java
req.setCharacterEncoding("UTF-8");
```
> 在post中用setCharacterEncoding()方法之前如果有使用获取参数方法则会转码失败!
#### 7.4、请求转发
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。

#### 7.5、Web中的相对路径和绝对路径
在 javaWeb 中,路径分为相对路径和绝对路径两种:
**相对路径是**:
- . 表示当前目录
- .. 表示上一级目录
- 资源名 表示当前目录/资源名
**绝对路径**:
http://ip:port/工程路径/资源路径
#### 7.6、web中 / 斜杠的不同意义
在 web 中 / 斜杠 是一种绝对路径。
/ 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/
```html
斜杠
```
/ 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径
1. <**url-pattern**>/servlet1**url-pattern**>
2. servletContext.getRealPath(“/”);
3. request.getRequestDispatcher(“/”);
>特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到 http://ip:port/
### 8、HttpServletResponse类
#### 8.1、HttpServletResponse类的作用
HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息, 我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置
#### 8.2、两个输出流的说明
| 方法 | 描述 | 流类型 |
| ------------------ | ---------------------------- | ------ |
| getOutputStream(); | 常用于下载(传递二进制数据) | 字节流 |
| getWriter(); | 常用于回传字符串(常用) | 字符流 |
#### 8.3、往客户端回传数据
要求 : 往客户端回传 字符串 数据。
```java
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
PrintWriter writer = resp.getWriter();
writer.write("response's content!!!");
}
}
```
#### 8.4、响应的乱码问题
解决响应中文乱码方案一(不推荐使用):
```java
//* *设置服务器字符集为* *UTF-8*
resp.setCharacterEncoding("UTF-8");
//* *通过响应头,设置浏览器也使用* *UTF-8* *字符集*
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
```
解决响应中文乱码方案二(推荐):
```java
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
```
#### 8.5、请求重定向
请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)。

请求重定向的第一种方案:
```java
// 设置响应状态码 302 ,表示重定向,(已搬迁)
resp.setStatus(302);
// 设置响应头,说明 新的地址在哪里
resp.setHeader("Location", "http://localhost:8080");
```
请求重定向的第二种方案(推荐使用):
```java
resp.sendRedirect("http://localhost:8080");
```
## JSP
### 1、JSP简介
jsp 的全称是 **J**ava **S**erver **P**ages。Java 的服务器页面。
jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据。
因为 Servlet 程序回传 html 页面数据是一件非常繁锁的事情。开发成本和维护成本都极高。
### 2、JSP的本质
jsp 页面本质上是一个 Servlet 程序。
当我们第一次访问 jsp 页面的时候。Tomcat 服务器会帮我们把 jsp 页面翻译成为一个 java 源文件。并且对它进行编译成为.class 字节码程序。
>其底层实现,也是通过输出流。把 html 页面数据回传给客户端
### 3、JSP的三种语法
#### a)jsp头部的page指令
jsp 的 page 指令可以修改 jsp 页面中一些重要的属性,或者行为。
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
```
| 属性 | 描述 |
| ------------ | ------------------------------------------------------------ |
| language | 表示jsp翻译后是什么语言文件,只支持java |
| contentType | 表示jsp返回的数据类型是什么,response.setContentType()参数值 |
| pageEncoding | 表示当前jsp页面文件本身的字符集 |
| import | 导包 |
| autoFlush | 设置当out输出流缓冲区满了之后,是否自动刷新冲级区,默认true |
| buffer | 设置out缓冲区的大小,默认8kb |
| errorPage | 设置当jsp页面运行时出错,自动跳转去的错误页面路径 |
| isErrorPage | 设置当前jsp页面是否是错误信息页面。默认false。如果是true可以获取异常信息 |
| session | 设置访问当前jsp页面,是否会创建HttpSession对象,默认true |
| extends | 设置jsp翻译出来的java类默认继承谁 |
#### b)jsp中的常用脚本
**i.** **声明脚本**(**极少使用**)
声明脚本的格式是: **<%!** 声明 java 代码 **%>**
作用:可以给 jsp 翻译出来的 java 类定义属性和方法甚至是静态代码块。内部类等。
**ii.** **表达式脚本(常用)**
表达式脚本的格式是:**<%=**表达式**%>**
表达式脚本的作用是:在 jsp 页面上输出数据。
表达式脚本的特点:
1. 所有的表达式脚本都会被翻译到_jspService() 方法中
2. 表达式脚本都会被翻译成为 out.print()输出到页面上
3. 由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用。
4. 表达式脚本中的表达式不能以分号结束。
**iii.** **代码脚本**
代码脚本的格式是:
**<%**
java 语句
**%>**
代码脚本的作用是:可以在 jsp 页面中,编写我们自己需要的功能(写的是 java 语句)。
代码脚本的特点是:
1. 代码脚本翻译之后都在_jspService 方法中
2. 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。
3. 还可以由多个代码脚本块组合完成一个完整的 java 语句。
4. 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据
### 4、JSP九大内置对象
jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。
| 对象 | 描述 |
| ----------- | ------------------ |
| request | 请求对象 |
| response | 响应对象 |
| pageContext | jsp的上下文对象 |
| session | 会话对象 |
| application | ServletContext对象 |
| config | ServletConfig对象 |
| out | jsp输出流对象 |
| page | 指向当前jsp的对象 |
| exception | 异常对象 |
### 5、JSP四大域对象
| 对象 | 作用范围 |
| ----------------------------------- | ---------------------------------------------------------- |
| pageContext (PageContextImpl 类) | 当前 jsp 页面范围内有效 |
| request (HttpServletRequest 类) | 一次请求内有效 |
| session (HttpSession 类) | 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器) |
| application (ServletContext 类) | 整个 web 工程范围内都有效(只要 web 工程不停止,数据都在) |
域对象是可以像 Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围。
虽然四个域对象都可以存取数据。在使用上它们是有优先顺序的。
四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序。
pageContext ====>>> request ====>>> session ====>>> application
# 2.27(EL&JSTL&MVC&分页&Filter)
## EL表达式
### 1、EL表达式简介
EL 表达式的全称是:**E**xpression **L**anguage。是表达式语言。
**EL 表达式的什么作用**:EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。
因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多。
EL 表达式的格式是:**${**表达式**}**
EL 表达式在输出 null 值的时候,输出的是空串。jsp 表达式脚本输出 null 值的时候,输出的是 null 字符串。
### 2、EL表达式搜索域数据的顺序
当四个域中都有相同的 key 的数据的时候,EL 表达式会按照四个域的从小到大的顺序去进行搜索,找到就输出。
### 3、EL搜索写法
*输出Person类中普通属性,数组属性。List 集合属性和 map 集合属性。*
```
public class Person {
// i.需求——输出 Person 类中普通属性,数组属性。list 集合属性和 map 集合属性。
private String name;
private String[] phones;
private List cities;
private Map map;
}
```
| 写法 | 描述 |
| ---------------------------------------------- | ---------------------------- |
| &{域中对象名} &{ p } | 输出对象 |
| &{域中对象名.属性名} &{ p.name } | 输出该对象指定的属性值 |
| &{域中对象名.数组名[索引]} &{ p.phones[2] } | 输出对象数组中某一个值 |
| &{域中对象名.集合名} &{ p.cities } | 输出该对象集合 |
| &{域中对象名.集合名[索引]} &{ p.cities[2] } | 输出对象集合中某一个值 |
| &{域中对象名.map集合名} &{ p.map } | 输出该对象Map集合 |
| &{域中对象名.map集合名.key} &{ p.map.key } | 输出该对象map集合中某个key值 |
### 4、EL表达式——运算
语法:${ 运算表达式 } , EL 表达式支持如下运算符
**关系运算**
| 关系运算符 | 说明 | 规范 | 结果 |
| :--------: | :------: | :--------------------------: | :---: |
| == 或 eq | 等于 | ${ 5 == 5 } 或 ${ 5 eq 5 } | true |
| != 或 ne | 不等于 | ${ 5 !=5 } 或 ${ 5 ne 5 } | false |
| < 或 lt | 小于 | ${ 3 < 5 } 或 ${ 3 lt 5 } | true |
| \> 或 gt | 大于 | ${ 2 > 10 } 或 ${ 2 gt 10 } | false |
| <= 或 le | 小于等于 | ${ 5 <= 12 } 或 ${ 5 le 12 } | true |
| \>= 或 ge | 大于等于 | ${ 3 >= 5 } 或 ${ 3 ge 5 } | false |
**逻辑运算**
| 关系运算符 | 说明 | 规范 | 结果 |
| :--------: | :-------: | :----------------------------------------------------: | :---: |
| && 或 and | && 或 and | ${ 12 == 12 && 12 < 11 } 或 ${ 12 == 12 and 12 < 11 } | false |
| \|\| 或 or | 或运算 | ${ 12 == 12 \|\| 12 < 11 } 或 ${ 12 == 12 or 12 < 11 } | true |
| ! 或 not | 取反运算 | ${ !true } 或 ${ not true } | false |
**算数运算**
| 关系运算符 | 说明 | 规范 | 结果 |
| :--------: | :--: | :----------------------------------: | :--: |
| + | 加法 | ${ 12 + 18 } | 30 |
| - | 减法 | ${ 18 - 8 } | 10 |
| * | 乘法 | ${ 12 * 12 } | 144 |
| / 或 div | 除法 | ${ 144 / 12 } 或 ${ 144 **div** 12 } | 12 |
| % 或 mod | 取模 | ${ 144 % 10 } 或 ${ 144 **mod** 10 } | 4 |
**empty运算**
empty 运算可以判断一个数据是否为空,如果为空,则输出 true,不为空输出 false。
以下几种情况为空:
1. 值为 null 值的时候,为空
2. 值为空串的时候,为空
3. 值是 Object 类型数组,长度为零的时候
4. list 集合,元素个数为零
5. map 集合,元素个数为零
**三元运算**
表达式 1?表达式 2:表达式 3
如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。
**“.”运算 和 [] 中括号运算符**
.点运算,可以输出 Bean 对象中某个属性的值。
[]中括号运算,可以输出有序集合中某个元素的值。
并且[]中括号运算,还可以输出 map 集合中 key 里含有特殊字符的 key 的值。
**EL表达式的11个隐含对象**
| **隐含对象** | 类型 | **描述** |
| :--------------- | :------------------: | :----------------------------------------------------------- |
| pageScope | Map | page 作用域,它可以获取 pageContext 域中的数据 |
| requestScope | Map | request 作用域,它可以获取 Request 域中的数据 |
| sessionScope | Map | session 作用域,它可以获取 Session 域中的数据 |
| applicationScope | Map | application 作用域,它可以获取 ServletContext 域中的数据 |
| param | Map | Request 对象的参数,字符串,它可以获取请求参数的值 |
| paramValues | Map | Request对象的参数,字符串集合,它也可以获取请求参数的值,获取多个值的时候使用。 |
| header | Map | HTTP 信息头,字符串,它可以获取请求头的信息 |
| headerValues | Map | HTTP 信息头,字符串集合,它可以获取请求头的信息,它可以获取多个值的情况 |
| initParam | Map | 上下文初始化参数,它可以获取在 web.xml 中配置的上下文参数 |
| cookie | Map | Cookie值,它可以获取当前请求的 Cookie 信息 |
| pageContext | PageContextImpl | 当前页面的pageContext,它可以获取 jsp 中的九大内置对象 |
**EL获取四个特定域中的属性**
pageScope ====== pageContext 域
requestScope ====== Request 域
sessionScope ====== Session 域
applicationScope ====== ServletContext 域
```html
<%
pageContext.setAttribute("key1", "pageContext1"); pageContext.setAttribute("key2", "pageContext2");
request.setAttribute("key2", "request");
session.setAttribute("key2", "session");
application.setAttribute("key2", "application");
%>
${ applicationScope.key2 }
```
### 5、EL中域对象的使用
#### 5.1、pageContext对象的使用
1. 协议: **${** req.scheme **}**
2. 服务器 ip: **${** pageContext.request.serverName **}**
3. 服务器端口: **${** pageContext.request.serverPort **}**
4. **获取工程路径:** **${** pageContext.request.contextPath **}**
5. 获取请求方法: **${** pageContext.request.method **}**
6. 获取客户端 ip 地址:**${** pageContext.request.remoteHost **}**
7. 获取会话的 id 编号:**${** pageContext.session.id **}**
#### 5.2、其他隐含对象的使用
| 隐含对象 | 返回值 | 说明 |
| :---------: | :------------------: | :--------------------------------------------: |
| param | Map | 它可以获取请求参数的值 |
| paramValues | Map | 它也可以获取请求参数的值,获取多个值的时候使用 |
- 输出请求参数 username 的值:**${** param.username **}**
- 输出请求参数 password 的值:**${** param.password **}**
- 输出请求参数 username 的值:**${** paramValues.username[0] **}**
- 输出请求参数 hobby 的值:**${** paramValues.hobby[0] **}**
- 输出请求参数 hobby 的值:**${** paramValues.hobby[1] **}**
| 隐含对象 | 返回值 | 说明 |
| :----------: | :------------------: | :--------------------------------------------: |
| header | Map | 它可以获取请求头的信息 |
| headerValues | Map | 它可以获取请求头的信息,它可以获取多个值的情况 |
- 输出请求头【User-Agent】的值:**${** header[**'User-Agent'**] **}**
- 输出请求头【Connection】的值:**${** header.Connection **}**
- 输出请求头【User-Agent】的值:**${** headerValues\[**'User-Agent'**][0] }
| 隐含对象 | 返回值 | 说明 |
| :------: | :----------------: | :------------------------------: |
| cookie | Map | 它可以获取当前请求的 Cookie 信息 |
- 获取 Cookie 的名称:**${** cookie.JSESSIONID.name **}**
- 获取 Cookie 的值:**${** cookie.JSESSIONID.value **}**
| 隐含对象 | 返回值 | 说明 |
| :-------: | :----------------: | :----------------------------------------------------: |
| initParam | Map | 它可以获取在 web.xml 中配置的上下文参数 |
```xml
username
root
url
jdbc:mysql:///test
```
- 输出**<**Context-param**>**username 的值:**${** initParam.username **}**
- 输出**<**Context-param**>**url 的值:**${** initParam.url **}**
## JSTL标签库
### 1、JSTL标签库简介
JSTL 标签库 全称是指 JSP Standard Tag Library JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标签库。
EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面变得更佳简洁。
JSTL 由五个不同功能的标签库组成。
| 功能范围 | URI | 前缀 |
| -------------------- | -------------------------------------- | ----- |
| **核心标签库--重点** | **http://java.sun.com/jsp/jstl/core** | **c** |
| 格式化 | http://java.sun.com/jsp/jstl/fmt | fmt |
| 函数 | http://java.sun.com/jsp/jstl/functions | fn |
| 数据库(不使用) | http://java.sun.com/jsp/jstl/sql | sql |
| XML(不使用) | http://java.sun.com/jsp/jstl/xml | x |
在 jsp 标签库中使用 taglib 指令引入标签库
```html
CORE 标签库
<%@ taglib prefix="c"uri="http://java.sun.com/jsp/jstl/core" %>
XML 标签库
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
FMT 标签库
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
SQL 标签库
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
FUNCTIONS 标签库
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
```
### 2、JSTL标签库的使用步骤
1. 先导入 jstl 标签库的 jar 包。
taglibs-standard-impl-1.2.1.jar
taglibs-standard-spec-1.2.1.jar
2. 第二步,使用 taglib 指令引入标签库。
<%@ **taglib** **prefix**="**c**" **uri**="**http://java.sun.com/jsp/jstl/core**" %>
### 3、core核心库使用
#### ****
作用:set 标签可以往域中保存数据
```jsp
<%--
i.
作用:set 标签可以往域中保存数据
域对象.setAttribute(key,value);
scope 属性设置保存到哪个域
page 表示 PageContext 域(默认值)
request 表示 Request 域
session 表示 Session 域
application 表示 ServletContext 域
var 属性设置 key 是多少
value 属性设置值
--%>
保存之前:${ sessionScope.abc }
保存之后:${ sessionScope.abc }
```
#### ****
if 标签用来做 if 判断。
```jsp
<%--
ii.
if 标签用来做 if 判断。
test 属性表示判断的条件(使用 EL 表达式输出)
--%>
12 等于 12
12 不等于 12
```
#### **\ \ \标签**
多路判断。跟 switch ... case .... default 非常接近
```jsp
<%--
iii. 标签
作用:多路判断。跟 switch ... case .... default 非常接近
choose 标签开始选择判断
when 标签表示每一种判断情况
test 属性表示当前这种判断情况的值
otherwise 标签表示剩下的情况
标签使用时需要注意的点:
1、标签里不能使用 html 注释,要使用 jsp 注释
2、when 标签的父标签一定要是 choose 标签
--%>
<%
request.setAttribute("height", 180);
%>
<%-- 这是 html 注释 --%>
小巨人
很高
还可以
大于 160
大于 150
大于 140
其他小于 140
```
#### ****
作用:遍历输出使用。
**1. 遍历 1 到 10,输出**
```jsp
<%--
1.遍历 1 到 10,输出
begin 属性设置开始的索引
end 属性设置结束的索引
var 属性表示循环的变量(也是当前正在遍历到的数据)
for (int i = 1; i < 10; i++)
--%>
```
**2. 遍历Object数组**
```jsp
<%--
2.遍历 Object 数组
for (Object item: arr)
items 表示遍历的数据源(遍历的集合)
var 表示当前遍历到的数据
--%>
<%
request.setAttribute("arr", new String[]{"18610541354","18688886666","18699998888"});
%>
${ item }
```
**3.遍历Map集合**
```jsp
<%
Map map = new HashMap(); map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
request.setAttribute("map", map);
%>
${entry.key} = ${entry.value}
```
**4. 遍历 List 集合--List中存放 Student 类,有属性:编号,用户名,密码,年龄,电话信息**
```jsp
<%--4.遍历 List 集合---list 中存放 Student 类,有属性:编号,用户名,密码,年龄,电话信息--%>
<%
List studentList = new ArrayList();
for (int i = 1; i <= 10; i++) {
studentList.add(new Student(i,"username"+i ,"pass"+i,18+i,"phone"+i));
}
request.setAttribute("stus", studentList);
%>
| 编号 |
用户名 |
密码 |
年龄 |
电话 |
操作 |
<%--
items 表示遍历的集合
var 表示遍历到的数据
begin 表示遍历的开始索引值
end 表示结束的索引值
step 属性表示遍历的步长值
varStatus 属性表示当前遍历到的数据的状态
for(int i = 1; i < 10; i+=2)
--%>
| ${stu.id} |
${stu.username} |
${stu.password} |
${stu.age} |
${stu.phone} |
${status.step} |
```
## MVC
MVC 全称:Model 模型、 View 视图、 Controller 控制器。
MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 Web 层的代码如何有效分离,单独工作。
**View 视图**:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作——
JSP/HTML。
**Controller 控制器**:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色——Servlet。
转到某个页面。或者是重定向到某个页面。
**Model 模型**:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码——
JavaBean/domain/entity/pojo。
**MVC** **是一种思想**
MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(**目的还是为了降低耦合度**)。

**MVC** **的作用还是为了降低耦合。让代码合理分层。方便后期升级和维护。**
## 分页实现
### 1、分页模块的分析

### 2、分页模型Page的抽取
当前页数,总页数,总记录数, 当前页数据,每页记录数
```java
/*** Page 是分页的模型对象
* @param 是具体的模块的 javaBean 类
*/
public class Page {
public static final Integer PAGE_SIZE = 4; // 当前页码
private Integer pageNo; // 总页码
private Integer pageTotal; // 当前页显示数量
private Integer pageSize = PAGE_SIZE; // 总记录数
private Integer pageTotalCount; // 当前页数据
private List items;
}
```
## Filter过滤器
### 1、Filter过滤器简介
1. Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
2. Filter 过滤器它是 JavaEE 的规范。也就是接口
3. Filter 过滤器它的作用是:**拦截请求**,过滤响应。
拦截请求常见的应用场景有:
1. 权限检查
2. 日记操作
3. 事务管理
……等等
### 2、Filter工作流程
**要求**:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必须是**用户登录之后才允许访问**。
**思考**:用户登录之后都会把用户登录的信息保存到 Session 域中。所以要**检查用户是否登录**,可以**判断 Session 中否包含有用户登录的信息即可**!
```jsp
<%
Object user = session.getAttribute("user"); // 如果等于 null,说明还没有登录
if (user == null) {
request.getRequestDispatcher("/login.jsp").forward(request,response); return;
}
%>
```
Filter的工作流程图:

```java
public class AdminFilter implements Filter {
/*** doFilter 方法,专门用于拦截请求。可以做权限检查 */
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession(); Object user = session.getAttribute("user");
// 如果等于 null,说明还没有登录
if (user == null) {
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
return;
} else {
// 让程序继续往下访问用户的目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
```
web.xml中的配置:
```xml
AdminFilter
com.atguigu.filter.AdminFilter
AdminFilter
/admin/*
```
Filter 过滤器的使用步骤:
1. 编写一个类去实现 Filter 接口
2. 实现过滤方法 doFilter()
3. 到 web.xml 中去配置 Filter 的拦截路径
### 3、Filter的生命周期
Filter 的生命周期包含几个方法
1. 构造器方法
2. init 初始化方法
第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)
3. doFilter 过滤方法
第 3 步,每次拦截到请求,就会执行
4. destroy 销毁
第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)
### 4、FilterConfig类
FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。
FilterConfig 类的作用是获取 filter 过滤器的配置内容
1. 获取 Filter 的名称 filter-name 的内容
2. 获取在 Filter 中配置的 init-param 初始化参数
3. 获取 ServletContext 对象
### 5、FilterChain过滤器链
Filter 过滤器
Chain 链,链条
FilterChain 就是过滤器链(多个过滤器如何一起工作)

**在多个Filter过滤器执行的时候,它们执行的优先顺序是由他们在web.xml中从上到下配置的顺序决定**
### 6、Filter的拦截路径
**精准匹配**
<**url-pattern**>/target.jsp**url-pattern**>
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp
**目录匹配**
<**url-pattern**>/admin/***url-pattern**>
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/*
**后缀名匹配**
- <**url-pattern**>*.html**url-pattern**>
以上配置的路径,表示请求地址必须以.html 结尾才会拦截到
- <**url-pattern**>*.do**url-pattern**>
以上配置的路径,表示请求地址必须以.do 结尾才会拦截到
- <**url-pattern**>*.action**url-pattern**>
以上配置的路径,表示请求地址必须以.action 结尾才会拦截到
> **Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在**
# 2.28(Cookie&Session&验证码问题&JSON&AJAX)
## Cookie
### 1、Cookie简介
1. Cookie 翻译过来是饼干的意思。
2. Cookie 是服务器通知客户端保存键值对的一种技术。
3. 客户端有了 Cookie 后,每次请求都发送给服务器。
4. 每个 Cookie 的大小不能超过 4kb
### 2、创建Cookie

Servlet 程序中的代码
```java
protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1 创建 Cookie 对象
Cookie cookie = new Cookie("key4", "value4");
//2 通知客户端保存
Cookie resp.addCookie(cookie);
//1 创建 Cookie 对象
Cookie cookie1 = new Cookie("key5", "value5");
//2 通知客户端保存
Cookie resp.addCookie(cookie1);
resp.getWriter().write("Cookie 创建成功");
}
```
### 3、服务器获取Cookie
服务器获取客户端的 Cookie 只需要一行代码:req.getCookies():Cookie[]

### 4、Cookie值的修改
方案一:
1. 先创建一个要修改的同名(指的就是 key)的 Cookie 对象
2. 在构造器,同时赋于新的 Cookie 值。
3. 调用 response.addCookie( Cookie );
```java
Cookie cookie = new Cookie("key1","newValue1");
response.addCookie( Cookie );
```
方案二:
1. 先查找到需要修改的 Cookie 对象
2. 调用 setValue()方法赋于新的 Cookie 值。
3. 调用 response.addCookie()通知客户端保存修改
```java
// 1、先查找到需要修改的 Cookie 对象
Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
if (cookie != null) {
// 2、调用 setValue()方法赋于新的 Cookie 值。
cookie.setValue("newValue2");
// 3、调用 response.addCookie()通知客户端保存修改
resp.addCookie(cookie);
}
```
### 5、Cookie生命控制
Cookie 的生命控制指的是如何管理 Cookie 什么时候被销毁(删除)
setMaxAge()
- 正数,表示在指定的秒数后过期
- 负数,表示浏览器一关,Cookie 就会被删除(默认值是-1)
- 零,表示马上删除 Cookie
```java
/**
* 设置存活1小时的Cookie
*/
Cookie cookie = new Cookie("life3600", "life3600"); cookie.setMaxAge(60 * 60); // 设置 Cookie 一小时之后被删除。
resp.addCookie(cookie);
resp.getWriter().write("已经创建了一个存活一小时的 Cookie")
```
```java
/**
*马上删除一个Cookie
*/
// 先找到你要删除的 Cookie 对象
Cookie cookie = CookieUtils.findCookie("key4", req.getCookies());
if (cookie != null) {
// 调用 setMaxAge(0);
cookie.setMaxAge(0); // 表示马上删除,都不需要等待浏览器关闭
// 调用 response.addCookie(cookie);
resp.addCookie(cookie);
resp.getWriter().write("key4 的 Cookie 已经被删除");
}
```
```java
/**
*默认的会话级别的Cookie
*/
Cookie cookie = new Cookie("defalutLife","defaultLife");
cookie.setMaxAge(-1);//设置存活时间
resp.addCookie(cookie);
```
### 6、Cookie有效路径 Path 的设置
Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。
path 属性是通过请求的地址来进行有效的过滤。
**CookieA path=/工程路径**
**CookieB path=/工程路径/abc**
请求地址如下:
**http://ip:port/工程路径/a.html**
CookieA 发送
CookieB 不发送
**http://ip:port/工程路径/abc/a.html**
CookieA 发送
CookieB 发送
### 7、Cookie练习——免用户名登录

**login.jsp页面**
```html
```
**LoginServlet程序**
```java
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("wzg168".equals(username) && "123456".equals(password)) {
//登录 成功
Cookie cookie = new Cookie("username", username);
cookie.setMaxAge(60 * 60 * 24 * 7);//当前 Cookie 一周内有效
resp.addCookie(cookie);
System.out.println("登录 成功");
} else {
// 登录 失败
System.out.println("登录 失败");
}
}
```
## Session会话
### 1、Session简介
1. Session 就一个接口(HttpSession)。
2. Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术。
3. 每个客户端都有自己的一个 Session 会话。
4. Session 会话中,我们经常用来保存用户登录之后的信息。
### 2、创建Session以及获取
如何创建和获取 Session。它们的 API 是一样的。
**request.getSession()**
- 第一次调用是:创建 Session 会话
- 之后调用都是:获取前面创建好的 Session 会话对象。
**isNew() ** 判断到底是不是刚创建出来的(新的)
- true 表示刚创建
- false 表示获取之前创建
> 每个会话都有一个身份证号。也就是 ID 值。而且这个 ID 是唯一的。 **getId() 得到 Session 的会话 id 值**
### 3、Session域数据的存取
| 方法 | 描述 |
| ----------------------- | ----------------------------------------------------- |
| setAttribute(key,value) | 往Session域中存放一个键值对 |
| getAttribute(key) | 取出Session域中存放的key所对应的value值,无则返回null |
### 4、Session生命周期控制
| 方法 | 描述 |
| ------------------------------------ | ------------------------------------------------------------ |
| setMaxInactiveInterval(int interval) | 设置 Session 的超时时间(以秒为单位),超过指定的时长,Session 就会被销毁。**值为正数的时候,设定 Session 的超时时长。 负数表示永不超时(极少使用)** |
| getMaxInactiveInterval() | 获取 Session 的超时时间 |
| public void invalidate() | 让当前 Session 会话马上超时无效。 |
**Session 默认的超时时间长为 30 分钟。**
设置默认的 Session 的超时时长为其他时长。可以web.xml 配置文件中做配置。就可以修改该 web 工程所有 Seession 的默认超时时长。
```xml
20
```
### 5、Session与浏览器之间底层实现

## 验证码
### 1、为什么要有验证码
- 注册环节:防止无效垃圾注册
- 登录环节:防止撞库攻击、暴力破解、保障用户数据
- 互动环节:防止批量垃圾互动信息破坏用户UGC内容生态
**追根接地验证码是解决表单重复提交问题**
### 2、解决表单重复提交
表单重复提交有三种常见的情况:
一:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。 造成表单重复提交问题。**解决方法:使用重定向来进行跳转**
二:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,就会着急,然后多点了几次提交操作,也会造成表单重复提交。 **解决方法:验证码**
三:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复提交。**解决方法:验证码**

## JSON
### 1、JSON简介
**JSON** (JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,而且很多语言都提供了对 json 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python等)。 这样就使得 JSON 成为理想的数据交换格式。
json 是一种轻量级的数据交换格式。
轻量级指的是跟 xml 做比较。
数据交换指的是客户端和服务器之间业务数据的传递格式。
### 2、JSON在JavaScript中的使用
json 是由键值对组成,并且由花括号(大括号)包围。每个键由引号引起来,键和值之间使用冒号进行分隔,多组键值对之间进行逗号进行分隔。
```js
var jsonObj = {
"key1": 12,
"key2":"value2",
....
}
```
**json的访问**
json 本身是一个对象。
json 中的 key 我们可以理解为是对象中的一个属性。
json 中的 key 访问就跟访问对象的属性一样: json 对象.key
**json的两个常用方法**
json 的存在有两种形式。
- 对象的形式存在,我们叫它 json 对象。
- 字符串的形式存在,我们叫它 json 字符串。
一般我们要操作 json 中的数据的时候,需要 json 对象的格式。
一般我们要在客户端和服务器之间进行数据交换的时候,使用 json 字符串。
**JSON.stringify()** 把 json 对象转换成为 json 字符串
**JSON.parse()** 把 json 字符串转换成为 json 对象
### 3、JSON在java中的使用
**JavaBean 和 json 的互转**
```java
@Test public void test1(){
Person person = new Person(1,"哈哈哈!");
// 创建 Gson 对象实例
Gson gson = new Gson();
// toJson 方法可以把 java 对象转换成为 json 字符串
String personJsonString = gson.toJson(person);
System.out.println(personJsonString);
// fromJson 把 json 字符串转换回 Java 对象
// 第一个参数是 json 字符串
// 第二个参数是转换回去的 Java 对象类型
Person person1 = gson.fromJson(personJsonString,Person.class);
System.out.println(person1);
}
```
**List 和 json 的互转**
```java
@Test public void test2() {
List personList = new ArrayList<>();
personList.add(new Person(1, "哈哈哈"));
personList.add(new Person(2, "康师傅"));
Gson gson = new Gson();
// 把 List 转换为 json 字符串
String personListJsonString = gson.toJson(personList);
System.out.println(personListJsonString);
List list = gson.fromJson(personListJsonString, new PersonListType().getType());
System.out.println(list);
Person person = list.get(0);
System.out.println(person);
}
```
**map 和 json 的互转**
```java
@Test public void test3(){
Map personMap = new HashMap<>();
personMap.put(1, new Person(1, "好帅"));
personMap.put(2, new Person(2, "康师傅也好帅"));
Gson gson = new Gson();
// 把 map 集合转换成为 json 字符串
String personMapJsonString = gson.toJson(personMap);
System.out.println(personMapJsonString);
Map personMap2 = gson.fromJson(personMapJsonString, new TypeToken>(){}.getType());
System.out.println(personMap2);
Person p = personMap2.get(1);
System.out.println(p);
}
```
## AJAX
### 1、AJAX请求简介
AJAX 即**A**synchronous **J**avascript **A**nd **X**ML(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
**ajax 是一种浏览器通过 js 异步发起请求,局部更新页面的技术。**
**Ajax 请求的局部更新,浏览器地址栏不会发生变化**
**局部更新不会舍弃原来页面的内容**
### 2、原生js中AJAX的运用
```html
Insert title here
```
### 3、jQuery中的AJAX请求
**$.ajax **方法
| 参数 | 描述 |
| -------- | ------------------------------------------------------------ |
| url | 表示请求的地址 |
| type | 表示请求的类型 GET 或 POST 请求 |
| data | 表示发送给服务器的数据 格式有两种: 一:name=value&name=value 二:{key:value} |
| success | 请求成功,响应的回调函数 |
| dataType | 响应的数据类型**text** 表示纯文本,**xml** 表示 xml 数据,**json** 表示 json 对象 |
```js
$("#ajaxBtn").click(function(){
$.ajax({
url:"http://localhost:8080/16_json_ajax_i18n/ajaxServlet",
// data:"action=jQueryAjax",
data:{action:"jQueryAjax"},
type:"GET", success:function (data) {
// alert("服务器返回的数据是:" + data);
// var jsonObj = JSON.parse(data);
$("#msg").html("编号:" + data.id + " , 姓名:" + data.name);
},
dataType : "json"
});
});
```
**$.get** 方法 和 **$.post** 方法
| 参数 | 描述 |
| -------- | ------------------------------------------------------------ |
| url | 表示请求的地址 |
| data | 表示发送给服务器的数据 格式有两种: 一:name=value&name=value 二:{key:value} |
| callback | 请求成功,响应的回调函数 |
| type | 响应的数据类型**text** 表示纯文本,**xml** 表示 xml 数据,**json** 表示 json 对象 |
**$.getJSON** 方法
| 参数 | 描述 |
| -------- | ------------------------------------------------------------ |
| url | 表示请求的地址 |
| data | 表示发送给服务器的数据 格式有两种: 一:name=value&name=value 二:{key:value} |
| callback | 请求成功,响应的回调函数 |
表单序列化 **serialize()**
**serialize()可以把表单中所有表单项的内容都获取到,并以 name=value&name=value 的形式进行拼接。**