i3geek.com
闫庚哲的个人博客

servlet,filter, listener的区别与联系

Servlet

servlet 流程是短的,url传来之后,就对其进行处理,之后返回或转向到某一自己指定的页面。详细看Servlet的学习>>

职责

  • 创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
  • 创建可嵌入到现有的html页面中的一部分html页面(html片段);
  • 读取客户端发来的隐藏数据;
  • 读取客户端发来的显示数据;
  • 与其他服务器资源(包括数据库和java的应用程序)进行通信;
  • 通过状态代码和响应头向客户端发送隐藏数据。

生命周期

生命周期分为三个阶段:初始化阶段(调用init方法)、响应客户请求阶段(调用service方法)、终止阶段(调用destroy方法)。

在下列时刻Servlet容器装载Servlet:

  • Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码:
    <loadon-startup>1</loadon-startup>
  • 在Servlet容器启动后,客户首次向Servlet发送请求
  • Servlet类文件被更新后,重新装载Servlet

Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init方法进行初始化。在Servlet的整个生命周期内,init()方法只被调用一次。

使用

1. 在web.xml中配置Servlet

<servlet>
<servlet-name>AutoServlet</servlet-name>
<servlet-class>
com.servlet.AutoServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AutoServlet</servlet-name>
<url-pattern>/AutoServlet</url-pattern>
</servlet-mapping>

2. 定义AutoServlet类,继承HttpServlet,实现方法doGet, doPost

Filter

filter流程是线性的,它就像是像一个职责链,url传来之后,进行预处理,然后传递给下一个filter继续执行,而servlet 处理之后,不会继续向下传递。其生命周期:init()->doFilter()->destroy()

过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等。其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一设置编码,简化操作;同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。

职责

  • filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应:
  • 在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;
  • 根据程序需要修改请求和响应;
  • 在servlet被调用之后截获servlet的执行

使用

1. web.xml配置

<filter>
<filter-name>checkUrl</filter-name>
<filter-class>com.lvjian.filter.CheckUrl</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>asong</param-value> 
//初始化传参,得到时在filter的init方法中用filterConfig.getInitParameter( "name" )
</init-param>
</filter>
<filter-mapping>
<filter-name>checkUrl</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

2. 继承 javax.servlet.Filter,实现 doFilter(HttpServletRequest request, HttpServletResponse response ,FilterChain filterChain) 等方法

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
//获取用户请求的URI
String request_uri = request.getRequestURI();
//获取web应用程序的上下文路径
String contextPath = request.getContextPath();
//去除上下文路径,得到剩余部分的路径
String uri = request_uri.substring(contextPath.length());
//创建会话session
HttpSession session = request.getSession(true);

//保持原有流程不变
filterChain.doFilter( servletRequest , servletResponse );

示例

   1: MyCharsetFilter.java 编码过滤器
   2: package ...;
   3: import ...;
   4:  
   5: // 主要目的:过滤字符编码;其次,做一些应用逻辑判断等.
   6: // Filter跟web应用一起启动
   7: // 当web应用重新启动或销毁时,Filter也被销毁
   8: public class MyCharsetFilter implements Filter {
   9:     private FilterConfig config = null;
  10:     
  11:     public void destroy() {
  12:         System.out.println("MyCharsetFilter准备销毁...");
  13:     }
  14:  
  15:     public void doFilter(ServletRequest arg0, ServletResponse arg1,
  16:             FilterChain chain) throws IOException, ServletException {
  17:         // 强制类型转换
  18:         HttpServletRequest request = (HttpServletRequest)arg0;
  19:         HttpServletResponse response = (HttpServletResponse)arg1;
  20:         // 获取web.xm设置的编码集,设置到Request、Response中
  21:         request.setCharacterEncoding(config.getInitParameter("charset"));
  22:         response.setContentType(config.getInitParameter("contentType"));
  23:         response.setCharacterEncoding(config.getInitParameter("charset"));
  24:         
  25:         // 将请求转发到目的地
  26:         chain.doFilter(request, response);
  27:     }
  28:  
  29:     public void init(FilterConfig arg0) throws ServletException {
  30:         this.config = arg0;
  31:         System.out.println("MyCharsetFilter初始化...");
  32:     }
  33: }

