过滤器filter与监听器listener
1、过滤器filter
1 概念filter
***filter:过滤器
***作用:对一个或者一类请求进行拦截 根据条件选择放行
web三大组件:servlet+filter+listener
servlet(秘书):接受请求 处理数据 给与响应
filter(保安):对请求进行拦截 选择放行
listener(FBI):对域对象的增删改查进行监控
2 filter使用
创建filter
package 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;
public class DemoFilter implements Filter {
{
System.out.println("DemoFilter:::构造代码块!!!");
}
@Override
public void destroy() {
System.out.println("DemoFilter:::destroy!!!");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
System.out.println("DemoFilter::::doFilter" + 1);
// 调用FilterChain的dofilter方法 放行请求
arg2.doFilter(arg0, arg1);
System.out.println("DemoFilter::::doFilter" + 2);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoFilter:::init!!!");
}
}
在web.xml配置filter
注意:xml用来设置拦截路径:/*:从项目路径开始
<filter>
<filter-name>DemoFilter</filter-name>
<filter-class>filter.DemoFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>DemoFilter</filter-name>
<url-pattern>/DemoServlet</url-pattern>
<url-pattern>/s/*</url-pattern>
<url-pattern>*.do</url-pattern>
<url-pattern>/s</url-pattern>
</filter-mapping>
创建servlet
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 DemoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
System.out.println("servlet::::DemoServlet");
response.getWriter().print("<font color='red'>DemoServlet:::success</font>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3 filter作用
* 访问权限控制
* 对request和response对象的功能进行控制
* 在请求处理之前执行预处理工作 在请求处理之后执行响应内容的加工:
(提取请求处理的公共代码)
编码集过滤器
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
//提取公共代码:对request和response设置编码集
arg0.setCharacterEncoding("UTF-8");
arg1.setCharacterEncoding("utf-8");
arg1.setContentType("text/html;charset=utf-8");
arg2.doFilter(arg0, arg1);
}
4 注意事项
* filter是单例 一个类只有一个对象
* filter单例对象 是tomcat启动时创建的
* filter可以拦截所有请求:包括对servlet、jsp、css、js、html、img
* Filter的doFilter方法用于拦截和url匹配的请求
* FilterChain的doFilter方法用于拦截的放行:::两个doFilter方法的参数列表不同
5 Filter的生命周期
- 创建对象
tomcat启动时 会创建filter的单例对象
- 初始化
filter对象一旦创建 tomcat就会调用filter对象的init方法 对filter对象进行初始化
- 拦截请求
每次filer配置的url被请求一次,tomcat就会调用filter对象的doFilter方法来拦截请求
然后通过FilterChain的doFiler来选择放行请求
- 销毁对象
tomcat在关闭之前 会调用filer对象的destroy方法 来销毁对象 释放内存
2、监听器listener
1 listener概念
***listener:监听器
监听域对象的某一事件 当此事件发生时 就执行对应的代码
listener:web的三大组件
注意:只能监听域对象+监听器中的代码是被动执行的
- 分类
域属性监听器:监听request/session/servletContext的属性的增删改:cud
HttpSessionAttributeListener,ServletRequestAttributeListener,ServletContextAttributeListener
域对象的生死监听器:监听request/session/servletContext对象创建和销毁
2 域属性监听器
package filter;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class DemoAttributelListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
// 统计人数:需要被整个项目共享 装在servletcontext域中:::要求会员登录 在seesion域中添加属性user
if (se.getName().equals("user")) { // 会员+1
// 获取servletcontext域中的count属性
Object count = se.getSession().getServletContext().getAttribute("count");
// 你是第一个登录者
if (count == null) {
se.getSession().getServletContext().setAttribute("count", 1);
} else {
// 原来的值+1
se.getSession().getServletContext().setAttribute("count", ((Integer) count) + 1);
}
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
// 统计人数:需要被整个项目共享 装在servletcontext域中:::要求会员登出:删除session中的域属性user
if (se.getName().equals("user")) { // 会员+1
// 获取servletcontext域中的count属性
Object count = se.getSession().getServletContext().getAttribute("count");
// 原来的值-1
se.getSession().getServletContext().setAttribute("count", ((Integer) count) - 1);
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println(se.getSession().getId()+se.getName());
System.out.println( se.getName() + se.getValue() + se.getSession().getAttribute(se.getName()));
}
}
- 配置监听器
<!-- 配置监听器 -->
<listener>
<listener-class>/filter/DemoAttributelListener</listener-class>
</listener>
3 域对象生死监听器
package filter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class DemoAttributelListener implements ServletRequestListener, HttpSessionListener, ServletContextListener {
public void requestDestroyed(ServletRequestEvent sre) {
}
// 统计每个页面的访问次数
public void requestInitialized(ServletRequestEvent sre) {
// 每个页面对应一个 访问次数 数据存储在map中
// 此数据被项目的所有资源共享:数据应该存储在servletcontext域中
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
System.out.println("requestInitialized:::请求的资源路径:::" + req.getServletPath());
String path = req.getServletPath();
// 获取servletContext域中添加属性:countMap
Map<String, Integer> countMap = (Map<String, Integer>) sre.getServletContext().getAttribute("countMap");
countMap.put(path, countMap.containsKey(path) ? (countMap.get(path) + 1) : 1);
}
public void sessionCreated(HttpSessionEvent se) {
}
public void sessionDestroyed(HttpSessionEvent se) {
}
public void contextDestroyed(ServletContextEvent sce) {
}
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
// 项目初始化就在servletContext域中添加属性:countMap
Map<String, Integer> countMap = new HashMap<>();
sce.getServletContext().setAttribute("countMap", countMap);
}
}
4 实现练习
- 统计:会员在线人数:::session的属性监听器
- 统计:在线人数:::session生死监听器
- 统计:资源访问量:::request的生死监听器