千家信息网

如何理解Servlet及Servlet容器的概念以及使用注意点

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,如何理解Servlet及Servlet容器的概念以及使用注意点,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Servle
千家信息网最后更新 2026年11月04日如何理解Servlet及Servlet容器的概念以及使用注意点

如何理解Servlet及Servlet容器的概念以及使用注意点,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

Servlet

Servlet是一个服务器端编程的组件,主要能力产生动态的数据内容,和任何java组件一样,Servlet也是平台不相关的。 Servlet的运行依赖于一个容器 (或者叫servlet engine),容器在运行时会把Servlet字节码加载到虚拟机中生存一个servlet实例,并负责管理servlet实例的生命周期。

和servlet交互的对面可以是一个web浏览器,也可以是任何一个支持http协议的客户端程序,客户端和Servlet之间交互遵循request/response模式进行,实际上Servlet设计为并不仅仅局限于http协议,任何基于request/response的协议Servlet都支持。

Servlet容器

Servlet容器为servlet提供运行环境,servlet容器通常实现为一个Web服务器或者应用服务器的一部分。

Servlet容器的核心功能是接受请求、解码请求内容,然后把解析后请求内容分发到相关的某个Servlet,Servlet处理后,容器会把Servlet返回的数据内容进行编码并发送给客户端。这个过程中容器可以在把请求分发给servlet之前修改请求内容,也可以在把servlet的返回内容发送到客户端之前修改响应内容。

Servlet容器必须要提供http 1.0/1.1的支持,也可以支持https。

Servlet有完整的生命周期

一个servlet的生命周期阶段主要包括:加载并创建servlet实例、初始化servlet实例、处理请求以及销毁。

servlet的生命周期阶段完全由servlet容器来管理,从编程的角度看生命周期主要体现在Servlet接口中定义的三个方法:

  • init方法,让应用程序有机会执行初始化

  • service方法,应用程序处理请求并响应内容的地方

  • destroy方法,让应用程序有机会释放servlet持有的各种资源

任何一个servlet都必须直接或者间接实现这三个方法。 Servlet实例则由容器负责实例化,不需要应用程序参与,容器可以在启动完成后就开始加载servlet,也可以在第一次servlet被选中处理请求时才加载此servlet。

servlet容器完成servlet的实例化后就开始进行初始化,容器会调用 init 方法并传递一个 ServletConfig 对象的引用,通过ServletConfig引用可以在Servlet中感知到Servlet的一些详细配置参数和代表应用程序的ServletContext引用。一个servlet实例整个生命周期过程中init方法只会被容器调用一次。

只有初始化完成的servlet才能进一步提供请求服务,如果init方法中抛出ServletException异常或者没有在容器定义的时间内返回,则servlet容器认为初始化失败,此servlet不能提供服务。init方法抛出的可能是一个UnavailableException异常,这个异常暗示容器此servlet目前不可用:永久性不可用或者临时不可用,如果是临时性不可用则UnavailableException应该带上一个不可用预估时间秒数,这种情况下容器不会直接失败,而是会阻塞预估的时长然后重新创建一个servlet实例并再次执行初始化。

servlet成功初始化后就可以处理请求了,容器会调用service方法,并传递ServletRequest和ServletResponse两个引用,ServletRequest封装了客户端请求信息,用户应用程序的则负责填充ServletResponse对象,service方法返回后流程被容器接管。

service方法如果抛出ServletException异常代表失败,容器需要作出合适的下一步处理,sevlet规范定义如下过程:service方法如果抛出实际是一个UnavailableException异常则表示此servlet目前不可用,同样有永久性不可用和临时不可用两种情况,如果是永久性不可用,则容器会调用servlet的destroy方法清理然后释放此servlet,并给客户端响应SC_NOT_FOUND(404)状态;如果是临时性不可用,则servlet容器在预估的不可用时间内会直接拒绝所有的匹配到此servlet的请求而直接响应SC_SERVICE_UNAVAILABLE(503)状态,并响应一个 Retry-After header,容器也可以选择忽略这两种不可用的差别,直接当做是永久性不可用并清理释放servlet对象。

一个servlet实例正常情况下应该是永久驻留在容器中,直到关闭容器时才会销毁容器中的servlet实例。在清理一个servlet实例之前,容器总是会调用destroy方法,用户通常可以在destroy方法中做一些资源清理、持久化等工作,一旦一个servlet的destroy方法被调用后,容器就会完全释放它以便垃圾收集器回收。

用Servlet编程

