理解HttpServlet抽象类没有抽象方法(从Servlet--GenericServlet--HttpServlet)

理解HttpServlet抽象类没有抽象方法

前两天复习了下Servlet,查看源码的时候发现了一个问题:HttpServlet已经实现了父类的所有抽象方法,为什么被定义成一个抽象类呢?想了好一阵。为了好理解我们就从Servlet–>GenericServlet–>HttpServlet一步步来看(顺便复习下Servlet)

1.Servlet
要新建一个servlet就要实现Servlet接口,我们来看Servlet接口里面的方法

在这里插入图片描述

①init(ServletConfig)当servlet类被加载时servlet容器会先调用servlet的空参构造器,然后调用init()方法并传入(ServletConfig(代表当前servlet的一些配置信息))
②getServletConfi()可以通过此方法获得ServletConfig
③ service(ServletRequest,ServletResponse)当有请求该servlet时,会调用该方法
④destroy 当卸载当前servlet容器时调用该方法销毁servlet
2.ServletConfi
可以看一下ServletConfig这个接口

在这里插入图片描述

①getServletName() 方法是可以返回当前servlet的名字(也就是web.xml文件中标签中中的值)
②getServletContext ()方法是返回ServletContext(当前web应用的上下文(每个web应用对应一个ServletContext,定义了servlet用来与servlet容器通信的多种方法))
③getInitParameter(string) 该方法可以根据名字来获取servlet的初始化参数
④getInitParameterNames ()该方法用来获取出初始化参数的参数名,注意返回类型为Enumeration 类型

每次要新建一个servlet都要实现Servlet接口(ServletConfig接口可不实现,因为ServletContext可以通过servletConfig.getServletContext()方法获得,前文提到ServletConfig接口是因为下面的GenericServlet要用到)重写这好几个方法是不是太麻烦好的,GenericServlet抽象类出现了

3.GenericServlet
该类实现了Servlet, ServletConfig接口并重写了方法,大家可自行查看源码,GenericServlet抽象类实现了上面讲到的两个接口的,所以很多方法不在赘述。我们来看其方法

在这里插入图片描述

①service(ServletRequest,ServletRespone) 该方法是servlet继承该抽象类后要实现的抽象方法,还是当请求该servlet时会调用该方法。、
比较有意思的是该类中有两个重载的init()方法:
②init(ServletConfig)该带参的init()方法是 GenericServlet 抽象类实现 servlet接口要实现的init方法,该方法会在servlet被加载时被servlet容器调用并传入ServletConfig
③ init()该空参的init() 方法是GenericServlet 抽象了自己新添加的init方法,目的是让继承该抽象类的servlet被加载并初始化时可以自己做些自定义的初始化。GenericServlet 中带参的init方法是这样写的:

@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}

看到这里感觉继承 GenericServlet 抽象类再写servlet,必直接实现Servelt接口容易多了吧,别急后边还有更易用的就是HttpServlet

4.HttpServlet
该抽象类继承了GenericServlet 抽象类,并且重写了GenericServlet 中唯一的抽象方法service(ServletRequest,ServletRespone)方法我们来看看HttpServlet的方法

在这里插入图片描述

新的改变

该抽象类诸多方法读者可参看源码,我们就说一说其中的连个重载方法,service(ServletRequest , ServletResponse)该方法是HttpServlet继承GenericServlet实现的抽象方法,一个是HttpServlet自己定义的 service(HttpServletRequest, HttpServletResponse)方法

#####① service(ServletRequest , ServletResponse) 该方法作用是,由于我们的请求都是http请求,所以把ServletRequest请求下转型为HttpServletRequest(ServletRequest子接口),ServletRespone请求下转型为HttpServletRespone(ServletRespone子接口),以获取更多关于请求的信息(如请求方式等),并调用自定义的service方法,源代码:
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {

    HttpServletRequest  request;
    HttpServletResponse response;

    try {
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
    } catch (ClassCastException e) {
        throw new ServletException("non-HTTP request or response");
    }
    service(request, response);
}
②service(HttpServletRequest, HttpServletResponse)自定义方法,根据请求的方式去调用不同的方法,源码如下:

protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

    String method = req.getMethod();

    if (method.equals(METHOD_GET)) {
        long lastModified = getLastModified(req);
        if (lastModified == -1) {
            // servlet doesn't support if-modified-since, no reason
            // to go through further expensive logic
            doGet(req, resp);
        } else {
            long ifModifiedSince;
            try {
                ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
            } catch (IllegalArgumentException iae) {
                // Invalid date header - proceed as if none was set
                ifModifiedSince = -1;
            }
            if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                // If the servlet mod time is later, call doGet()
                // Round down to the nearest second for a proper compare
                // A ifModifiedSince of -1 will always be less
                maybeSetLastModified(resp, lastModified);
                doGet(req, resp);
            } else {
                resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
        }

    } else if (method.equals(METHOD_HEAD)) {
        long lastModified = getLastModified(req);
        maybeSetLastModified(resp, lastModified);
        doHead(req, resp);

    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);

    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req,resp);

    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req,resp);

    } else {
        //
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1];
        errArgs[0] = method;
        errMsg = MessageFormat.format(errMsg, errArgs);

        resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    }
}
看到这里你会觉得这下更简单了吧,当我们再新建servlet的时候只需要继承HttpServlet让后根据请求方式重写对应的doXXX()方法就行了吧!确实是。

前边讲了这么一堆,就讲了如何从Servlet迭代到HttpServlet这个过程,以及每个类或接口里边的方法。还没有说重点,为什么HttpServlet没有抽象方法,却定义成抽象类。
个人理解了好久觉得是这样的:如果HttpServlet不是抽象类的话,你就可以产生Httpser对象,但是单纯的HttpServlet对象时不能处理任何业务逻辑的,里边方法没有功能;
所以要定义成抽象类,防止你创建对象。
但是继承了HttpServlet类创建servlet就方便多了,你要根据自己需要然后重写需要的方法,让后自定义逻辑,这样就方便多了。
总结:HttpServlet抽象类没有抽象方式是为了避免你自己创建一个没有业务功能的HttpServlet对象,但是给你一个提供了这样一个类方面你的servlet开发。(原创个人拙见,欢迎讨论)

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值