关于这个问题, 是个比较复杂的话题. 不过我希望通过例子来解释会方便理解一些.
假设有一个非常危险的任务, 是九死一生. 需要你揣着炸药包从北平开车走高速路过保定去石家庄把鬼子的碉堡给炸了. 注意: 这个任务十分艰巨, 有可能半路炸药爆炸. 所以出发前你需要苦练10元一本的<<铁布衫>>, 还需要立遗嘱交代一下后事. 下面是路线图:
去时路线: 北平 ==> 高速路收费站入口(都有警察和警犬) A ==> 保定收费站 B ==> 石家庄收费站 C ==> 炸碉堡 D ==> 转车(刚才的车已经炸没了) E =>
回来路线: 石家庄收费站 ==> 保定收费站 ==> 高速路收费站出口(都有警察和警犬) A ==> 安全回到北平 G
那么我们先简介可能发生的情况. A 点有可能被警察和警犬发现, 所以你只能被扭送回北平. 即使不被发现, 还可能出现收费时发现10个现大洋一个路口的买路钱没带!! 哎, 只能又回去了. 还有最惨的: 高速路入口写着: 对不起, 到石家庄的路线因为施工不通! 只好回家等着吧.
到了B和C你可能还会被人发现带了炸药包, 或者发现买路费少带了! 极有可能又被扭送回北平, 注意已经在半道了, 是不会让你继续到石家庄的, 所以你会被从车上逮下来, 然后转到警车上带回来! 也就是从 B 或者 C 直接返回.
好了, 最佳情况就是你炸了碉堡, 也成功的返回了. 然后你可以开心的把<<铁布衫>>扔了, 然后宣告遗嘱作废.
OK, 以上过程, 就是过滤器和监听器的真实案例.
那么炸碉堡这个任务, 就相当于要调用 JSP 或者 Servlet 来获得执行结果(炸碉堡 D ). 在执行之前你需要做一些准备工作, 相当于要写一个
监听器 com.allanlxf.ums.web.ServiceListener
在里面你可以做一些事情例如初始化资源, 例如上文的苦练<<铁布衫>>, 立遗嘱, 这个相当于代码中的
public void contextInitialized(ServletContextEvent sce) 这样一个初始化事件.
那么在整个任务完成之后, 这些事情你就要考虑应该作废了, 所以需要
public void contextDestroyed(ServletContextEvent sce) 这样一个销毁事件, 例如把<<铁布衫>>扔了, 然后宣告遗嘱作废, 也就是收回资源.
那么过滤器在哪里呢? 它位于任务的 A B C 点. 注意是双向路程都会经过的. 也就是请求和响应都会经过. 但是过滤器也会检查不同的情况, 例如 A 点实际上有两个过滤功能: 查炸药包和收买路钱. 这就相当于配置了:
sessionFilter
* *.do
* REQUEST
* FORWARD
两个过滤功能都要检查. 如果成功了怎么办呢? 会继续让你走下一个路口, 注意不是让你直接成功. 也就是代码:
if(session.getAttribute("user") != null || path.equals("/login"))//若用户已经登录并且当前路径仍然停留在登录页面 {
chain.doFilter(request, response);//继续走下面的过滤器或者任务(不保证最终任务, 因为下个过滤器也可能让你回来)
只有当走到 C 点的时候, 下一步才是执行了最终的任务: 执行JSP或者Servlet.
}
反过来怎么办? 把你扭送上警车, 强行返回! 这样你连路口 B C 和最终任务都无法访问了. 也就是不会让你访问下一个过滤器和执行最终的 JSP 或者 Serlvet, 可以选择直接返回, 或者放警车上带回去.
{
return;// 直接返回
或者 response.sendRedirect(request.getContextPath() + "/login.jsp");//则扭送上警车, 强行返回到警察局
}
那么在 E 点发生了什么? 也就是你可能替换掉了原来的 response 对象, 也就是换车. 这意味着你可以在过滤器里私下修改请求和响应对象.
虽然已经不那么抽象了, 但是要理解可能还是需要耐心体会的.