Tomcat学习笔记(一)——Servlet规范

虽然说一直都有在频繁使用Tomcat,但是对其背后的原理和整体结构设计没有深入研究。因此找了本关于Tomcat的书叫做《Tomcat内核设计剖析》,准备深入学习一下Tomcat。


想当初刚开始使用Tomcat的时候,对于Tomcat影响最深刻的就是Tomcat就是一个Servlet容器。那么什么是Servlet呢?想要回答这个问题,首先需要了解Servlet规范。Servlet规范描述了HTTP请求及响应处理过程相关的对象及其作用。该规范的核心接口就是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();
}

Servlet的生命周期主要包括加载实例化、初始化、处理请求、销毁。实例化一般由Web容器完成,初始化、处理请求、以及销毁分别对应上述Servlet接口的init、service以及destroy方法。在init方法中需要一个ServletConfig类型的参数,该参数为web.xml配置文件中配置的对应的初始化参数。查看一下ServletConfig接口,发现在里面定义了4个方法。

public interface ServletConfig {
	//获取对应的servlet名称,对应web.xml中<servlet-name>标签
    String getServletName(); 
    
	//获取Web.xml中定义的Context,对应<context-param>标签
    ServletContext getServletContext();	
    
	//获取给定初始化参数名称的值,对应<servlet>标签下<init-param>标签下的<param-value>标签中的值,
	//方法中需要的参数为<param-name>
    String getInitParameter(String var1);	
	
	//获取定义的初始化参数的名称的枚举,对应<init-param>
    Enumeration getInitParameterNames();	
}

为了方便开发人员的使用,Java在Java Servlet API中提供了两个抽象类分别是GenericServlet和HttpServlet。它们之间的继承和实现关系如下图所示。在不使用Spring之前,我们通常会自己定义一个继承HttpServlet的Servlet,并重写doGet和doPost方法来做业务逻辑处理。

在这里插入图片描述

在HttpServlet中定义了很多方法,例如doHead,doPost,doPut,doDelete等等方法用于处理客户端发起的对应的Http请求。HttpServlet中的service就是将不同的请求转发到各自对应的请求处理方法上。

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            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);
        }
    }

看到这里已经明白了当初学习tomcat时候,为什么需要实现一个继承于HttpServlet抽象类的servlet,并且重写doGet和doPost方法。但是还需要解决Servlet中方法中需要的两个参数,ServletRequest和ServletResponse.

ServletRequest接口


ServletRequest接口的实现封装了客户端请求的所有信息,如果使用HTTP协议则对应的请求对象类型是HttpServletRequest类。ServletRequest接口对象的作用域为Servlet的service方法或Filter的doFilter方法,除非启用了异步处理调用ServletRequest接口对象中的startAsync方法,此时request对象会一直有效知道调用AsyncContext的complete方法。


ServletResponse接口


ServletResponse接口的实现封装了服务器要返回客户端的所有信息。对应HTTP协议则为HttpServletResponse。


Filter接口


Filter接口允许Web容器对请求和响应做统一处理。例如,统一改变HTTP请求内容和响应内容,它可以作用于某个Servlet或一组Servlet。

public interface Filter {
    void init(FilterConfig var1) throws ServletException;

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    void destroy();
}

在一个 Web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个Filter链(FilterChain).
FilterChain对象中有一个doFilter()方法,执行该方法可以让当前Filter放行,让请求进入下一个Filter.
FilterChain的拦截过程如下图所示:
在这里插入图片描述
当浏览器访问 Web 服务器中的资源时,需要经过两个过滤器 Filter1 和 Filter2。首先 Filter1 会对这个请求进行拦截,在 Filter1 中处理完请求后,通过调用 Filter1 的 doFilter() 方法将请求传递给 Filter2,Filter2 处理用户请求后同样调用 doFilter() 方法,最终将请求发送给目标资源。当 Web 服务器对这个请求做出响应时,也会被过滤器拦截,但这个拦截顺序与之前相反,最终将响应结果发送给客户端浏览器。


RequestDispatcher -- ___ 请求分发器负责把请求转发给另外一个Servlet处理,或在响应中包含另外一个Servlet的输出。我们可以通过ServletContext的getRequestDispatcher方法和getNamedDispatcher方法分别以路径或Servlet名称作为参数获取对应Servlet的RequestDispatcher。 ```java public interface RequestDispatcher { //将当前请求转移到目标Servlet void forward(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; //将目标请求包含到当前Servlet void include(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值