Servlet中的过滤器(拦截器)Filter与监听器Listener的作用和区别

来源:互联网 发布:手机隐藏录像软件 编辑:程序博客网 时间:2024/04/30 04:23

Servlet中的过滤器(拦截器)Filter与监听器Listener的作用和区别

0、创建: 加载顺序  监听器-->过滤器-->Servlet.项目启动后,容器会首先创建声明的各种监听器,为后继的各个事件监听做准备,然后创建过滤器,最后是Servlet.销毁的时候是反序进行的
1、Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等。其

工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一设置编码,简化操作;同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。它是随你的web应用启动而启

动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新启动的时候才销毁,以下通过过滤编码的代码示例来了解

它的使用:    
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


public class LoginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // 获得在下面代码中要用的request,response,session对象
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;
        HttpSession session = servletRequest.getSession();


        // 获得用户请求的URI
        String path = servletRequest.getRequestURI();
        //System.out.println(path);
        
        // 从session里取员工工号信息
        String empId = (String) session.getAttribute("empId");
        /*创建类Constants.java,里面写的是无需过滤的页面
        for (int i = 0; i < Constants.NoFilter_Pages.length; i++) {
            if (path.indexOf(Constants.NoFilter_Pages[i]) > -1) {
                chain.doFilter(servletRequest, servletResponse);//让目标资源执行,放行
                return;
            }
        }*/
        
        // 登陆页面无需过滤
        if(path.indexOf("/login.jsp") > -1) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }

        // 判断如果没有取到员工信息,就跳转到登陆页面
        if (empId == null || "".equals(empId)) {
            // 跳转到登陆页面
            servletResponse.sendRedirect("/JingXing_OA/login.jsp");
        } else {
            // 已经登陆,继续此次请求
            chain.doFilter(request, response);
        }
    }
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

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

  <!-- 配置登陆过滤器 -->
    <filter>
        <filter-name>login</filter-name>
        <filter-class>com.jingxing.oa.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>login</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

     以上的例子简单的说明了Filter的使用,具体其他的应用可以看具体的场景。

Filter链

  在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
  web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

Filter的执行流程就是:执行第一个过滤器的chain.doFilter()之前的代码-->第二个过滤器的chain.doFilter()之前的代码-->……-->第n个过滤器的chain.doFilter()之前的代码-->所请求servlet的service()方法中的代码-->所请求servlet的doGet()或doPost()方法中的代码-->第n个过滤器的chain.doFilter()之后的代码-->……-->第二个过滤器的chain.doFilter()之后的代码-->第一个过滤器的chain.doFilter()之后的代码。


2、现在来说说Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启

动而启动,只初始化一次,随web应用的停止而销毁。主要作用是: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或

者是一些固定的对象等等。下面利用监听器对数据库连接池DataSource的初始化演示它的使用:    
   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对象,从而获取与数据库的连接,提高性能,方便使

用。

          上面通过两个示例演示了Filter和Listener的基本使用,对于其它的应用则需要我们在项目开发中根据具体的场景选择。

0 0
原创粉丝点击