servlet中的filter/listener/interceptor区别与联系

原文:http://www.cnblogs.com/doit8791/p/4209442.html


1.filter 过滤器

filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等。
它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。

Filte用处。
  • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
  • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
  • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。
Filter种类。
  • 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
  • 日志Filter:详细记录某些特殊的用户请求。
  • 负责解码的Filter:包括对非标准编码的请求解码。
  • 能改变XML内容的XSLT Filter等。
  • Filter可负责拦截多个请求或响应;一个请求或响应也可被多个请求拦截。
创建一个Filter两个步骤:
  • 建Filter处理类;
  • web.xml文件中配置Filter。

下面先介绍一个简单的记录日志的Filter,这个Filter负责拦截所有的用户请求,并将请求的信息记录在日志中。

public class LogFilter implements Filter {  
    FilterConfig config;  

    public void destroy() {  
        this.config = null;  
    }  

    public void doFilter(ServletRequest req, ServletResponse res,  
            FilterChain chain) throws IOException, ServletException {  
        // 获取ServletContext 对象,用于记录日志  
        ServletContext context = this.config.getServletContext();  
        //long before = System.currentTimeMillis();  
        System.out.println("before the log filter!");  
        //context.log("开始过滤");  
        // 将请求转换成HttpServletRequest 请求  
        HttpServletRequest hreq = (HttpServletRequest) req;  
        // 记录日志  
        System.out.println("Log Filter已经截获到用户的请求的地址:"+hreq.getServletPath() );  
        //context.log("Filter已经截获到用户的请求的地址: " + hreq.getServletPath());  
        try {  
            // Filter 只是链式处理,请求依然转发到目的地址。  
            chain.doFilter(req, res);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        System.out.println("after the log filter!");  
        //long after = System.currentTimeMillis();  
        // 记录日志  
        //context.log("过滤结束");  
        // 再次记录日志  
        //context.log(" 请求被定位到" + ((HttpServletRequest) req).getRequestURI()  
        //      + "所花的时间为: " + (after - before));  
    }  

    public void init(FilterConfig config) throws ServletException {  
        System.out.println("begin do the log filter!");  
        this.config = config;  
    }  

 }  
<filter>
        <filter-name>logfilter</filter-name>
        <filter-class>com.mine.test.LogFilter</filter-class>
</filter>
<filter-mapping>
        <filter-name>logfilter</filter-name>
        <url-pattern>/*</url-pattern> <!--配置过滤的范围   后缀符合即过滤  此处为全部过滤-->
</filter-mapping>

在web.xml文件中配置该Filter,使用init-param元素为该Filter配置参数,init-param可接受如下两个子元素:

  1. param-name:指定参数名。
  2. param-value:指定参数值。

多个匹配的Filter,是按照其在web.xml中配置的顺序来执行的。

生命周期
  1. 启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;

  2. 每一次请求时都只调用方法doFilter()进行处理;

  3. 停止服务器时调用destroy()方法,销毁实例。


2.listener:监听器

通过listener可以监听web服务器中某一个执行动作,并根据其要求作出相应的响应。通俗的语言说就是在application,session,request三个对象创建消亡或者往其中添加修改删除属性时自动执行代码的功能组件。
Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。
主要作用是: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。

生命周期

Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。
web.xml 的加载顺序是:context- param -> listener -> filter -> servlet

listener:职责如概念。

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

  • 第一类:与servletContext有关的listner接口。包括:ServletContextListener、ServletContextAttributeListener
  • 第二类:与HttpSession有关的Listner接口。包括:HttpSessionListner、HttpSessionAttributeListener、HttpSessionBindingListener、
    HttpSessionActivationListener;
  • 第三类:与ServletRequest有关的Listener接口,包括:ServletRequestListner、ServletRequestAttributeListener
案例:显示登陆用户列表,并实现踢人功能。
  1. http://blog.csdn.net/wsf861559021/article/details/8261826

  2. 单点登录

package com.hq.listener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

import com.hq.pojo.Users;

/**
 * Application Lifecycle Listener implementation class OnlineUsersListener
 * 
 */
@WebListener
public class OnlineUsersListener implements HttpSessionAttributeListener {

