Servlet与HttpServlet详解
一、Servlet概述
Servlet(Server Applet)是Java Servlet API中定义的一个接口,用于扩展Web服务器的功能。Servlet是一个运行在Web服务器或应用服务器上的Java程序,它可以动态地生成Web页面或其他类型的响应。
二、HttpServlet类
HttpServlet
类是Java Servlet API中的一个核心类,它继承自GenericServlet
类,实现了Servlet
接口,并为HTTP协议提供了特定的实现。HttpServlet
类的主要职责是处理HTTP请求和构建HTTP响应。
service(ServletRequest req, ServletResponse res)
这是Servlet接口中的核心方法,所有来自客户端的请求首先都会调用此方法。HttpServlet
为这个方法提供了默认实现,它会根据请求的类型(GET、POST等)调用对应的doXXX
方法。
doGet(HttpServletRequest request, HttpServletResponse response)
用于处理HTTP GET请求。
doPost(HttpServletRequest request, HttpServletResponse response)
用于处理HTTP POST请求。
doPut, doDelete, doOptions, doHead, doTrace 等
这些方法用于处理其他类型的HTTP请求,但在常见的Web应用中很少直接使用。
init(ServletConfig config)
Servlet的初始化方法,当Servlet实例被加载到内存并准备使用时,容器会调用此方法。
destroy()
Servlet的销毁方法,当Servlet实例不再需要并被容器卸载时,容器会调用此方法。
部署Servlet
HttpServlet
并覆盖相应的方法。web.xml
文件中配置Servlet的映射路径和初始化参数等信息。客户端请求
容器调度
调用service方法
service
方法,并传入HttpServletRequest
和HttpServletResponse
对象。HttpServletRequest
对象包含了请求的所有信息,如参数、头信息等。HttpServletResponse
对象用于构建并发送HTTP响应。处理请求
service
方法会调用相应的doXXX
方法。doXXX
方法中实现业务逻辑,如访问数据库、处理数据等。构建响应
HttpServletResponse
对象设置响应的状态码、响应头、响应体等。发送响应
HttpServletResponse
对象封装成HTTP响应,并通过网络发送给客户端。Servlet生命周期结束
destroy
方法,允许开发者进行资源清理工作。service
方法是Servlet容器(如Tomcat)用来调用特定HTTP方法处理程序的入口点。当客户端发送一个HTTP请求到Servlet容器时,容器会解析请求,确定它是哪种类型的HTTP方法(如GET、POST、PUT、DELETE等),然后调用相应的doXXX
方法。service
方法是一个重要的方法,它根据客户端发送的HTTP请求类型(如GET、POST等)调用相应的doXXX
方法。以下是HttpServlet
类中service
方法的实现:
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
// 将ServletRequest和ServletResponse强制转换为HttpServletRequest和HttpServletResponse
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("Cannot cast to HttpServletRequest/HttpServletResponse");
}
// 获取HTTP请求方法
String method = request.getMethod();
if (method.equalsIgnoreCase("GET")) {
// 如果是GET请求,调用doGet方法
long lastModified = getLastModified(request);
if (lastModified == -1) {
// 标记响应不被缓存
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
} else {
// 检查If-Modified-Since头以判断是否发送304 Not Modified响应
long ifModifiedSince = request.getDateHeader("If-Modified-Since");
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// 资源已修改,发送新内容
maybeSetLastModified(response, lastModified);
} else {
// 资源未修改,发送304 Not Modified响应
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
}
doGet(request, response);
} else if (method.equalsIgnoreCase("HEAD")) {
// 如果是HEAD请求,调用doHead方法
long lastModified = getLastModified(request);
maybeSetLastModified(response, lastModified);
doHead(request, response);
} else if (method.equalsIgnoreCase("POST")) {
// 如果是POST请求,调用doPost方法
doPost(request, response);
} else if (method.equalsIgnoreCase("PUT")) {
// 如果是PUT请求,调用doPut方法
doPut(request, response);
} else if (method.equalsIgnoreCase("DELETE")) {
// 如果是DELETE请求,调用doDelete方法
doDelete(request, response);
} else if (method.equalsIgnoreCase("OPTIONS")) {
// 如果是OPTIONS请求,调用doOptions方法
doOptions(request, response);
} else if (method.equalsIgnoreCase("TRACE")) {
// 如果是TRACE请求,调用doTrace方法
doTrace(request, response);
} else {
// 对于不支持的HTTP方法,抛出ServletException
throw new ServletException("HTTP method " + method + " is not supported");
}
}
这个service
方法首先检查传入的ServletRequest
和ServletResponse
是否可以安全地强制转换为HttpServletRequest
和HttpServletResponse
。接着,它获取HTTP请求的方法(如GET、POST等),并根据这个方法调用相应的doXXX
方法。如果请求方法是GET,它还会检查If-Modified-Since
头以判断是否发送304 Not Modified响应。
对于不支持的HTTP方法,service
方法会抛出一个ServletException
。通常,开发者会覆盖doGet
、doPost
等方法来提供具体的业务逻辑,而service
方法则负责调度这些方法。
三、示例代码
下面是一个简单的HttpServlet
示例,展示了如何处理GET请求:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
// 实际的逻辑是在这里
String message = "Hello, World!
";
// 将响应体写入到response对象中
response.getWriter().write(message);
}
}
在这个示例中,MyServlet
类继承了HttpServlet
类,并重写了doGet()
方法。当容器接收到一个GET请求时,它会调用doGet()
方法来处理请求。在doGet()
方法中,我们设置了响应的内容类型为HTML,并构建了一个简单的HTML消息作为响应体。