Servlet的继承结构
Servlet
接口:
// 顶级的Servlet接口
public interface Servlet {
// 初始化方法,构造完毕后,tomcat自动调用完成初始化功能的方法
void init(ServletConfig var1) throws ServletException;
// 获取ServletConfig对象的方法
ServletConfig getServletConfig();
// 接收用户请求,向用户响应信息的方法
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
// 返回Servlet字符串形式描述信息的方法
String getServletInfo();
// Servlet在回收前,tomcat调用的销毁方法,往往用于做资源的释放工作
void destroy();
}
Servlet
接口中的每个抽象方法都是用于定义Servlet生命周期中的特定操作。下面是详细解释:
1. init(ServletConfig var1)
:
- 作用:这个方法是用于初始化Servlet的。当Servlet被第一次加载时,Servlet容器(例如Tomcat)会调用这个方法。它相当于Servlet的“构造器”,让你能够执行一些初始化操作,比如打开数据库连接、读取配置文件等。
- 参数:
ServletConfig var1
,这是一个接口,提供了Servlet的配置信息,比如初始化参数、上下文等。 - 为什么抽象:不同的Servlet在初始化时可能需要不同的逻辑。例如,有些Servlet可能需要初始化数据库连接,而有些则可能需要加载配置文件。实现类需要根据具体需求编写初始化代码。
- 具体场景:你可以在实现类中定义这个方法,用于初始化资源,如数据库连接池、缓存等。
2. getServletConfig()
:
- 作用:返回
ServletConfig
对象,该对象包含了Servlet的配置信息,包括Servlet的初始化参数和Servlet上下文。通过这个方法,Servlet能够获取到在web.xml
中定义的初始化参数。 - 为什么抽象:每个Servlet都有可能需要访问自己特定的配置。具体的实现类根据配置的不同,可以定义如何返回这些配置信息。
- 具体场景:例如,如果你有一些在
web.xml
中定义的初始化参数(如数据库连接URL、用户名、密码等),你可以通过此方法来获取这些参数。
3. service(ServletRequest var1, ServletResponse var2)
:
- 作用:这是Servlet最重要的方法,用来处理客户端请求并生成响应。每当客户端发送请求时,Servlet容器会调用
service()
方法来处理请求。它可以处理HTTP GET、POST等不同类型的请求。 - 参数:
ServletRequest var1
:包含了来自客户端的请求数据(如请求参数、请求头、客户端信息等)。ServletResponse var2
:用于向客户端发送响应数据(如响应内容、响应头等)。
- 为什么抽象:不同的Servlet会处理不同类型的请求。例如,一个Servlet可能处理用户登录请求,另一个Servlet则可能处理文件上传。实现类需要根据不同的业务逻辑来编写处理请求的代码。
- 具体场景:假设你有一个登录Servlet,它会在
service()
方法中检查用户的用户名和密码是否正确,并生成相应的响应(成功或失败消息)。
4. getServletInfo()
:
- 作用:这个方法用于返回关于Servlet的一些描述信息,通常是字符串形式。这个方法通常在管理和调试时用到,可以帮助管理员或开发者获取Servlet的相关信息(如版本、作者等)。
- 为什么抽象:每个Servlet的描述信息会有所不同,具体的实现类可以提供相应的描述信息。例如,可以返回Servlet的版本、用途、作者等信息。
- 具体场景:你可以在实现类中定义该方法,返回类似于“这个Servlet用于处理用户登录请求,版本为1.0,开发者是John Doe”之类的信息。
5. destroy()
:
- 作用:当Servlet生命周期结束时,Servlet容器会调用
destroy()
方法。这是一个清理工作的方法,用于释放Servlet占用的资源,比如关闭数据库连接、释放文件句柄等。它在Servlet即将被卸载或容器即将关闭时被调用。 - 为什么抽象:不同的Servlet在销毁时可能有不同的清理逻辑。实现类可以根据自己使用的资源,编写特定的释放资源逻辑。
- 具体场景:如果你的Servlet在运行时创建了数据库连接或打开了文件,那么你应该在
destroy()
方法中关闭这些资源,避免资源泄露。
GenericServlet
类:
GenericServlet
是一个抽象类,它实现了Servlet
接口,简化了Servlet的实现流程,常用于为不同协议(如HTTP、FTP等)的具体Servlet提供基础功能。以下是各部分的详细解释:
1. 字段声明
private transient ServletConfig config;
config
是用来存储ServletConfig
对象的,该对象包含Servlet的初始化参数和上下文。这里使用了transient
关键字,表示在序列化时,这个字段不会被序列化。
2. destroy()
方法
public void destroy() {
// 该抽象方法为空,在子类中可以覆盖实现具体的销毁代码
}
- 这是
Servlet
接口的destroy()
方法的实现。GenericServlet
类并没有提供具体的销毁逻辑,而是将其留给子类去实现。子类可以在该方法中进行资源释放或清理工作。
3. init(ServletConfig config)
方法
public void init(ServletConfig config) throws ServletException {
this.config = config; // 保存配置对象到当前的实例变量
this.init(); // 调用重载的无参init方法
}
- 当Servlet容器(如Tomcat)调用
init(ServletConfig config)
方法时,会传入ServletConfig
对象。这个方法的作用是:- 保存传入的
ServletConfig
对象 到类的config
字段中,以便稍后使用。 - 然后调用了无参的
init()
方法,这样子类可以只重写无参的init()
方法,而不用关心ServletConfig
的传递。
- 保存传入的
4. init()
方法
public void init() throws ServletException {
// 该方法为空,我们可以覆盖此方法来初始化具体的内容
}
- 这是
init()
方法的无参重载版本。在init(ServletConfig config)
方法中会调用这个无参的init()
,子类可以选择只重写这个无参的init()
来完成特定的初始化操作,而不必处理ServletConfig
对象。
5. getServletConfig()
方法
public ServletConfig getServletConfig() {
return this.config;
}
- 该方法返回
ServletConfig
对象,供子类在需要时获取Servlet的配置信息。通常情况下,这个配置对象包括Servlet的初始化参数等信息。
HttpServlet:
1. 继承关系
HttpServlet
继承了 GenericServlet
类,并且实现了 Servlet
接口,提供了用于处理 HTTP 请求的方法。与 GenericServlet
类相比,HttpServlet
增加了专门处理 HTTP 请求的方法,比如处理 GET
和 POST
请求。
public class HttpServlet extends GenericServlet {
// 处理 HTTP 请求的核心方法
}
2. HTTP 请求方法的处理
HttpServlet
提供了对常见 HTTP 请求方法(如 GET
、POST
、PUT
、DELETE
)的处理。常用的方法有:
1. doGet(HttpServletRequest req, HttpServletResponse resp)
- 处理来自客户端的
GET
请求。浏览器在输入 URL 后默认会发送GET
请求,例如请求页面、资源等。 - 这个方法一般用来读取数据而非修改数据
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<h1>Hello, World!</h1>"); }
2. doPost(HttpServletRequest req, HttpServletResponse resp)
- 处理来自客户端的
POST
请求,通常用于提交数据(例如表单提交)。 - 这个方法一般用来处理服务器端的资源更新或创建。
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); // 处理用户输入的数据 }
3. doPut(HttpServletRequest req, HttpServletResponse resp)
- 处理
PUT
请求,通常用于更新资源。
4. doDelete(HttpServletRequest req, HttpServletResponse resp)
- 处理
DELETE
请求,通常用于删除服务器上的资源。
HttpServlet
抽象类对 service()
方法的处理方式:
public abstract class HttpServlet extends GenericServlet {
// 参数的父转子 调用重载service方法
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// 参数的父转子
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 调用重载的service
this.service(request, response);
}
}
HttpServlet
类中重载的service方法:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的方法
String method = req.getMethod(); // GET, POST, PUT, DELETE, OPTIONS, ...
if (method.equals("GET")) {
this.doGet(req, resp);
} else if (method.equals("HEAD")) {
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = LStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg); // 返回HTTP状态码501:未实现
}
}
HttpServletRequest
和 HttpServletResponse
HttpServletRequest
和HttpServletResponse
是 HTTP 请求和响应的两个关键对象,提供了操作 HTTP 请求和生成响应的接口。
HttpServletRequest
:
- 用于获取请求的信息,包括请求参数、请求头、会话、Cookie 等。
HttpServletResponse
:
- 用于生成和发送响应,包括响应内容、响应头、Cookie 等。
这个 service()
方法是 HttpServlet
类的核心,它通过 if-else
结构来处理不同的 HTTP 请求类型。每种 HTTP 方法都有相应的处理函数(如 doGet()
、doPost()
等),开发者可以通过重写这些方法来实现具体的请求处理逻辑。对于未实现的 HTTP 方法,返回状态码 501
,通知客户端请求未被实现。
service()
方法的工作原理
HttpServlet
类重写了GenericServlet
的service()
方法。这个方法会根据 HTTP 请求的类型自动调用相应的处理方法(如doGet()
、doPost()
等)。- 一般情况下,不建议直接重写
service()
方法,而是通过重写doGet()
、doPost()
等方法来处理不同的请求。
自定义的Servlet方法
// 自定义Servlet
class Servlet1 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 接收用户请求信息
// 做出响应
}
}
详细解释:
-
Servlet1
类:- 这个类是一个自定义的
Servlet
,继承自HttpServlet
。 HttpServlet
是处理 HTTP 请求的基类,通常通过重写它的doGet()
、doPost()
或service()
方法来实现请求处理。
- 这个类是一个自定义的
-
service(HttpServletRequest req, HttpServletResponse resp)
方法:- 这个方法重写了
HttpServlet
中的service()
方法,用来处理所有的 HTTP 请求。它会接收两个参数:HttpServletRequest req
:封装了来自客户端的请求信息。HttpServletResponse resp
:用于向客户端发送响应信息。
- 在这个方法中,你可以从请求中获取参数、头信息等,并通过响应发送回数据。
- 这个方法重写了