在javaweb编程的时候,我们不可避免的会使用到java的过滤器(Filter)和监听器(Listener),今天我们对这两部分的内容做一下简单介绍。
过滤器Filter
过滤器顾名思义,是用来根据用户的需求,对请求进行过滤操作或对请求进行一些个性化处理的。
我们先来看一下过滤器是怎么实现的。
- 过滤器的实现
在java中,实现过滤器,需要实现javax.servlet.Filter接口。实现接口,需要实现三个方法:
① init(FilterConfig config)
② doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
③ destroy()
其中,init()方法是web容器初始化的时候调用的,且只调用执行一次。init方法中含有一个config参数,该参数是用来读取配置在filter中的初始化参数的。
doFilter方法是过滤器的主方法,所有需要实现的个性化操作均在本方法中完成。方法含有三个参数:ServletRequest ,ServletResponse ,FilterChain 。其中request和response参数不多做解释,分别是请求和响应参数,可以获取请求的参数及session等信息,也可以通过response回写响应信息。而FilterChain 这个参数可能是比较陌生的,这个参数时过滤链参数,那是用来做什么的呢?举一个现实的例子,我们在参观某些景点的时候,会有提示说:1.5m以下或12岁以下的儿童不允许入内。那工作人员在筛选的时候,肯定是分两步的:1 询问你的年龄。 2 测量你的身高。这两个条件可以理解为两个过滤器。那进入景点的时候,工作人员问完你的年龄登记后,可能会跟你说去哪里测一下身高。也就是说,两个过滤器总会有一个先后顺序的,那前面的过滤器完成后怎么去找到接下来的过滤器呢?就是通过这个过滤链FilterChain 来找到。过滤链其实就是多个过滤器组成的链。在完成本过滤器的操作后,执行chain.doFilter(request,response);即可找到下一个过滤链,进行接下来的过滤操作。
destroy()方法是doFilterO方法里的所有线程退出或已超时,由容器调用的。服务器调用destoryO以指出过滤器已结束服务,用于释放过滤器占用的资源。
在完成过滤器的设计后,在web.xml中配置对应的过滤器即可。
过滤器执行过程
过滤器的执行过程如下图:
我们可以看出,过滤器是作用在客户端和servlet之间,起到“过滤”的作用的。
请看下文实例:
过滤器类:
public class FilterDemo01 implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String code=request.getParameter("code")==null?"":request.getParameter("code");
System.out.println("code:"+code);
System.out.println(code=="code");
if("code".equals(code)){
System.out.println("我不开心了!");
}
chain.doFilter(request,response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
String name=arg0.getInitParameter("name");
System.out.println(name+" say:Filter init ...");
}
}
web.xml: 过滤器的配置,和servlet的配置是类似的。
<!-- filter -->
<filter>
<filter-name>filter</filter-name>
<filter-class>com.ugrow.filter.FilterDemo01</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>why</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
监听器Listener
- 监听器的作用
监听器的作用是监听你的web应用,监听许多信息的初始化,销毁,增加,修改,删除值等。Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。
- 监听器的实现
监听器的实现与过滤器是类似的。一:编写监听器类。 二 :配置监听器 监听器的类型
按监听的对象划分:servlet2.4规范定义的事件有三种:
1.用于监听应用程序环境对象(ServletContext)的事件监听器
2.用于监听用户会话对象(HttpSession)的事件监听器
3.用于监听请求消息对象(ServletRequest)的事件监听器
按监听的事件类项划分
1.用于监听域对象自身的创建和销毁的事件监听器
2.用于监听域对象中的属性的增加和删除的事件监听器
3.用于监听绑定到HttpSession域中的某个对象的状态的事件监听器
在一个web应用程序的整个运行周期内,web容器会创建和销毁三个重要的对象,ServletContext,HttpSession,ServletRequest。
简单实例:
监听器类:
public class MyListener02 implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("listener is initing");
}
}
web.xml
<!-- listener -->
<listener>
<listener-class>com.ugrow.listener.MyListener02</listener-class>
</listener>
<listener>
<listener-class>com.ugrow.listener.MyListener</listener-class>
</listener>
监听器,过滤器和Servlet的执行顺序
在javaweb中,监听器,过滤器和Servlet这三者的执行顺序是:
监听器执行–>过滤器执行–>servlet执行–>servlet执行完成–>过滤器销毁–>监听器销毁。
也就是说,监听器的执行是早于过滤器的。那如果是多个监听器和多个过滤器,如何定义他们的执行先后顺序呢?监听器和过滤器的执行顺序是跟在web.xml中的配置顺序有关的,越往上的组件越先加载执行。所以按照自己的需求配置即可。