Servlet、Filter 生命周期
Servlet作为JavaEE必须掌握的内容,Struts2通过使用Filter的功能实现了一个MVC的框架。因此掌握这Servlet以及Filter的生命周期显得非常重要。
1. Servlet的生命周期
虽然通过使用IDE工具快速创建了Servlet,但是很多人没有弄明白这个东西到底是怎么什么时候实例化或者销毁的,丢开一阵子后很快就忘记服务器在后台到底做了什么。因此了解Servlet的生命周期非常必要。
Servlet是JavaEE标准下的一个接口,该接口抽象出了以下几个方法:
| 返回值 | 方法名称 | 作用 |
void |
init(ServletConfig config) |
初始化Servlet类实例 |
ServletConfig |
getServletConfig() |
获取含有初始化参数的Servlet配置文件 |
void |
service(ServletRequest req, ServletResponse res) |
调用Servlet的实例方法 |
void |
getServletInfo() |
获取Servlet的信息,包含版本、作者、版权等 |
void |
destroy() |
销毁Servlet类型内容 |
HttpServlet类基本实现了大部分Servlet接口的内容,目前使用IDE创建一个Servlet基本都是集成HttpServlet进行实现的。
回到Servlet生命周期。当用户发出了一个请求,tomcat这类服务器中间件是如何实例化用户编写的Servlet呢?这要从配置文件说起。
① 当用户在浏览器内输入请求,服务器中间件会根据web.xml去查找需要实例化的Servlet。如下:
<servlet>
<!-- ②根据servletName找到对应的Servlet,这个名称必须和mapping里面的名称一样 -->
<servlet-name>RequestServlet</servlet-name>
<!-- ③找到代码中需要实例化的具体对象位置,实例化对象 -->
<servlet-class>com.scl.controler.RequestServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>RequestServlet</servlet-name>
<!--①中间件匹配url内的链接 -->
<url-pattern>/requestmap</url-pattern>
</servlet-mapping>
Servlet 配置
中间件通过反射查找到对应的类,进行实例化。
② 调用对应servlet类内的init方法。只运行一次init方法
③ 分析请求,servlet实例调用service方法。HttpServlet类把这个方法分成get和post两种请求方式处理相关逻辑。
④ 当服务器中间件被关闭或者web.xml被修改时,服务器中间件会调用servlet实例的destroy方法,对Servlet进行销毁。
package com.scl.controler; import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class RequestServlet extends HttpServlet
{
private static final long serialVersionUID = 1L; @Override
public void init() throws ServletException
{
System.out.println("servlet init!");
} @Override
public void destroy()
{
System.out.println("servlet destory!");
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
System.out.println("do servlet method");
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
} }
RequestServlet 示例代码
在浏览器访问http://localhost:8081/FilterProject/requestmap会得到如下结果
servlet init!
do servlet method
实例代码结果
当关闭服务器中间件时会调用destroy方法,init方法只会调用一次。
2. Filter的生命周期
掌握Servlet以后,再接触基础的Filter类,会发现。这两块内容在web.xml里面的配置基本是一样的!先来看下Filter接口抽象了哪几个方法。
| 返回值 | 方法名称 | 作用 |
void |
init(FilterConfig filterConfig) |
初始化Filter实例 |
void |
doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
调用Filter过滤内容 |
void |
destroy() |
销毁Filter实例 |
Filter 实例在启动web容器的时候就开始进行初始化,而Servlet实例则是在用户通过浏览器访问程序的时候调用。
① 当web容器(服务器中间件)启动的时候,建立Filter实例,初始化Filter接口。
② 当用户通过浏览器访问站点,Filter过滤用户请求
③ 进行Servlet服务处理
④ 当web容器退出时,servlet实例先销毁,再销毁filter实例
Filter配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <filter>
<!-- ② -->
<filter-name>MyFilter</filter-name>
<!-- ③ -->
<filter-class>com.scl.filter.MyFilter</filter-class>
</filter> <filter>
<filter-name>MyFilter2</filter-name>
<filter-class>com.scl.filter.MyFilter2</filter-class>
</filter>
<!-- 多个Filter,按照mapping里面的配置顺序进行过滤操作 -->
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MyFilter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<!-- ②根据servletName找到对应的Servlet,这个名称必须和mapping里面的名称一样 -->
<servlet-name>RequestServlet</servlet-name>
<!-- ③找到代码中需要实例化的具体对象位置,实例化对象 -->
<servlet-class>com.scl.controler.RequestServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>RequestServlet</servlet-name>
<!--①中间件匹配url内的链接 -->
<url-pattern>/requestmap</url-pattern>
</servlet-mapping> <welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Filter 配置
Filter 的使用必须通过类去实现Filter接口
package com.scl.filter; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class MyFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
System.out.println("myFilter init!");
} @Override
public void destroy()
{
System.out.println("myFilter destroy!");
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
System.out.println("filter start");
chain.doFilter(request, response);
System.out.println("filter end");
} }
MyFilter 代码
package com.scl.filter; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class MyFilter2 implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
System.out.println("myFilter2 init!");
} @Override
public void destroy()
{
System.out.println("myFilter2 destroy!");
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
System.out.println("filter2 start");
chain.doFilter(request, response);
System.out.println("filter2 end");
} }
MyFilter2 代码
访问http://localhost:8080/FilterProject/requestmap 会有以下结果
servlet init!
filter start
filter2 start
do servlet method
filter2 end
filter end
含Filter的servlet运行结果
其中,在web容器运行的时候Filter就已经初始化了,并在控制台输出:
myFilter2 init!
myFilter init!
两个不同的Filter在运行的时候,按照filter-mapping中的顺序先后进行过滤。
关于url-mapping节点内容,有以下解析:
假设当前工程目录为:testmapping。
1 、url的精确匹配。
无论使用什么路径访问站点查找Servlet都是先以精确匹配开始。有 MapServlet 的url-pattern 设置为:/map,同时也有ServletB的url-pattern 设置为/* ; 假设用户输入http://localhost:8081/testmapping/map; 容器会找到MapServlet,并且只匹配MapServlet ,ServletB被放弃。(Filter 不一样,Filter是一个链式过滤,按照filter-mapping的顺序,都匹配上)。servlet会一层一层地查找,
2 、后缀名匹配。
url最后一段包含扩展,容器将会根据扩展选择合适的servlet。如 MapServlet 的url-pattern 设置为:"*.action";则访问http://localhost:8081/testmapping/a/a.action时,会匹配上。注意尽量不要直接使用".action"来指定,这样会报错。
3 、默认servlet。
当前两种方式没法匹配上的时候,如果是静态资源或者JSP文件,则走容器内部的default-servlet匹配。
以上为Servlet及Filter的生命周期总结,如有问题烦请指出纠正。
Servlet、Filter 生命周期的更多相关文章
- Servlet和Filter生命周期
1. 生命周期 1.1. Servlet生命周期 servlet是一个基于java技术的WEB组件,运行在服务器端,我们利用 sevlet可以很轻松的扩展WEB服务器的功能,使它满足特定的应用需要.s ...
- Servlet生命周期 、Filter生命周期、Listering(监听器)总结
Servlet生命周期简述 (1)加载和实例化 当Servlet容器启动或客户端发送一个请求时,Servlet容器会查找内存中是否存在该Servlet实例,若存在,则直接读取该实例响应请求:如果不存在 ...
- JSP Servlet WEB生命周期
[转载] JavaWeb的生命周期是由Servlet容器来控制的总的来说分为三个阶段1.启动阶段:加载web应用相关数据,创建ServletContext对象,对Filter和servlet进行初始化 ...
- servlet的生命周期与运行时的线程模型
第 14 章 生命周期 注意 讲一下servlet的生命周期与运行时的线程模型,对了解servlet的运行原理有所帮助,这样才能避免一些有冲突的设计. 如果你不满足以下任一条件,请继续阅读,否则请跳过 ...
- Servlet/JSP-01 Servlet及其生命周期
一.起步 1.新建一个类继承Servlet接口 public class HelloServlet implements Servlet { @Override public void destroy ...
- Servlet学习(一)——Servlet的生命周期、执行过程、配置
1.什么是Servlet Servlet 运行在服务端的Java小程序,是sun公司提供一套规范(接口),用来处理客户端请求.响应给浏览器的动态资源.但servlet的实质就是java代码,通过jav ...
- Servlet的生命周期及工作原理
Servlet生命周期分为三个阶段: 1,初始化阶段 调用init()方法 2,响应客户请求阶段 调用service()方法 3,终止阶段 调用destroy()方法 Servlet初始化阶段: 在 ...
- Servlet的生命周期
Servlet的生命周期 Servlet的生命周期是由tomcat服务器来控制的. 1 构造方法: 创建servlet对象的时候调用.默认情况下,第一访问servlet就会创建servlet对象只创建 ...
- Servlet的生命周期+实现方式
1.Servlet的生命周期: (1)被创建: 默认情况下,Servlet第一次被访问时,被服务器创建.会调用init()方法. 一个 ...
随机推荐
- Android Bundle传递简单数据、对象数据
Android开发过程中进程遇到组件之间.进程之间等数据的传递,数据传递有非常多种,当中使用Bundle传递非常方便. Bundle能够传递多种数据,是一种类似map的key-value数据结构 简单 ...
- JavaScript提高:003:easy UI实现tab页面自适应问题
前面说到使用easyUI在asp.net中实现了tab控件效果.http://blog.csdn.net/yysyangyangyangshan/article/details/38307477只是有 ...
- inline(内联元素)和block(块级元素) 的区别
块级元素,默认是独自占据一行的.比如是<p>.<h1>.<h2>.<h3>.<h4>.<h5>.<h6>.<u ...
- UNIX基础知识之信号
本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 信号(signal)是通知进程已发生某种情况的 ...
- 图片onerror(转)
<script type="text/javascript"> <!– function nofind(){ var img=event.srcElement; ...
- php中序列化与反序列化在utf8和gbk编码中测试
在php中如果我们统一编码是没有什么问题了,但是很多朋友会发现一个问题就是utf8和gbk编码中返回的值会有所区别: php 在utf8和gbk编码下使用serialize和unserialize互相 ...
- 如何判断一个数是否为素数(zt)
怎么判断一个数是否为素数? 笨蛋的作法: bool IsPrime(unsigned n){ if (n<2) { //小于2的数即不是合数也不是素数 throw 0; ...
- Spreadsheet Tracking
Spreadsheet Tracking Data in spreadsheets are stored in cells, which are organized in rows (r) and ...
- 最短路径之Dijkstra算法及实例分析
Dijkstra算法迪科斯彻算法 Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图.首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径.它的初始 ...
- [转]让ORACLE LIKE 时不区分大小写
本文转自:http://hi.baidu.com/dosttyy/item/9073803df47ef9f62784f49a 让ORACLE LIKE 时不区分大小写: select * from t ...