    /**
     * @see HttpSessionAttributeListener#attributeRemoved(HttpSessionBindingEvent)
     */
    public void attributeRemoved(HttpSessionBindingEvent ev) {
        if ("user".equals(ev.getName())) {
            Users user = (Users) ev.getValue();
            ServletContext application = ev.getSession().getServletContext();
            List<Users> list = new ArrayList<Users>();
            if (application.getAttribute("onlineUsersList") != null) {
                list = (List<Users>) application
                        .getAttribute("onlineUsersList");
                list.remove(user);
            }
        }
    }

    /**
     * @see HttpSessionAttributeListener#attributeAdded(HttpSessionBindingEvent)
     */
    public void attributeAdded(HttpSessionBindingEvent ev) {
        if ("user".equals(ev.getName())) {
            ServletContext application = ev.getSession().getServletContext();
            Users user = (Users) ev.getValue();
            if (application.getAttribute("onlineUserMap") != null) {
                HashMap<String, String> onlineUser = (HashMap<String, String>)application.getAttribute("onlineUserMap");
                String sessionId = onlineUser.get(user.getOnlyId().toString());
                if (!"".equals(sessionId)) {
                    if (!ev.getSession().getId().equals(sessionId)) {
                        System.out.println("session不同地点重复登陆"+ev.getSession());
                        List<Users> list = new ArrayList<Users>();
                            list = (List<Users>) application.getAttribute("onlineUsersList");
                            for(Users u : list){
                                if(u.getOnlyId().equals(user.getOnlyId())){
                                    list.remove(u);
                                    list.add(user);
                                    onlineUser.remove(user.getOnlyId().toString());
                                    onlineUser.put(user.getOnlyId().toString(), ev.getSession().getId());
                                }
                            }
                    } 
                } else{//当前账号第一次登陆
                    System.out.println("当前session第一次登陆"+ev.getSession());
                    List<Users> list = new ArrayList<Users>();
                    list = (List<Users>) application.getAttribute("onlineUsersList");
                    list.add(user);
                }
            } else {//第一次有账号登陆
                System.out.println("第一次有账号登陆"+ev.getSession());
                List<Users> list = new ArrayList<Users>();
                list.add(user);
                application.setAttribute("onlineUsersList", list);
            }
        }
    }

    /**
     * @see HttpSessionAttributeListener#attributeReplaced(HttpSessionBindingEvent)
     */
    public void attributeReplaced(HttpSessionBindingEvent ev) {
        if ("user".equals(ev.getName())) {
            System.out.println("session重复登陆");
            ServletContext application = ev.getSession().getServletContext();
            List<Users> list = new ArrayList<Users>();
            if (application.getAttribute("onlineUsersList") != null) {
                list = (List<Users>) application
                        .getAttribute("onlineUsersList");
                list.remove(ev.getValue());
                list.add((Users) ev.getSession().getAttribute("user"));
            }

        }
    }

}
package com.hq.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;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.hq.pojo.Users;
import com.hq.service.impl.PermissionServiceImpl;

//@WebFilter("/UserServlet/*")
public class PermissionFilter implements Filter {

    private PermissionServiceImpl permissionService=new PermissionServiceImpl();

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        if (req.getSession().getAttribute("user") != null) {
            Users user = (Users) req.getSession().getAttribute("user");
            boolean flag = permissionService.validate(user, req.getRequestURI());
            if (flag) {
                chain.doFilter(request, response);
            } else {
                req.setAttribute("errorMsg", "对不起您没有权限");
                req.getRequestDispatcher("/error.jsp").forward(req, response);
                return;  
            }
        } else {
            req.setAttribute("errorMsg", "请登陆");
            //resp.sendRedirect("login.jsp");
            req.getRequestDispatcher("/login.jsp").forward(req, response);
            return;  
        }

    }

    /**
     * Default constructor.
     */
    public PermissionFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

3.interceptor

是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,是基于JAVA的反射机制。比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

生命周期

以struts的拦截器为例,加载了struts.xml以后,初始化相应拦截器。当action请求来时调用intercept方法,服务器停止销毁interceptor。

这里的拦截器指的是mvc框架中的拦截器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值