博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
详细理解servlet实现的几种方式和生命周期
阅读量:6849 次
发布时间:2019-06-26

本文共 4815 字,大约阅读时间需要 16 分钟。

现在很多的开发都是用的框架,然后很多同学学习的时候又是直接接触的框架,对于底层的一些开发,完全没有任何的了解。虽然对于业务上面来说,没有什么问题。但是很多时候当你被面试问到,或者是想要了解框架底层原理的时候,这就不得不知道了。所以今天详细说说它。

 

开发servlet的三种方式

1、实现servlet接口(偏向底层)

2、继承GenericServlet(觉得1不好用,就开发了这个,现在基本没啥用)

3、继承HttpServlet(现在大多数用这个)

 

理解实现servlet接口的方式,理解servlet生命周期

首先当servlet第一次被调用的时候,会调用servlet的init方法,把servlet实例装载到内存中。

之后会调用service方法,当第二次servlet被访问的时候就会直接调用service函数。

只有当web应用关闭,或者容器关闭,或者电脑关闭时候,才会调用destroy方法销毁servlet

 

下面是浏览器发出请求后servlet执行的流程图

 

Servlet接口有五个方法

init初始化,就是把servlet装载到内存中,只会被调用一次

getServletConfig获取servletConfig对象

service主要的服务方法,放业务逻辑,每次都会被调用

getServletInfo得到servlet配置信息

destroy销毁该servlet,从内存中清除掉

 

继承GenericServlet

GenericServlet实现了servlet接口

然后只有一个抽象方法需要你自己去重写

那就是service方法,所以相比来说init别的方法他都帮你实现好了,只要你写service方法就可以了。

至少看起来继承GenericServlet比直接实现servlet接口要方便

这个类是在javax.servlet.GenericServlet下的

 

 

继承HttpServlet

因为后来发现servlet主要是为了服务于http请求的,而且发现GenericServlet对于http来说还不够好

所以有了HttpServlet,首先它是继承自GenericServlet

然后它有很多http相关的方法,post,get,put等待

用户可以根据自己需要来实现这些方法

每个过来的请求都会调用service方法,最后service会根据不用的请求分发到不同的地方去做。

下面的问题中会在源码中详细说明。

 

 

下面有关servlet service描述错误的是?

1、不管是post还是get方法提交过来的连接,都会在service中处理

每次请求都会调用service方法,最终都会在service中处理,正确;

2、doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的

GenericServlet只是继承了Servlet的接口,实现了它其中的5个方法,其中需要用户重写的是service方法,而doGet/doPost是因为之后出现了HttpServlet才有的,是针对http请求才有了这个类,才有了doPost和doGet,所以是错误的。

3、service()是在javax.servlet.Servlet接口中定义的

Servlet接口一共定义了5个方法,其中就有service(),正确;

4、service判断请求类型,决定是调用doGet还是doPost方法

 

下面详细说说最后一个选项。

我们来看一看源码

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 = req.getDateHeader(HEADER_IFMODSINCE);        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);    }    }

这个就是HttpServlet中service方法的源码

首先我们看到的就是String method = req.getMethod();

这个就是通过request获取方法

然后根据方法判断调用哪一个方法

要说明的是前面它已经定义好了那些字符串

private static final String METHOD_DELETE = "DELETE";

   private static final String METHOD_HEAD = "HEAD";
   private static final String METHOD_GET = "GET";
   private static final String METHOD_OPTIONS = "OPTIONS";
   private static final String METHOD_POST = "POST";
   private static final String METHOD_PUT = "PUT";
   private static final String METHOD_TRACE = "TRACE";
所以第四个选项说:service判断请求类型,决定是调用doGet还是doPost方法,是正确的。

需要指出的是

前面说过

HttpServlet是继承自GenericServlet,而GenericServlet需要用户实现一个service,刚才我们看到的是它自己的

而在HttpServlet中其实是有的。它肯定要写这样一个方法的。

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);    }

源码是这样的,它会把原来的ServletRequest 请求直接强转换成HttpServletRequest然后再去调用它正真的service方法。

这点是需要指出的,HttpServletRequest比ServletRequest进行了进一步的封装,方法更适合http。

 

Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。
(1)加载:容器通过类加载器使用servlet类对应的文件加载servlet
(2)创建:通过调用servlet构造函数创建一个servlet对象
(3)初始化:调用init方法初始化
(4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求
(5)卸载:调用destroy方法让servlet自己释放其占用的资源

转载地址:http://mdrul.baihongyu.com/

你可能感兴趣的文章
paip.文件读写api php java python总结.txt
查看>>
C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 客户端多网络支持
查看>>
Effective C++ Item 18 Make interfaces easy to use correctly and hard to use incorrectly
查看>>
UTI iPhone支持依文件后缀名打开应用
查看>>
linux中ftp用户登录密码忘记了怎么修改
查看>>
3.8 spring - AbstractBeanDefinition 介绍
查看>>
struts2.1.6教程十、类型转换
查看>>
有关html5设计那些事,你真的考虑过前端的实现吗(最近别人经常问我这种问题,所以我就写一篇了,可能也有别人和我一样吐槽过)...
查看>>
MyISAM InnoDB 区别
查看>>
SQL Server基础之<存储过程>
查看>>
SASS的一些使用体会(安装-配置-开启firefox的调试)
查看>>
win7 精简板 安装ardunio uno r3驱动
查看>>
android 获取资源文件 r.drawable中的图片转换为drawable、bitmap
查看>>
转:LayoutInflater作用及使用
查看>>
HTML在Select具体的使用说明
查看>>
127使用 TableView 自带的单元格样式实现好友列表,另外在单元格中添加辅助按钮...
查看>>
机器学习(Machine Learning)&深度学习(Deep Learning)资料
查看>>
JQUERY AJAX无刷新异步上传文件
查看>>
Continue SQL query even on errors
查看>>
Leetcode_num13_Climbing Stairs
查看>>