通常我们要在应用程序中实现一个Servlet类的话,不需要直接实现Servlet接口,而是通过扩展GenericServlet,在http环境中的话就就可以扩展HttpServlet,GenericServlet对Servlet接口做了基本实现,只是预留了service方法需要用户实现, GenericServlet的实现没有绑定到任何具体的应用层协议,它是通用的。

在HTTP协议环境中,平台还提供了一个HttpServlet的实现类,HttpServlet就扩展自GenericServlet,HttpServlet完成实现了service方法,service方法中的实现方式是根据不同的http动词作了一些基本情况的判断处理,然后把正常情况下的过程委托到几个特定的http方法:doGet,doPost,doPut,...,绝大多数情况我们自己的Servlet实现类应该选择扩展HttpServlet,并且不应该直接重写service方法,而是应该重写doXXX方法。

public class RequestParameterServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        super.doGet(req, resp);        // …    }}

应该重写无参数init方法

Servlet接口中定义的init方法带有一个ServletConfig参数:

public void init(ServletConfig config) throws ServletException;

init方法在GenericServlet中做了一个基本实现:

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

在GenericServlet版本的init实现中,先把容器传递过来的ServletConfig引用保存下来,然后调用了一个无参数的init方法,这个无参数的int方法正是预留给用户实现的,因此,不管我们的Servlet类是扩展了GenericServlet,还是扩展了HttpServlet,如果有初始化的需求,那么我们应该重写GenericServlet中的无参数init方法。

多线程环境中的Servlet

通常情况下,容器只会为web descriptor中声明的每个servlet创建一个实例,这意味着在多线程情况下,其service方法是并发状态下运行,因此我们在实现service方法时要自己保证其线程安全性,通常的做法是不在Servlet实现类中使用共享字段,或者对service方法中的相关代码段加锁。

另一种方式是我们的Servlet类实现SingleThreadModel接口,SingleThreadModel是一个标识接口,servlet容器保证实现SingleThreadModel的servlet实例的service方法在同一时间只有一个线程访问,容器的做法可能是在servlet实例上加锁,容器也可能会为同一个Servlet类创建出多个实例并在容器中缓存它们,然后对每一个请求分发到其中一个空闲的servlet实例。但是并不推荐使用SingleThreadModel接口,因为SingleThreadModel方式并不能完全解决线程安全问题,例如session中的数据并不能保证线程安全,并且在servlet 2.4版本中已经废弃。

如何处理请求的字符编码

客户端的所有请求数据,包括请求路径,协议,请求头以及请求内容等这些数据全部都被容器封装在一个ServletRequest对象中,从ServletRequest对象中读取请求内容时必须要知道数据是如何编码的,否则就不可能正确解析请求数据。

由于目前大多数浏览器客户端在发送请求时都没有在Content-Type域中提供字符编码的标记,因此servlet规范中明确要求所有servlet容器在读取请求数据时应该默认使用"ISO-8859-1"来解析数据。如果客户端没有发送请求数据的编码格式,规范定义调用getCharacterEncoding方法应该返回null。

如果客户端没有发送请求内容的编码格式,并且如果容器设定的默认编码和实际的请求内容编码又不一致时,就会解析得到错误的数据,为了纠正这种情况ServletRequest另外供了一个setCharacterEncoding方法,编程人员可以调用此方法覆盖容器提供的编码格式来读取数据,此方法的调用一定要在读取任何请求内容之前,否则不会有效果。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

容器 方法 实例 内容 数据 客户 客户端 情况 编码 应用 程序 应用程序 接口 处理 参数 周期 生命 线程 对象 永久 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 有格互联网科技 互联网金融 科技金融 美国互联网科技 世界互联网领先科技成果 极限挑战互联网科技 上海喔噻互联网科技 唐信互联网科技 大连 互联网科技logo 万达互联网科技 受益于互联网科技的高速发展 知域互联网科技有限公司大骗子 乌苏新华互联网科技做什么的 洛阳共同富裕互联网科技有限公司 广州百诚互联网科技有限公司官网 浙南科技城互联网大厦招聘 西安有哪些互联网高科技企业 唯美互联网科技 互联网科技品牌 互联网领先科技成果宣传视频 互联网科技自媒体灵感 互联网科技有限公司 翻译 宁夏科技产业互联网案例 链环科技传统企业怎么转型互联网 银川新华互联网科技学校联系电话 畅思互联网科技 内蒙古九一互联网科技 中和天地互联网科技有限公司 上海科技产业互联网平台 江苏互联网科技小贷 全球科技与互联网公司市值变化
0