Servlet详解

Servlet详解

Servlet全解(一篇就够)-CSDN博客

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

image-20260129141158870

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容器的职责

  1. 网络通信:监听端口,管理socket连接池
  2. 协议解析:解析HTTP请求,封装成对象
  3. 生命周期管理:Servlet的初始化、销毁
  4. 线程管理:为每个请求分配线程
  5. 会话管理:维护HttpSession
  6. 资源管理:处理静态资源,JSP编译等

一句话总结

Servlet容器把复杂的网络编程和HTTP协议解析封装起来,让开发者只需要关心业务逻辑,通过简单的API就能处理HTTP请求和响应。

这就是为什么你只需要写 doGet()doPost() 方法,就能轻松开发Web应用的原因!

posted @ 2026-02-14 14:27  deyang  阅读(3)  评论(0)    收藏  举报