# JavaWeb
**Repository Path**: mr-lsj/JavaWeb
## Basic Information
- **Project Name**: JavaWeb
- **Description**: Java Web 程序设计 课堂笔记 | Java Web
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-02-08
- **Last Updated**: 2023-02-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
> 本文约 7066 字,阅读大约需要 21 分钟(持续更新)
# Java Web 程序设计 课堂笔记 | Java Web
---
# 1、Java Web 入门
## 1.1 Web应用简介
- 静态网站和动态网站
- C/S和B/S架构
- Web应用运行过程
---
## 1.2 Eclipse Web应用环境配置
### 1.2.1 JDK配置:环境变量设置
### 1.2.2 Eclipse基本配置
- 字体,字号
- 加快启动速度
- workspace编码: utf-8
- jsp文件编码: utf-8
- installed jres设置
- Tomcat服务器配置
- 默认端口:8080,主机地址: localhost或者127.0.0.1,访问方式:localhost:8080
### 1.2.3 Web应用的目录结构

### 1.2.4 Web 应用发布到 Tomcat 中
#### 1.2.4.1 在Eclipse内部署到 tomcat 中,部署,启动(通常在开发中使用)
##### 步骤1:项目的部署(Add)与移除(Remove)


##### 步骤2:项目的清除(彻底清理,清空 ..\apache-tomcat-9.0.37\wtpwebapps 目录)

##### 步骤3:自定义项目文件部署路径
双击下方 Tomcat v9.0 Server at localhost ,Server Locations 中的选项配置:
**use workspace metadata (does not modify Tomcat installation)**:使用项目所在的 Workspace 位置,由系统自动选择
**use Tomcat installation (takes control of Tomcat installation)**:使用 Tomcat 安装所在位置
**use custom location (does not modify Tomcat installation)**:
**Deploy path**:部署路径(发布到所在文件夹 **..\apache-tomcat-9.0.37\wtpwebapps** )