以下是 MyCharsetFilter.java 在web.xml 中配置:

   1: <filter>
   2:       <filter-name>filter</filter-name>
   3:       <filter-class>dc.gz.filters.MyCharsetFilter</filter-class>
   4:       <init-param>
   5:           <param-name>charset</param-name>
   6:           <param-value>UTF-8</param-value>
   7:       </init-param>
   8:       <init-param>
   9:           <param-name>contentType</param-name>
  10:           <param-value>text/html;charset=UTF-8</param-value>
  11:       </init-param>
  12:   </filter>
  13:   <filter-mapping>
  14:       <filter-name>filter</filter-name>
  15:       <!-- * 代表截获所有的请求  或指定请求/test.do  /xxx.do -->
  16:       <url-pattern>/*</url-pattern>
  17:   </filter-mapping>

所有的奥秘就在Filter中的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的 doFilter()方法。比如执行顺序:执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的 chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的 chain.doFilter()之后的代码,最后返回响应。

过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前,这样才能确保在使用请求中的数据前设置正确的编码。

Listener

如果说servlet和filter是查找url进行操作,则listener就是监听对象的动作进行触发操作,有点类似于我们数据库中的触发器。如在session的创建或更改时做一些事情。

监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。主要作用是: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。

职责

servlet2.4规范中提供了8个listener接口,可以将其分为三类,分别如下:

  • 第一类:与servletContext有关的listner接口。包括:ServletContextListener、ServletContextAttributeListener
  • 第二类:与HttpSession有关的Listner接口。包括:HttpSessionListner、HttpSessionAttributeListener、HttpSessionBindingListener、HttpSessionActivationListener;
  • 第三类:与ServletRequest有关的Listener接口,包括:ServletRequestListner、ServletRequestAttributeListener

使用

1. 在web.xml中配置

<listener>
<listener-class>demo.listener.MyContextLoader</listener-class>
</listener>
//这样服务器就会在启动时创建MyContextLoader的一个实例,并开始监听servlet,session的操作

2. 实现,常用的listener有:

(1) ServletContextListener 监听ServletContext。
当创建ServletContext时,激发 contextInitialized(ServletContextEvent sce)方法;
当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。

(2)ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。

(3)HttpSessionListener 监听HttpSession的操作。
当创建一个Session时,激发 session Created(HttpSessionEvent se)方法;
当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。

(4)HttpSessionAttributeListener 监听HttpSession中的属性的操作。
当在Session增加一个属性时,激发 attributeAdded(HttpSessionBindingEvent se) 方法;
当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEventse)方法;
当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

示例

   1: MyServletContextListener.java
   2: package dc.gz.listeners;
   3: import javax.servlet.ServletContext;
   4: import javax.servlet.ServletContextEvent;
   5: import javax.servlet.ServletContextListener;
   6: import org.apache.commons.dbcp.BasicDataSource;
   7:  
   8: /**
   9:  * Web应用监听器
  10:  */
  11: public class MyServletContextListener implements ServletContextListener {
  12:  
  13:     // 应用监听器的销毁方法
  14:     public void contextDestroyed(ServletContextEvent event) {
  15:         ServletContext sc = event.getServletContext();
  16:         // 在整个web应用销毁之前调用,将所有应用空间所设置的内容清空
  17:         sc.removeAttribute("dataSource");
  18:         System.out.println("销毁工作完成...");
  19:     }
  20:  
  21:     // 应用监听器的初始化方法
  22:     public void contextInitialized(ServletContextEvent event) {
  23:         // 通过这个事件可以获取整个应用的空间
  24:         // 在整个web应用下面启动的时候做一些初始化的内容添加工作
  25:         ServletContext sc = event.getServletContext();
  26:         // 设置一些基本的内容;比如一些参数或者是一些固定的对象
  27:         // 创建DataSource对象,连接池技术 dbcp
  28:         BasicDataSource bds = new BasicDataSource();
  29:         bds.setDriverClassName("com.mysql.jdbc.Driver");
  30:         bds.setUrl("jdbc:mysql://localhost:3306/hibernate");
  31:         bds.setUsername("root");
  32:         bds.setPassword("root");
  33:         bds.setMaxActive(10);//最大连接数
  34:         bds.setMaxIdle(5);//最大管理数
  35:         //bds.setMaxWait(maxWait); 最大等待时间
  36:         // 把 DataSource 放入ServletContext空间中,
  37:         // 供整个web应用的使用(获取数据库连接)
  38:         sc.setAttribute("dataSource", bds);
  39:         System.out.println("应用监听器初始化工作完成...");
  40:         System.out.println("已经创建DataSource...");
  41:     }
  42: }

web.xml中配置如下,很简单:

   1: <!-- 配置应用监听器  -->
   2:   <listener>
   3:       <listener-class>dc.gz.listeners.MyServletContextListener</listener-class>
   4:   </listener>

这样配置好了之后,以后在web应用中就可以通过ServletContext取得BasicDataSource对象,从而获取与数据库的连接,提高性能,方便使用。

区别比较

作用对象


  • 针对url:
    servlet,filter都是针对url进行的操作,这点我们通过它们的配置就可以看到,这两个在配置时都需要配置url-pattern。
  • 针对对象:
    listener是针对对象的操作,它是在某个对象发生某些动作的时候执行,所以listener是提前封装好的对特定的对象的操作,只需要声明名称和类的位置即可。

作用范围


  • Servlet:
    servlet一般是针对特定的url进行操作的,所以它需要在jsp中指定servlet的地址才能跳转过去进行执行。
  • Filter:
    filter一般是针对所有的url进行操作的,它是对所有url的一个公共的操作,所以filter是基于容器的操作,比如字符集过滤器等。
  • Listener:
    listener的范围就是针对它所监听的对象的某个操作,但是在项目一启动就开始进行监听,直到那个动作发生才执行操作,有点类似于“守株待兔”。

总结

1、filter流程是线性的,它就像是像一个职责链,url传来之后,进行预处理,然后传递给下一个filter继续执行,而servlet 处理之后,不会继续向下传递。

2、Filter是过滤器主要用于对request的拦截设置,就像个漏斗 比如你一个服务器的数据提交过来,我先看看有没有我这个漏斗要过滤的,我先过滤下,然后在往后面传,这样保证数据的安全性。用于Request字符编码设置,权限控制等等。。

3、Listener是监听器主要负责监听WEB内部的动向,就像个放哨的,例如session监听,如果你个session一加进来,就会触发监听器.。或者用于在线人数的统计等等。。。

Servlet,Filter,Listener,Interceptor

赞(1)
未经允许不得转载:爱上极客 » servlet,filter, listener的区别与联系
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址