Servlet详解
目录
Servlet详解
Servlet 规范发展:
Servlet 2.5 (2005) → Servlet 3.0 (2009) → Servlet 3.1 (2013)
→ Servlet 4.0 (2017) → Jakarta Servlet 5.0 (2020)

Servlet生命周期
public class ServletDemo1 implements Servlet {
//Servlet对象倍实例化的时候init方法就会执行,而且只执行一次。(Servlet是单例)
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("ServletDemo1 实例化");
}
//Service方法:任何一次请求都会执行service方法,可以执行多次
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("ServletDemo1 执行");
}
//Servlet从服务器中移除或服务器关闭的时候销毁Servlet,只执行一次
@Override
public void destroy() {
System.out.println("ServletDemo1 销毁");
}
}
tomcat怎么去调用servlet的,怎么去传递request和response的。
解答:tomcat中:servlet引擎解析请求,看是不是第一次,是就执行初始化方法,并且根据web.xml的配置创建servletconfig对象,然后通过init方法传递到servlet里面去。不是第一次就调用service方法,并创建request对象和空的response对象,传递到servlet的service方法里。
socket实现和Tomcat实现
Tomcat - 如何设计一个简单的web容器 | Java 全栈知识体系
总结:关于servlet的真相就是,socket连接成功后,socket.getInputStream()封装到HttpRequest,socket.getOutputStream()到HttpResponse,然后传递给对应的servlet的service方法里面,这样就封装好了,servlet只需要关注业务。
Servlet的底层真相
// Tomcat/Nginx等Web服务器的处理流程
while (true) {
// 1. 接受socket连接
Socket socket = serverSocket.accept();
// 2. 获取输入输出流
InputStream input = socket.getInputStream();
OutputStream output = socket.getOutputStream();
// 3. 封装成HTTP对象(核心步骤!)
HttpServletRequest request = new HttpServletRequestImpl(input);
HttpServletResponse response = new HttpServletResponseImpl(output);
// 4. 找到对应的Servlet
Servlet servlet = findServletByUrl(request.getRequestURI());
// 5. 调用Servlet的service方法
servlet.service(request, response); // 这是关键!
// 6. 关闭连接
socket.close();
}
Servlet开发者视角
// 开发者只需要关心业务逻辑
public class MyServlet extends HttpServlet {
// 完全不用管socket、inputstream等底层细节
protected void doGet(HttpServletRequest request,
HttpServletResponse response) {
// 直接使用封装好的request获取参数
String username = request.getParameter("username");
// 直接使用response写响应
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>Hello " + username + "</h1>");
// 不需要手动关闭流,容器会处理
}
}
封装的核心思想
对请求的封装(HttpServletRequest)
- 原始数据:
socket.getInputStream()获取的字节流 - 封装后:提供
getParameter()、getHeader()、getSession()等方便的方法 - 实现方式:解析HTTP协议头,解析URL参数,解析Cookie等
对响应的封装(HttpServletResponse)
- 原始数据:
socket.getOutputStream()获取的字节流 - 封装后:提供
setContentType()、getWriter()、sendRedirect()等方法 - 实现方式:自动添加HTTP响应头,处理编码,管理缓冲等
Servlet规范的伟大之处
// 对比:没有Servlet框架的原始代码
public void handleRequest(Socket socket) {
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
// 手动解析HTTP请求
String line;
while ((line = in.readLine()) != null && !line.isEmpty()) {
// 解析请求行、请求头...
}
// 手动构造HTTP响应
out.println("HTTP/1.1 200 OK");
out.println("Content-Type: text/html");
out.println();
out.println("<html><body>...</body></html>");
in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Servlet容器的职责
- 网络通信:监听端口,管理socket连接池
- 协议解析:解析HTTP请求,封装成对象
- 生命周期管理:Servlet的初始化、销毁
- 线程管理:为每个请求分配线程
- 会话管理:维护HttpSession
- 资源管理:处理静态资源,JSP编译等
一句话总结
Servlet容器把复杂的网络编程和HTTP协议解析封装起来,让开发者只需要关心业务逻辑,通过简单的API就能处理HTTP请求和响应。
这就是为什么你只需要写 doGet() 和 doPost() 方法,就能轻松开发Web应用的原因!
浙公网安备 33010602011771号