##### 步骤4:添加并访问项目
在 Eclipse 中添加项目至 Tomcat 后发布并访问,网页访问方式:**127.0.0.1:8080/test/index.jsp** 或 **127.0.0.1:8080/test/**

#### 1.2.4.2 在 Eclipse 外部启动,部署,直接部署到 Tomcat 中,不通过 Eclipse (通常于开发完成后上线、脱离开发环境时使用)
web 应用可以将 war 包的形式部署到 Tomcat 中
##### 步骤1:在 eclipse 中将 web 应用打包成 war 包形式

##### 步骤2:选择 Web -> WAR file

##### 步骤3:设置项目导出 war 包路径

##### 步骤4:将项目导出的 war 包(test.war) 复制到 Tomcat 安装目录下的 webapps 目录(..\apache-tomcat-9.0.37\webapps)中

##### 步骤5∶启动 Tomcat
- 通过 **..\apache-tomcat-9.0.37\bin** 目录中的 **startup.bat** 和 **shutdown.bat** 文件来对 Tomcat 服务器进行启动和关闭
##### 步骤6:访问项目(test)应用
#### 1.2.4.3 快速创建一个 Java Web 项目
##### 步骤1:复制原有的 Java Web 项目

##### 步骤2:重命名新的 Java Web 项目

#### 步骤3:选择 Peoperties ,修改项目的根路径(Servlet 的页面路径)

#### 步骤4:在 Web Project Settings 修改路径(自定义)

### 1.2.5 Tomcat 的目录结构
- \bin:包含一些实用工具,主要掌握:**startup.bat** 脚本 - 启动 Tomcat 服务器,**shutdown.bat** 脚本 - 关闭 Tomcat 服务器
- \conf:包含服务器的配置文件,比如端口,用户等信息
- \lib:包含服务器和 Web 应用程序使用的类库,**jsp-api.jar** 和 **servlet-api.jar**
- \webapps:Web应用的发布目录,Eclipse 外部部署 **.war** 文件存放路径
- \wtpwebapps:Eclipse 中在 Tomcat 服务器安装路径下发布项目的默认路径(内部部署)
- \work:Web 应用程序的临时工作目录
- \temp:存放 Tomcat 运行时的临时文件目录
### 1.2.6 Tomcat 项目的部署与移除
- 项目的部署(Add)与移除(Remove)


- 项目的清除(彻底清理,清空 **..\apache-tomcat-9.0.37\wtpwebapps** 目录)

### 1.2.7 Tomcat 的图形化管理(管理员登陆)
#### 步骤1:配置管理员账号信息
- 打开 Tomcat 安装所在路径下 **..\apache-tomcat-9.0.37\conf** 中的 **tomcat-users.xml** 文件

- 在 **tomcat-users.xml** 文件 `` 标签中添加账户信息(用户名:**tomcat**;密码:**123**)
```html
```

#### 步骤2:管理员登陆
1. 通过 Tomcat 页面进入管理员登陆入口(或直接输入网址 **http://localhost:8080/manager/html**),选择 Host Manager

2. 在弹出窗口中填写已配置的用户名和密码
3. 进入管理页面 
---
# 2、Servle基础
## 2.1 Servlet基础
Servlet:运行在服务器端的 java 代码,运行在 Servlet 容器中的 java 类
什么是 Servlet 容器? Tomcat
Serlvet 功能:
- 接收处理用户的 Http 请求
- 给用户 HTTP 响应
---
## 2.2 Servlet体系结构

- javax.servlet 包
- **Servlet 接口**:开发人员编写的 Servlet 必须直接或者间接的实现 **javax.servlet.Servlet** 的接口
- 方法:
- **init(Servletconfig config)**:Servlet 的初始化方法,在 Servlet 实例化后,**容器调用该方法进行 Servlet 的初始化**; ServletAPI 规定对任何 Servlet 实例 init() 方法**只能被调用一次**。参数为 ServletConfig ,我们初始化过程中可以读取一些配置信息,比如 web.xml 中的信息
- **service(ServletRequest req,ServletResponse resp)**:Servlet 的服务方法。
- **destroy()**: Servlet 的销毁方法
- **getServletConfig()**:获得 ServletConfig 对象,该对象中包含了若干配置信息。
- **getServletInfo()**:一个 String 对象,该对象包含 Servlet 的信息。例如:开发者、创建日期、描述信息等。
- **GenericServlet抽象类**:与 Servlet 接口基本相同,只是为了是使用方便,做成抽象类的形式。
- **Javax.servlet.http.HttpServlet**:抽象类,能够处理 HTTP 请求的 servlet,它在原有 Servlet 接口上添加了对 HTTP 协议的处理,它比Servlet接口的功能更为强大。**用户编写的 Servlet 类多数基于该抽象类**。
- 方法:
- **service(HttpServletRequest req, HttpServletResponse resp)**:重写了 **Servlet接口** 的 service() 方法,该方法会自动判断用户的请求方式;若为 **GET** 请求,则调用 HttpServlet的doGet() 方法;若为 **POST** 晴求,则调用 doPost() 方法。
- **doGet(HttpServletRequest req,HttpServletResponse resp)**:此方法被本类的 service() 方法调用,用来处理一个 HTTP GET 操作。
- **doPost(HttpServletRequest req,HttpServletResponse resp)**:此方法被本类的 service() 方法调用,用来处理一个 HTTP POST 操作。
- javax.servlet.http 包
---
## 2.3 Servlet 生命周期
(选择、判断)
- Servlet 生命周期是指 Servlet 实例从创建( **init() 方法**)到响应客户请求( **doPost()、doGet() 方法**),直至销毁( **destory() 方法** )的过程。
- Servlet 程序本身**不直接**在 Java 虚拟机上运行,由 **Servlet 容器( Tomcat )**负责管理其整个生命周期。
- 在 Servlet 生命周期中,会经过创建、初始化、服务可用、服务不可用、处理请求、终止服务、销毁七种状态。
- Servlet 生命周期可分为四个阶段:加载和实例化、初始化、处理请求、销毁。
Servlet 生命周期中七种状态间的转换关系以及转换过程的四个阶段:

### 2.3.1 第一阶段:加载和实例化
- Servlet 的创建是指加载和实例化两个过程
- Servlet 容器在如下时刻加载和实例化一个 Servlet:
- 在服务器运行中,**客户机首次向Servlet发出请求时**(创建对象);
- 重新装入 Servlet 时,如:**服务器重新启动、Servlet 被修改**;
- 在为 Servlet 配置了自动装入选项(load-on-startup)时,服务器在启动时会自动装入此 Servlet。
### 2.3.2 第二阶段:初始化
- Servlet 实例化后,Servlet 容器将调用 Servlet 的 init(ServletConfig config) 方法来对 Servlet 实例进行初始化(**容器自动进行初始化**);
- 如果初始化没有问题,Servlet 在 Web 容器中会处于服务可用状态;如果初始化失败,Servlet 容器会从运行环境中清除掉该实例;
- 当 Servlet 运行出现异常时,Servlet 容器会使该实例变为服务不可用状态。Web 程序维护人员可以设置 Servlet,使其成为服务不可用状态,或者从服务不可用状态恢复成服务可用状态。
### 2.3.3 第三阶段:处理请求
- 服务器接收到客户端请求,会为该请求创建一个“请求”对象和一个“响应”对象并调用 **service() 方法**,service() 方法再调用其他方法来处理请求;
- 在Servlet生命周期中,service() 方法可能被**多次调用**。当多个客户端同时访问某个 Servlet 的 service() 方法时,**服务器会`为每个请求创建一个线程`,这样可以**并行**处理多个请求,减少请求处理的等待时间,提高服务器的响应速度**。但同时也要注意对同一对象的并发访问问题。
### 2.3.4 第四阶段:销毁
- 当 Servlet 容器需要终止 Servlet(比如 Web 服务器即将被关掉或需要出让资源),它会先调用 Servlet 的 destroy() 方法使其释放正在使用的资源。在 Servlet 容器**调用 destroy() 方法**之前,**必须让当前正在执行 service() 方法的任何线程完成执行**,或者超过了服务器定义的时间限制。在 destroy() 方法完成后, Servlet 容器必须释放 Servlet 实例以便被垃圾回收。
---
## 2.4 创建一个 Servlet 文件
- 步骤1

- 步骤2
Java package:包名
Class name:类名
Superclass:使用的父类

- 步骤3
Name:Servlet 名称(别名或代号)
Description:描述
URL mappings:访问方式

- 步骤4
- 初始化文件

---
## 2.5 Servlet 的创建过程
- 两种方式:传统的通过 web.xml 进行配置;注解方式配置
### 2.5.1 web.xml 方式配置
#### 步骤1

#### 步骤2:创建 Java 文件

#### 步骤3:在 Java 文件中编写以下代码
```java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Servlet 创建:web.xml 方式配置 */
public class HelloServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
System.out.println("welcome");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doPost(req, resp);
}
}
```
#### 步骤4:编辑 /WEB-INF 目录下的 web.xml 文件

```html
newProject
index.jsp
Hello1
com.servlet.c1.HelloServlet1
Hello1
/hello1
```
#### 步骤5:访问页面
通过链接访问 **localhost:8080/newProject/hello1**,访问后可检查控制台输出信息

### 2.5.2 通过 web.xml 进行 Servlet 声明配置的属性及描述
```html
Servlet样例
XXServlet
XXServlet
com.qst.chapter02.servlet.XXServlet
username
qst
0
true
XXServlet
/XX
```
### 2.5.3 注解方式配置(常用)
#### 步骤1

#### 步骤2:创建 Java 文件

#### 步骤3:在 Java 文件中编写以下代码
```java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** 添加注解,对文件进行解释,表示 HelloServlet2 类为 Servlet 文件
* name:定义的 Servlet 名称
* urlPatterns:访问方式:http://localhost:8080/newProject/hello2
*/
@WebServlet(name = "hello2", urlPatterns = "/hello2")
public class HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
System.out.println("welcome2");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
}
}
```
#### 步骤4:访问页面
通过链接访问 **localhost:8080/newProject/hello2**,访问后可检查控制台输出信息

### 2.5.4 注解 @WebServlet 的属性及描述
类型 | 属性名 | 描述
:-- | :-- | :--
name | String | 指定Servlet的名字,可以为任何字符串,一般与Servlet的类名相同,如果没有显式指定,则该Servlet的取值即为类的全限定名
urlPatterns | String[] | 指定一组Servlet的URL匹配模式,可以是匹配地址映射(如:/SimpleServlet )、匹配目录映射(如:/servlet/\*)和匹配扩展名映射(如:\*.action)
value | String[] | 该属性等价于 urlPatterns 属性。两个属性不能同时使用
loadOnStartup | int | 指定 Servlet 的加载顺序。当此选项没有指定时,表示容器在该 Servlet 第一次被请求时才加载;当值为 0 或者大于 0 时,表示容器在应用启动时就加载这个Servlet。值越小,启动该 Servlet 的优先级越高。原则上不同的 Servlet 应该使用不同的启动顺序数字
initParams | WeblnitParam[] | 指定一组 Servlet 初始化参数,为可选项
asyncSupported | boolean | 声明 Servlet 是否支持**异步操作模式**(效率较高),默认为 false
description | String | 指定该 Servlet 的描述信息
displayName | String | 指定该 Servlet 的显示名,通常配合工具使用
### 2.5.5 注解 @WebServlet 的使用示例
```java
@WebServlet(
name = "XXServlet", urlPatterns = { "/XX" },
initParams = { @WebInitParam(name = "username", value = "qst") },
loadOnStartup = 0, asyncSupported = true,
displayName = "XXServlet",description="Servlet样例"
)
public class XXServlet extends HttpServlet {
……
}
```
---
## 2.6 Servlet 的应用
### 2.6.1数据处理( 前台 -> 后台 )
#### 2.6.1.1 处理超链接请求数据
##### 1. 语法格式
```html
链接文本
```
##### 2. 示例
>**LinkRequestServlet**:Servlet 文件名
> **?**:跳转地址之后传递的参数
> **pageNo**:键(key)/ 参数名
> **2**:值(value)
> **queryString**:键(key)
> **"QST"**:值(value)
> **?pageNo=2&queryString=QST**:查询字符串
```html
……
下一页
……
```
##### 3. 发送请求的两种地址形式
- 绝对地址:http://localhost:8080/chapter02/
- 相对地址(相对于当前的页面或相对于当前的 Servlet):LinkRequestServlet、../LinkRequestServlet
- 当通过超链接发送的请求到达 Servlet 容器时,包含数据的请求将被容器转换为 **HttpServletRequest 对象**。由 HttpServletRequest 对象完成请求数据的处理。
- HttpServletRequest对象常用的数据处理方法:
```java
// 获取单个参数的值,返回由 name 指定的用户请求参数所对应的值
public String getParameter(String name);
// 获取多个值,返回由name指定的一组用户请求参数的值
public String[] getParameterValues(String name);
// 获取参数名称,返回所有客户请求的参数名
public Enumeration getParameterNames();
```
#### 2.6.1.2 处理 Form 表单请求数据
##### 1. 语法格式
```html
```
##### 2. 示例
> FormRequestServlet:请求的服务器端Servlet地址
> POST:请求类型
```html
```
##### 3. 注意
- form 中需要注意的问题(两个属性):
- **method**:请求提交的方式是get还是**post**
- **action**:指定的是由谁来处理这个请求,一般action要指定一个servlet的地址,**表单提交地址**
- 表单中的标签如果需要气象服务端提交数据,则必须有 **name** 属性,或者说后台获取的数据就是通过表单的 **name** 属性提交的,其他的如id属性等等是不能提交数据的。(当获取数据是通过 request.getParameter() 方法实现的时候)
- 在 Servlet 中获取数据的方式与超链接的方式相同,都是通过 HttpServletRequest 对象实现的
- **public String getParameter(String name)**:返回由name指定的用户请求参数的值。
```java
String pageNo = request.getParameter("pageNo");
String queryString = request.getParameter("queryString");
```
- **public String[] getParameterValues(String name)**:返回由 name 指定的一组用户请求参数的值。
```java
String[] favors = request.getParameterValues("favors");
```
- **public Enumeration getParameterNames()**:返回所有客户请求的参数名。
```java
//获取所有表单中参数的名字
Enumeration e= request.getParameterNames();
StringBuilder builder = new StringBuilder();
while(e.hasMoreElements()) {
String s = e.nextElement();
builder.append(s);
builder.append(",");
}
System.out.println(builder.toString());
```
##### 4.文件结构及源代码(实例)
> 目录结构
```tree
newProject2
├── Java Resources
│ └── src
│ └── com.servlet.c1
│ └── FormServlet.java
├── build
├── WebContent
│ ├── META-INF
│ └── WEB-INF
│ ├── lib
│ └── web.xml
├── index.jsp
└── login.jsp
```
---
> 源代码
**FormServlet.java**(处理 Form 表单请求数据)
```java
package com.servlet.c1;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/FormServlet")
public class FormServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public FormServlet() {
super();
}
/** request 请求对象,response:响应对象 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/** 中文乱码问题
* 1 乱码可能出现的位置,请求时 request 中,或者相应时出现在 response 中
* 2 解决办法:在 request 或 response 中解决,设置编码方式
*/
request.setCharacterEncoding("utf-8");
// 设置响应文本类型为 HTML,字符编码为 UTF-8
response.setContentType("text/html; charset=utf-8");
response.setCharacterEncoding("utf-8");
// 获取请求数据
String loginName = request.getParameter("loginName");
String password = request.getParameter("password");
String[] favors = request.getParameterValues("favors");
// 返回枚举集合,相当于迭代器,用于存放参数名称(loginName、password、favors、btlogin)
Enumeration e = request.getParameterNames();
// 获取输出流
PrintWriter out = response.getWriter();
// 只能把数据写入到缓冲区中,缓冲区不满的话,要输出数据应使用 flush 方法和 close 方法
out.print("账号:");
out.print(loginName);
out.print("
密码:");
out.print(password);
// 爱好
out.print("
爱好:");
for(String f : favors) {
out.print(f);
out.print(",");
}
out.print("
");
// 输出参数名称
out.print("表单参数有:");
// 使用迭代器
while(e.hasMoreElements()) {
String p = e.nextElement();
out.print(p);
out.print(" ");
}
out.print("
");
// 响应输出数据
out.flush();
out.close();
}
}
```
---
**web.xml**
```html
newProject2
index.jsp
```
---
**index.jsp**(默认访问首页)
```html
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
Insert title here
首页
hello world
下一页
```
---
**login.jsp**(表单提交页面)
```html
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
login
```
---
### 2.6.2 重定向和请求转发(跳转)
#### 2.6.2.1 重定向
- 重定向是指由原请求地址重新定位到某个新地址,原有的request 请求失效,客户端看到的是新的 request 请求返回的响应结果,客户端浏览器地址栏变为新请求地址。
- 由请求 ServletA 到 ServletB 的重定向过程

- 重定向通过 HttpServletResponse 对象的 sendRedirect() 方法实现
##### 1. 语法格式
> 参数 **location**:指定重定向的 URL(所要跳转的页面)
```java
public void sendRedirect(String location)throws java.io.IOException
```
##### 2. 示例
> /chapter02/index.jsp:重定向到当前应用程序(chapter02)的根目录下的index.jsp页面
```java
response.sendRedirect("/chapter02/index.jsp");
```
---
> 总结:
> - 可以重定向到当前应用,也可以重定向到外部
> - 实现方式:通过 response 对象来实现
> ```java
> response.sendRedirect("/insex.jsp")
> ```
> - 两次请求,两次响应
> - 地址栏会发生变化
> - 因为是两次请求,两次相应,在重定向的过程中,请求中的数据是不能保持的,或者说是**会丢数据**
#### 2.6.2.2 请求转发
- 请求转发是指将请求再转发到其他地址,转发过程中使用的是同一个 request 请求,转发后浏览器地址栏内容不变。
- 由请求 ServletA 到 ServletB 的转发过程(请求、相应只有一次,地址不变)

- 请求转发使用 RequestDispatcher 接口中的 forward() 方法来实现,该方法可以把请求转发给另外一个资源,并让该资源对此请求进行响应。
##### 1. 语法格式
> **forward() 方法**:将请求转发给其他资源
> **include() 方法**:将其他资源并入到当前请求中
```java
RequestDispatcher dispatcher = request.getRequestDispatcher(String path);
dispatcher.forward(ServletRequest request,ServletResponse response);
```
##### 2. 示例
- 表示请求转发到当前项目站点的根目录下的 index.jsp 页面
```java
RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp").forward(request, response);
```
##### 3. 目录结构及源代码(实例)
> 目录结构
```tree
newProject2
├── Java Resources
│ └── src
│ └── com.servlet.c1
│ └── RedirectServlet.java
├── build
├── WebContent
│ ├── META-INF
│ └── WEB-INF
│ ├── lib
│ └── web.xml
├── index.jsp
└── login.jsp
```
---
> 源代码
**RedirectServlet.java**
```java
package com.servlet.c1;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/RedirectServlet")
public class RedirectServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public RedirectServlet() {
super();
}
/** request 请求对象,response:响应对象 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/** 中文乱码问题
* 1 乱码可能出现的位置,请求时 request 中,或者相应时出现在 response 中
* 2 解决办法:在 request 或 response 中解决,设置编码方式
*/
request.setCharacterEncoding("utf-8");
// 设置响应文本类型为 HTML,字符编码为 UTF-8
response.setContentType("text/html; charset=utf-8");
response.setCharacterEncoding("utf-8");
// 获取请求数据
String loginName = request.getParameter("loginName");
String password = request.getParameter("password");
String[] favors = request.getParameterValues("favors");
// 如果用户是 tom,密码是 1234,直接跳转到首页上
if(loginName.equals("tom") && password.equals("1234")) {
// 重定向方式;"/" 代表应用的根目录;两次请求,两次响应
response.sendRedirect("/newProject2/index.jsp");
// // 请求转发的方式;一次请求,一次响应
// RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
// dispatcher.forward(request, response);
}
}
}
```
---
**web.xml**
```html
newProject2
index.jsp
```
---
**index.jsp**(默认访问首页)
```html
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
Insert title here
首页
hello world
下一页
```
---
**login.jsp**(表单提交页面)
```html
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
login
```
---
> 总结:
> - 只可以跳转到当前应用的内部
> - 实现方式:通过RequestDispatcher 对象来实现,该对象可以通过 request 对象获取
> ```java RequestDispatcher dispatcher =
> request.getRequestDispatcher("/index.jsp");
> dispatcher.forward(request, response);
> ```
> - 一次请求,一次响应
> - 地址栏不会发生变化
> - 数据请求转发的过程中是能够一直保持的,也就是说在后面的 Servlet 中是可以获取之前数据的。**不丢数据**