认识
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-start