Servlet之过滤器(Filter)和监听器(Listener)
过滤器
过滤器是一个java组件,可以拦截发送至某个servlet,jsp页面或静态页面的请求,可以在响应发送到客户之前进行拦截
工作原理:

过滤器类必须实现 Filter 接口,包含的方法如下:
void destroy() //销毁方法
void init(FilterConfig filterConfig) throws ServletException //初始化方法
//主要的工作方法
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
//这里写request的相关代码
chain.doFilter(request, resp);
//这里写response的相关代码
}
FilterChain chain 过滤器链
FilterChain 接口用于调用过滤器链中的下一个过滤器或调用过滤器结束后的资源
过滤器链如图:

过滤器生命周期的各个阶段:
实例化:Web容器在不是web应用程序的时候对所有过滤器进行实例化
web容器回调它的无参构造方法
初始化:实例化完成之后,马上进行初始化工作
web容器回调init方法
过滤:请求路径匹配过滤器的URL映射
web容器回调 doFilter方法 --> 主要工作方法
销毁:web容器在卸载web应用之前
web容器回调 destroy方法
过滤器的实际应用:
1.对请求消息体中的数据设置统一的编码
2.阻止非法用户的请求
3.过滤非法数据
注意:
过滤器使用时需要在web.xml中配置,需要在“url-pattern”标签中指明过滤的对象 如“/*”过滤项目中所有文件,代码如下:
<filter>
<display-name>OurFilter</display-name>
<filter-name>OurFilter</filter-name>
<filter-class>nm.filter.OurFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OurFilter</filter-name>
<url-pattern>/show.do</url-pattern>
</filter-mapping>
过滤器的简单实例应用
我们都知道当我们百度搜索关键词的时候,搜索出的关键词会变成着重飘红。
接下来的通过过滤器,来简单的模仿百度的这种功能:
- 用户请求的页面
package nm.filter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class OurServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//这里我们向页面输出4段带"我们"的句子
out.println("我们去玩吧<br/>");
out.println("你打不过我们<br/>");
out.println("我们一起吃饭去<br/>");
out.println("看我们的儿子<br/>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- 在这里我们写一个MyWriter类继承PrintWriter类 重写里面的write方法,将原来输出字符串的方法,改变成保存字符串的方法,另外再写一个获取字符串的方法,如下:
package nm.filter;
import java.io.PrintWriter;
import java.io.Writer;
public class MyWriter extends PrintWriter{
private StringBuilder buffer;
public MyWriter(Writer out) {
super(out);
buffer = new StringBuilder();
}
@Override
public void write(String s) {
buffer.append(s);
}
// 将write流中的内容全部转换为String
public String getContent(){
return buffer.toString();
}
}
- 这里我们写一个MyResponse类继承HttpServletResponseWrapper类(HttpServletResponse接口的实现类),来获取我们上面所写的MyWriter类:
package nm.filter;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class MyResponse extends HttpServletResponseWrapper{
private MyWriter myWriter;
public MyResponse(HttpServletResponse response) {
super(response);
}
@Override
public MyWriter getWriter() throws IOException {
myWriter = new MyWriter(super.getWriter());
return myWriter;
}
public MyWriter getMyWriter(){
return myWriter;
}
}
- 完成上面两个类之后,我们来写过滤器。通过过滤器我们将用户访问的页面拦截,将原本输出的信息用我们所写的类和方法代替,将里面的关键词“我们”进行修改,之后再利用原始的类和方法将信息输出:
package nm.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.http.HttpServletResponse;
public class OurFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
MyResponse resp = new MyResponse((HttpServletResponse)response);
chain.doFilter(request, resp);
MyWriter writer = resp.getMyWriter();
if(writer!=null){
String content = writer.getContent();
String new_content = content.replace("我们","<span style='color:red'>我们</span>");
response.getWriter().write(new_content);
}
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
最终的结果如图:

监听器
Listener 用于监听java web程序中的事件,比如 创建,修改,删除 Session,request,context等 ,并触发响应的事件
观察者模式:事件发生的时候会自动触发该事件对应 的Listener
Listener 主要对于 Session,request,context 进行监控
具体如下:
不同功能Listener需要实现的不同的Listener接口
一个Listener也可以实现多个接口,这样可以多种功能的监听器一起工作
8种监听器 分为三类
1.监听Session,request,context的创建 和 销毁
HttpSessionListener :监听Session的创建和销毁
创建Session的时候执行 sessionCreate 方法
当session的执行invalidate方法的时候,触发SessionDestroyed 方法
ServletRequestListener : 监听Request的创建和销毁
每次用户请求request都会执行requestInitialized方法
request处理完毕之后销毁之前执行 requestDestroyed
注意:如果一个HTML页面中有多个图片,则每请求一次HTML页面可能会触发request事件
ServletContextListener :监听Context的创建和销毁
服务器启动的时候 执行 contextInitialized 方法
服务器关闭或项目卸载 执行 contextDestroyed 方法
2.监听对象属性编号 分别:
Session属性变化 HttpSessionAttributeListener
Context属性变化 ServletContextAttributeListener
Request属性变化 ServletRequestAttributeListener
XXXXAdded();
XXXXReplaced();
XXXXRemoved() ;
说明:XXXX表示 Session context request
3.监听Session内的对象
HttpSessionBindingListener
当对象被放到Session里执行 valueBound 方法
当对象从Session中移除执行 valueUnbound 方法
HttpSessionActivationListener
服务器关闭的时候,会将Sessioin里的内容保存到硬盘上,这个过程叫 钝化
服务器重新启动的时候,会将session内容从硬盘中重新加载。
当Session中的对象被钝化的时候 sessionWillPassivate
当session中的对象被重新加载 执行sessionDidActivate
常用于session内的对象对session监听
注意: 是Session内的对象,而不是Session本身,不需要web.xml配置
实现web.xml 的Listener 配置
1. <listener> 标签 和 <listener-class>
2. <listener> 一般配置在 <servlet> 标签的前面
具体代码如下:
<listener>
<listener-class>nm.listener.TestListener</listener-class>
</listener>
监听器简单的应用实例
接下来,我们通过监听器来实现一个简单的统计用户在线人数的简单实例,具体代码如下:
- 用户登录界面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户登录界面</title>
</head>
<body>
<h1>用户登录界面</h1>
<form action="login.do" method="post">
用户名:<input type="text" name="uname" /><br/><br/><br/>
密 码:<input type="password" name="upwd" /><br/><br/><br/>
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
- 用户登录的简单处理程序,用户名为admin密码为123456
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String uname = request.getParameter("uname");
String upwd = request.getParameter("upwd");
HttpSession session = request.getSession();
//登陆成功后向页面输出当前在线人数
if(uname.equals("admin") && upwd.equals("123456")) {
response.getWriter().println("登陆成功~<br/>");
response.getWriter().println("当前在线人数 :"+(Integer)session.getServletContext().getAttribute("uerNumber")+"<br/>");
response.getWriter().println("<a href='DistoryServlet'>点击退出</a>");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- 用户点击退出后的处理程序,这里的处理是删除会话session并重定向到登陆界面
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DistoryServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//清除session并重定向到登陆界面
request.getSession().invalidate();
response.sendRedirect("login.html");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- 监听器处理程序,用一个变量来统计在线人数,每建立一个会话我们就让变量增加1,每销毁一个会话我们就让变量减少1
package listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class LoginListener implements HttpSessionListener {
int uerNumber = 0; //用来统计在线人数的变量
public void sessionCreated(HttpSessionEvent arg0) {
uerNumber++;
//将变量设为应用上下文的属性,便于在整个项目都可以访问到在线人数
arg0.getSession().getServletContext().setAttribute("uerNumber", uerNumber);
System.out.println("当前在线用户:"+uerNumber);
}
public void sessionDestroyed(HttpSessionEvent arg0) {
uerNumber--;
//将变量设为应用上下文的属性,便于在整个项目都可以访问到在线人数
arg0.getSession().getServletContext().setAttribute("uerNumber", uerNumber);
System.out.println("当前在线用户:"+uerNumber);
}
}
结果如图:

以上就是Servlet中的
过滤器(Filter)和监听器(Listener)
Servlet之过滤器(Filter)和监听器(Listener)的更多相关文章
- 过滤器Filter与监听器Listener
过滤器Filter 过滤器也是一种servlet 它也可以对用户的请求进行处理 , 但是他所做的处理,只是一些轻量级的处理.Fileter就好像jsp页面与servlet之间的一道关卡,如果这个 ...
- 过滤器(filter),监听器(listener),与servlet的执行顺序
创建: 加载顺序 监听器-->过滤器-->Servlet.项目启动后,容器会首先创建声明的各种监听器,为后继的各个事件监听做准备,然后创建过滤器,最后是Servlet.销毁的时候是反序进行 ...
- 二十五、过滤器Filter,监听器Listener,拦截器Interceptor的区别
1.Servlet:运行在服务器上可以动态生成web页面.servlet的声明周期从被装入到web服务器内存,到服务器关闭结束.一般启动web服务器时会加载servelt的实例进行装入,然后初始化工作 ...
- Servlet过滤器Filter和监听器
一.Servlet过滤器的概念: *********************************************************************************** ...
- JavaWeb学习篇之----Servlet过滤器Filter和监听器
首先来看一下Servlet的过滤器内容: 一.Servlet过滤器的概念: ************************************************************** ...
- Servlet的过滤器Filter
Servlet 编写过滤器 Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息. 可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Serv ...
- 8-过滤器Filter和监听器Listener
一.web监听器:监听特殊事件的发生1.监听实现步骤 a.写一个java类,实现特定的接口,重写相关方法 b.在web.xml中,牌配置 <listener> <listener-c ...
- Java Web(五) 监听器Listener
监听器概述 在上一篇里介绍了过滤器Filter,而Listener是Servlet的另一个高级特性.Listener用于监听Java Web程序中的事件,例如创建,修改,删除Session,reque ...
- JavaWeb_初识过滤器Filter
菜鸟教程 传送门 过滤器Filter::JavaWeb三大组件之一,它与Servlet很相似,过滤器是用来拦截请求的,而不是处理请求的 当用户请求某个Servlet时,会先执行部署在这个请求上的Fil ...
随机推荐
- javascript 之数据类型
写在前面 国庆整理资料时,发现刚开始入门前端时学习JS 的资料,打算以一个基础入门博客记录下来,有不写不对的多多指教: 先推荐些书籍给需要的童鞋 <JavaScript 高级程序设计.pdf&g ...
- 添加 hexo yilia 主题的文章阅读量
根据此篇博客(点击查看) 配置出自己的博客阅读量,里面介绍了如何配置开通 leancloud 应用 当然介绍我如何配置 yilia 显示自己的浏览量的. 首先在 yilia 主题下修改 _config ...
- 65、django之模型层(model)--添加、单表查询、修改基础
上篇带大家简单做了一下图书表的创建.简单的查看和删除,今天会先简单介绍添加和修改,因为添加和修改与删除一样都很简单,本篇会相对多介绍一点单表查询,大家都知道数据库中查询是最重要的一部分,毕竟无论是修改 ...
- 对象转字典 iOS
最近在开发SDK,我开放给客户model类设置信息后,对象转字典,POST给后台. 思路:通过Runtime访问属性列表,快速转换成字典. FRObjectToDictionary.h类 p.p1 { ...
- 加载web项目时报的错误:Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modul
用eclipse开发的java项目不能加载到tomcat6.0服务器,原因是:jst.web的版本高了 <installed facet="jst.web" version= ...
- 快速部署Telegraf & Influxdb
是什么? Telegraf 是一个用 Go 编写的代理程序,可收集系统和服务的统计数据,并写入到 InfluxDB 数据库.Telegraf 具有内存占用小的特点,通过插件系统开发人员可轻松添加支持其 ...
- 关于session共享的解决方法
当网站业务规模和访问量的逐步增大,原本由单台服务器.单个域名组成的网站架构可能已经无法满足发展需要 此时会购买更多的服务器,并且以频道化的方式启用多个二级子域名,然后根据业务功能将网站分别部署在独立的 ...
- Java基础笔记8
Object类 Object类是所有类的父类. 如果某个类没有显示的继承某个父类,那么该类则继承Object. 类 Object 是类层次结构的根类.每个类都使用 Object 作为超类. 所有对象( ...
- django开发中利用 缓存文件 进行页面缓存
首先我们先来了解下浏览器的缓存 浏览器缓存机制 Cache-control策略 Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是 ...
- 2017CCPC秦皇岛G ZOJ 3987Numbers(大数+贪心)
Numbers Time Limit: 2 Seconds Memory Limit: 65536 KB DreamGrid has a nonnegative integer n . He ...