认识
Servlet 就是 Sun 公司开发动态 Web 的一门技术
Sun 在这些 API (Application Programming Interface,应用程序接口)中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口。
- 把开发好的Java类部署到web服务器中。
把实现了 Servlet 接口的 Java 程序叫做,Servlet
广义的 Servlet
广义的 Servlet 不仅仅指的是实现了 Servlet
接口的 Java 类,还包括与 Servlet 相关的一系列技术和组件,如 Servlet 容器、过滤器(Filter)、监听器(Listener)等,它们共同构成了 Java Web 应用的基础架构。
狭义的 Servlet
狭义的 Servlet 指的是遵循 Servlet 规范编写的 Java 类,这些类实现了 javax.servlet.Servlet
接口或继承自 javax.servlet.GenericServlet
、javax.servlet.http.HttpServlet
等抽象类。它们用于处理客户端的 HTTP 请求,并生成相应的响应。
生命周期
Servlet 的生命周期包括以下几个阶段:
- 加载和实例化:当客户端第一次请求某个 Servlet 时,Web 服务器会加载该 Servlet 类并创建其实例。
- 初始化:Servlet 实例创建后,服务器会调用其
init
方法进行初始化操作。init
方法在 Servlet 的整个生命周期中只会被调用一次。 - 服务:当客户端发送请求时,服务器会调用 Servlet 的
service
方法。service
方法会根据请求的类型(如 GET、POST)调用相应的doGet
或doPost
方法来处理请求。 - 销毁:当 Web 服务器关闭或 Servlet 被卸载时,服务器会调用 Servlet 的
destroy
方法进行资源释放和清理工作。
工作原理
概述
- 客户端发起请求:客户端(如浏览器)通过 HTTP 协议向 Web 服务器发送请求。
- 服务器接收请求:Web 服务器(如 Tomcat)接收到请求后,根据请求的 URL 查找对应的 Servlet。
- 调用 Servlet:如果找到对应的 Servlet,服务器会创建或复用 Servlet 实例,并调用其相应的方法(如
doGet
或doPost
)来处理请求。 - Servlet 处理请求:Servlet 方法根据请求的信息进行相应的处理,如读取请求参数、访问数据库等。
- 生成响应:Servlet 处理完请求后,生成响应数据,如 HTML 页面、JSON 数据等,并将其发送回客户端。
- 服务器返回响应:Web 服务器将 Servlet 生成的响应发送给客户端。
在 Maven Web 项目中,当你启动项目后,会生成一个target的目录。 target
包是 Maven 构建过程中产生的输出目录,主要包含以下内容:
- 编译后的类文件:项目中所有 Java 源文件(如
src/main/java
目录下的BasicServlet
等类文件)**经过编译后生成的.class
文件,**会被放置在target/classes
目录及其子目录中,这些字节码文件是程序运行时 JVM 可执行的文件。 - 资源文件:
src/main/resources
目录下的资源文件,在构建过程中会被复制到target/classes
目录中,比如配置文件等,方便运行时程序读取。 - 打包后的文件:如果对项目进行打包操作(如执行
mvn package
命令),会生成如 WAR 包(Web 应用归档文件)等,也会存放在target
目录下。这些包可以直接部署到 Tomcat 等 Web 服务器上运行。 - 生成的辅助文件:像
generated-sources
目录下存放的由 Maven 插件生成的一些源文件,例如注解处理生成的文件等 ,用于辅助项目的编译和运行。
target
包对于项目的编译、运行、部署都至关重要,是项目从源码到可执行或可部署状态的中间产物集合。
target和Servlet 生命周期
target/classes
下的文件与 Servlet 的生命周期密切相关。
1. 加载和实例化阶段
在 Web 应用启动时,Web 服务器(如 Tomcat)会去 target/classes
目录及其子目录中查找 Servlet 类的字节码文件(.class
文件)。例如图中的 BasicServlet
、RedirectServlet
和 SubmitForm
等 Servlet 类,编译后的字节码文件就存放在该目录对应的包结构下。服务器加载这些字节码文件,并通过类加载机制将其加载到 JVM 中,然后创建 Servlet 实例(上文提到过,当你第一次访问时才会创建servlet实例,并且每个servlet只有一个实例),这个过程依赖于 target/classes
下正确的字节码文件,没有它们,服务器无法识别和实例化 Servlet。
2. 初始化阶段
Servlet 实例创建后,服务器会调用其 init
方法进行初始化。init
方法中可能会读取配置文件等资源,而这些配置文件如果在项目开发阶段放在 src/main/resources
目录下,在构建过程中会被复制到 target/classes
目录中,Servlet 可以从这里读取所需信息来完成初始化,因此 target/classes
下的资源文件对于 Servlet 初始化过程必不可少。
Servlet :
public interface Servlet {void init(ServletConfig var1) throws ServletException;ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;String getServletInfo();void destroy();
}
GenericServlet:
public void init(ServletConfig config) throws ServletException {this.config = config;this.init();
}
初始化信息
ServletConfig
是一个由 Servlet 容器(如 Tomcat)创建并传递给 Servlet 的对象,它包含了 Servlet 的配置信息。包含的配置信息如下:
- Servlet 名称
- 初始化参数
<init-param>
- ServletContext
Servlet 名称
- 获取方法:通过
getServletName()
方法获取。 - 配置方式:在部署描述符(如
web.xml
)中使用<servlet-name>
标签进行配置;若使用注解方式(如@WebServlet
),则由注解中的name
属性指定。
//--------------**web.xml 配置**:-----------------
<servlet><servlet-name>MySampleServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class>
</servlet>//--------------**注解方式**:-----------------
@WebServlet(name = "MySampleServlet", urlPatterns = "/myServlet")
public class MyServlet extends HttpServlet {// Servlet 实现代码
}
初始化参数
- 获取方法
- 通过
getInitParameter(String name)
方法获取指定名称的初始化参数值。 - 通过
getInitParameterNames()
方法获取所有初始化参数的名称枚举。
- 通过
- 配置方式:在
web.xml
中使用<init-param>
标签进行配置;若使用注解方式,可在@WebServlet
注解中使用initParams
属性指定。
//--------------**web.xml 配置**:-----------------
<servlet><servlet-name>MySampleServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class><init-param><param-name>dbUrl</param-name><param-value>jdbc:mysql://localhost:3306/mydb</param-value></init-param><init-param><param-name>dbUser</param-name><param-value>root</param-value></init-param>
</servlet>
//--------------**注解方式**:-----------------
@WebServlet(name = "MySampleServlet", urlPatterns = "/myServlet", initParams = {@WebInitParam(name = "dbUrl", value = "jdbc:mysql://localhost:3306/mydb"),@WebInitParam(name = "dbUser", value = "root")})
public class MyServlet extends HttpServlet {// Servlet 实现代码
}
ServletContext 对象
- 获取方法:通过
getServletContext()
方法获取。 - 配置方式:由 Servlet 容器自动创建和管理,无需开发者手动配置。
3. 服务阶段
当客户端发送请求时,服务器根据请求的 URL 找到对应的 Servlet 实例,并调用其 service
方法,进而根据请求类型(如 GET
、POST
)调用 doGet
或 doPost
等方法处理请求。在处理请求过程中,Servlet 可能会调用其他类、访问数据库等,这些相关类的字节码文件同样存放在 target/classes
目录下,只有该目录下的类文件完整且正确,Servlet 才能正常执行服务逻辑。
4. 销毁阶段
当 Web 应用停止或服务器关闭时,Servlet 的 destroy
方法会被调用以释放资源。destroy
方法执行过程中,也可能依赖于 target/classes
目录下的一些配置信息来完成资源清理等操作,例如关闭与特定配置相关的连接等。
target/classes
下的文件是 Servlet 生命周期各个阶段能够正常运行的基础,包含了 Servlet 类及其依赖类的字节码文件以及相关资源文件等关键内容。
web.xml
常见配置元素
1. Servlet 配置
<servlet><servlet-name>MyServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class><init-param><param-name>param1</param-name><param-value>value1</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/myServlet</url-pattern>
</servlet-mapping>
<servlet>
:定义一个 Servlet,包含 Servlet 的名称和对应的 Java 类。<servlet-name>
:为 Servlet 命名,用于在其他配置中引用。<servlet-class>
:指定 Servlet 类的全限定名。<init-param>
:为 Servlet 设置初始化参数。<load-on-startup>
:指定 Servlet 的加载顺序,数值越小越先加载。<servlet-mapping>
:将 Servlet 映射到一个或多个 URL 模式。
2. 过滤器配置
<filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class><init-param><param-name>filterParam</param-name><param-value>filterValue</param-value></init-param>
</filter>
<filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
:定义一个过滤器,包含过滤器的名称和对应的 Java 类。<filter-name>
:为过滤器命名。<filter-class>
:指定过滤器类的全限定名。<init-param>
:为过滤器设置初始化参数。<filter-mapping>
:将过滤器映射到一个或多个 URL 模式。
3. 监听器配置
<listener><listener-class>com.example.MyListener</listener-class>
</listener>
<listener>
:注册一个监听器,指定监听器类的全限定名。
4. 全局初始化参数
<context-param><param-name>globalParam</param-name><param-value>globalValue</param-value>
</context-param>
<context-param>
:设置整个 Web 应用的初始化参数。
5. 错误页面配置
<error-page><error-code>404</error-code><location>/404.jsp</location>
</error-page>
<error-page><exception-type>java.lang.Exception</exception-type><location>/error.jsp</location>
</error-page>
<error-page>
:指定不同 HTTP 错误状态码或异常类型对应的错误处理页面。
示例 web.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 全局初始化参数 --><context-param><param-name>globalParam</param-name><param-value>globalValue</param-value></context-param><!-- Servlet 配置 --><servlet><servlet-name>MyServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class><init-param><param-name>param1</param-name><param-value>value1</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/myServlet</url-pattern></servlet-mapping><!-- 过滤器配置 --><filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class><init-param><param-name>filterParam</param-name><param-value>filterValue</param-value></init-param></filter><filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 监听器配置 --><listener><listener-class>com.example.MyListener</listener-class></listener><!-- 错误页面配置 --><error-page><error-code>404</error-code><location>/404.jsp</location></error-page><error-page><exception-type>java.lang.Exception</exception-type><location>/error.jsp</location></error-page>
</web-app>
与注解的对比
从 Servlet 3.0 开始,Java 支持使用注解(如 @WebServlet
、@WebFilter
、@WebListener
等)来替代部分 web.xml
的配置。注解的优点是代码更加简洁,配置与代码紧密结合;而 web.xml
的优点是配置集中,便于统一管理和维护,对于复杂的配置场景更为合适。在实际开发中,也可以将注解和 web.xml
结合使用。
ServletContext
ServletContext
是 Java Servlet 规范中的一个重要接口,代表整个 Web 应用程序,在 Web 应用的生命周期内只有一个 ServletContext
实例。
获取方式
在 Servlet 中,可以通过以下两种常见方式获取 ServletContext
对象:
- 通过
ServletConfig
获取:重写init()方法。在 Servlet 的init(ServletConfig config)
方法中,可以通过config.getServletContext()
方法获取ServletContext
对象。示例代码如下: - 直接获取:在 Servlet 中,也可以直接通过
getServletContext()
方法获取ServletContext
对象。
public class MyServlet extends HttpServlet {private ServletContext context;//重写init()方法即可@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);context = config.getServletContext();}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = getServletContext();}
}
常用方法
- 存储和获取属性
void setAttribute(String name, Object object)
:将一个对象存储在ServletContext
中,使用指定的名称作为键。Object getAttribute(String name)
:根据指定的名称从ServletContext
中获取存储的对象,如果对象不存在则返回null
。void removeAttribute(String name)
:从ServletContext
中移除指定名称的属性。
- 读取资源文件
java.io.InputStream getResourceAsStream(String path)
:返回指定路径下资源文件的输入流,用于读取文件内容。java.net.URL getResource(String path)
:返回指定路径下资源文件的 URL。
- 获取初始化参数
String getInitParameter(String name)
:返回指定名称的应用初始化参数的值,如果参数不存在则返回null
。java.util.Enumeration<String> getInitParameterNames()
:返回所有应用初始化参数名称的枚举。
- 请求转发
getRequestDispatcher(String path)
此外还有:
- 日志记录:log()
- 获取上下文路径:String getContextPath()
--------------------存储和获取属性----------------------
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("Hello Servlet");ServletContext context = this.getServletContext();context.setAttribute("msg", "Hello Servlet");}
}public class ReadContextServelt extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String msg = (String) this.getServletContext().getAttribute("msg");System.out.println(msg);resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().print("ReadContextServlet"+ msg);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
------------------读取资源文件-----------------------
public class TwoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/dp.properties");Properties properties = new Properties();properties.load(is);String username = properties.getProperty("username");String password = properties.getProperty("password");resp.getWriter().print("username:"+username+" password:"+password);}
}
-----------------获取初始化参数-------------------
public class GetParamServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = context.getInitParameter("user");String password = context.getInitParameter("password");resp.getWriter().write("username:"+username+" password:"+password);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}<context-param><param-name>user</param-name><param-value>root</param-value></context-param><context-param><param-name>password</param-name><param-value>123456</param-value></context-param>
-------------------------请求转发---------------------
public class SourceServletWithContext extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取 ServletContext 对象ServletContext context = getServletContext();// 通过 ServletContext 获取 RequestDispatcher 对象RequestDispatcher dispatcher = context.getRequestDispatcher("/targetServlet");// 执行转发操作dispatcher.forward(request, response);}
}
public class TargetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");response.getWriter().println("<html><body>");response.getWriter().println("<h2>这是目标 Servlet 处理的结果</h2>");response.getWriter().println("</body></html>");}
}
HttpServletResponse
功能概述
- 设置响应状态码:告知客户端请求的处理结果,如 200 表示请求成功,404 表示请求的资源不存在,500 表示服务器内部错误等。
- 设置响应头:可以设置各种 HTTP 响应头信息,如内容类型、缓存控制、字符编码等,用于控制客户端对响应的处理方式。
- 输出响应体:向客户端发送实际的响应内容,如 HTML 页面、JSON 数据、图片等。
常用方法
1. 设置响应状态码
setStatus(int sc)
:设置 HTTP 响应的状态码。例如,response.setStatus(HttpServletResponse.SC_OK)
表示请求成功,状态码为 200。sendError(int sc)
:发送错误响应给客户端,同时设置相应的错误状态码。例如,response.sendError(HttpServletResponse.SC_NOT_FOUND)
表示请求的资源不存在,状态码为 404。
2. 设置响应头
setHeader(String name, String value)
:设置指定名称的响应头及其值。例如,response.setHeader("Content-Type", "text/html;charset=UTF-8")
用于设置响应内容的类型为 HTML,并指定字符编码为 UTF-8。addHeader(String name, String value)
:添加一个响应头,如果该名称的响应头已经存在,则会添加一个新的值。setContentType(String type)
:设置响应内容的类型。例如,response.setContentType("application/json")
表示响应内容为 JSON 数据。setCharacterEncoding(String charset)
:设置响应的字符编码。例如,response.setCharacterEncoding("UTF-8")
用于指定响应使用 UTF-8 编码。
3. 输出响应体
getWriter()
:返回一个PrintWriter
对象,用于以字符流的方式输出响应内容。通常用于输出文本数据,如 HTML 页面、JSON 字符串等。getOutputStream()
:返回一个ServletOutputStream
对象,用于以字节流的方式输出响应内容。通常用于输出二进制数据,如图片、文件等。
代码示例
public class SendErrorExampleServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.sendError(404, "404 Not Found");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
public class SetStatusExampleServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setStatus(666);resp.setStatus(200);resp.getWriter().write("更改状态响应码");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
实现重定向
public class RedirctServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {log("RedirctServlet");resp.sendRedirect("/r/basic");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
public class BasicServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("basic");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
HttpServletRequest
HttpServletRequest
是 Java Servlet 规范中的一个重要接口,它封装了客户端发送的 HTTP 请求信息。Servlet 可以通过 HttpServletRequest
对象获取客户端请求的各种信息,如请求参数、请求头、请求方法等,从而根据这些信息进行相应的处理。以下从功能、常用方法、使用示例等方面详细介绍。
功能概述
- 获取请求参数:客户端在发送请求时,可能会携带一些参数,如表单数据、URL 参数等。
HttpServletRequest
提供了方法来获取这些参数的值。 - 获取请求头信息:HTTP 请求包含多个请求头,如
User - Agent
、Cookie
等。通过HttpServletRequest
可以获取这些请求头的信息。 - 获取请求方法:确定客户端发送请求所使用的方法,如
GET
、POST
等。 - 获取请求的 URL 和 URI:获取客户端请求的完整 URL 或相对 URI,用于处理请求路径相关的逻辑。
- 获取会话信息:通过
HttpServletRequest
可以获取或创建用户的会话(HttpSession
),用于在多个请求之间共享数据。
获取请求参数代码演示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>表单提交示例</title>
</head>
<body>
<form action="submitForm" method="post"><!-- 普通文本输入框,对应单个值的参数 --><label for="username">用户名:</label><input type="text" id="username" name="username"><br><!-- 显示爱好标签 --><span>爱好:</span><br><!-- 多选框,对应多个值的参数 --><input type="checkbox" id="reading" name="hobbies" value="阅读"><label for="reading">阅读</label><br><input type="checkbox" id="sports" name="hobbies" value="运动"><label for="sports">运动</label><br><input type="checkbox" id="music" name="hobbies" value="音乐"><label for="music">音乐</label><br><input type="submit" value="提交">
</form>
</body>
</html>public class SubmitForm extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 设置响应内容类型和字符编码resp.setContentType("text/html;charset=UTF-8");PrintWriter out = resp.getWriter();// 使用 getParameter 方法获取单个值的参数String username = req.getParameter("username");out.write(username);// 使用 getParameterValues 方法获取多个值的参数String[] hobbies = req.getParameterValues("hobbies");if (hobbies != null) {for (String hobby : hobbies) {out.println("<p>" + hobby + "</p>");}}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}
补充
ServletContext与 ServletRequest
获取 RequestDispatcher
的区别
ServletRequest.getRequestDispatcher
:路径是相对于当前请求的路径。例如,如果当前请求的 URL 是/app/someServlet
,调用request.getRequestDispatcher("anotherServlet")
会将请求转发到/app/anotherServlet
。ServletContext.getRequestDispatcher
:路径是相对于 Web 应用的根目录。例如,context.getRequestDispatcher("/anotherServlet")
会将请求转发到 Web 应用根目录下的anotherServlet
。
转发和重定向
在 Java Web 开发中,转发(Forward)和重定向(Redirect)是两种常用的页面跳转方式,它们都能实现从一个资源跳转到另一个资源,但在多个方面存在明显区别。
转发是服务器端的行为。当客户端发送请求到服务器的某个 Servlet 或 JSP 页面时,如果该资源无法完全处理请求,或者需要其他资源协助处理,服务器会直接将请求转发给另一个 Servlet、JSP 页面或静态资源,整个过程都在服务器内部完成,客户端并不知道请求发生了转发。
重定向:是客户端的行为(重新定义方向,换页面,全换)。服务器接收到客户端的请求后,会返回一个重定向响应(状态码 302 或 303)给客户端,其中包含了新的 URL 地址。客户端收到这个响应后,会自动向新的 URL 地址发送一个新的请求。
-
转发:整个过程只涉及一次请求。url不会变化
-
重定向:涉及两次请求。url变化
-
转发示例代码与说明:
在一个大型的用户管理系统中,用户注册功能涉及多个步骤**,如输入验证、数据插入数据库、发送注册成功邮件等**。为了提高代码的可维护性和复用性,可以将这些步骤拆分成不同的 Servlet 来处理,通过转发实现模块之间的协作。在整个用户注册流程中,如果只是在服务器端的不同 Servlet 之间进行转发处理,且没有返回新的页面内容给客户端,前端页面从用户的视觉上看不会发生变化。例如,在输入验证、数据插入数据库、发送注册成功邮件这些步骤中,服务器端的 Servlet 依次处理请求,期间只是在内部传递数据和执行逻辑,没有给客户端返回新的 HTML 页面。
// 处理用户注册表单提交的 Servlet
@WebServlet("/registerForm")
public class RegisterFormServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//......dispatcher.forward(request, response);}
}// 处理数据插入的 Servlet
@WebServlet("/insertUserServlet")
public class InsertUserServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 实际应用中这里会有数据库插入代码System.out.println("用户 " + username + " 已成功插入数据库");dispatcher.forward(request, response);}
}// 发送注册成功邮件的 Servlet
@WebServlet("/sendEmailServlet")
public class SendEmailServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 模拟发送邮件操作System.out.println("已向用户 " + username + " 发送注册成功邮件");response.getWriter().write("注册成功");}
}
在这个示例中,从 RegisterFormServlet
开始,依次转发到 insertUserServlet
和 sendEmailServlet
进行处理,最后只是返回了一个简单的文本信息 “注册成功”,前端页面在视觉上不会有明显变化,除非页面上有 JavaScript 代码监听服务器响应并进行相应的页面更新。