listener & Filter
listener
监听器LIstener就是在application,session,request三个对象创建、销毁或者往其中添加修改、删除属性时自动执行代码的功能组件。
【listener 时Servlet的监听器,可以监听客户端的请求,服务端的操作等等】
-
listener的分类
- ServletContex监听:
- ServletContexListener:对于整个servlet上下文进行监听(创建、销毁)
- ServletContex创建:启动服务器的时候
- ServletContex销毁:关闭服务器的时候(从服务器移除项目的时候)
- ServletContexAttributeListener:对Servlet上下文属性进行监听(增删改属性)
- ServletContexListener:对于整个servlet上下文进行监听(创建、销毁)
- Session监听:
- HttpSessionListener接口:对于Session的整体状态监听
- Session创建:只要调用getSession就会创建
- Session销毁:超时、非正常关闭、非正常关闭服务器(序列化)
- HttpSessionAttributeListener接口:对session的属性进行监听
- HttpSessionActivationListener:用于监听现在session的值,钝化(序列化)还是活化(反序列化)的动作。
- HttpSessionListener接口:对于Session的整体状态监听
- Request监听
- ServletRequestListener:用于对request请求进行监听(创建和销毁)
- Request创建:访问服务器上的任何资源这个请求都会创建
- Request销毁:服务器已经对这次请求做出了响应
- ServletRequestAttributeListener:对Request属性的监听(增删改属性)
- ServletRequestListener:用于对request请求进行监听(创建和销毁)
- ServletContex监听:
-
Listener应用实例
- 利用HttpSessionListener统计最多在线用户人数
- Spring使用ContextLoaderListener加载ApplicationContext配置信息
- Spring使用Log4jConfigListener配置Log4j日志
- Spring使用IntrospectorCleanupListener清理缓存
-
监听器的作用:监听某一个事件的发生,状态的改变
【坚挺的内部机制,其实就是接口的回调】
Filter
-
Filter简介
- Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等 一些高级功能。 Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter 技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,Filter接口源代码:
public abstract interface Filter{
public abstract void init(FilterConfig paramFilterConfig) throws ServletException;
public abstract void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain
paramFilterChain) throws IOException, ServletException;
public abstract void destroy();
}
- Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等 一些高级功能。 Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter 技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,Filter接口源代码:
-
Filter是如何实现拦截的?(Filter的工作原理)
- Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前, 都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的: 调用目标资源之前,让一段代码执行。 是否调用目标资源(即是否让用户访问web资源)。 调用目标资源之后,让一段代码执行。 web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个 doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问, 否则web资源不会被访问。
-
Filter开发流程
-
Filter开发步骤 :
Filter开发分为2步:
编写java类实现Filter接口,并实现其doFilter方法。
在web.xml 文件中使用和元素对编写的filter类进行注册,并设置它所能拦截的资源。
过滤器范例:
package com.tain.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 FilterDemo implements Filter { public FilterDemo() { } public void destroy() { System.out.println("----Filter销毁了----"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 对request、response进行一些预处理 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); System.out.println("----调用service之前执行一段代码----"); chain.doFilter(request, response); // 执行目标资源,放行 System.out.println("----调用service之后执行一段代码----"); } public void init(FilterConfig fConfig) throws ServletException { System.out.println("------filter初始化了-------"); } }
在web. xml中配置过滤器:
-
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>FilterDemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>FilterServlet</display-name>
<servlet-name>FilterServlet</servlet-name>
<servlet-class>com.tian.servlet.FilterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FilterServlet</servlet-name>
<url-pattern>/FilterServlet</url-pattern>
</servlet-mapping>
<filter>
<display-name>FilterDemo</display-name>
<filter-name>FilterDemo</filter-name>
<filter-class>com.tain.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
filter细节
【有多个过滤器时,过滤顺序与注册的 顺序有关,只要有一个过滤器不放行,那么后面的过滤器和servlet都不会收到请求】
-
init方法的参数 FilterConfig , 可以用于获取filter在注册的名字 以及初始化参数。 其实这里的设计的初衷与ServletConfig是一样的。
-
如果想放行,那么在doFilter 方法里面操作,使用参数 chain
chain.doFilter(request, response); 放行, 让请求到达下一个目标。
-
/* 写法格式与servlet一样。
- 全路径匹配 以 / 开始
/LoginServlet - 以目录匹配 以 / 开始 以 * 结束
/demo01/* - 以后缀名匹配 以 * 开始 以后缀名结束
*.jsp *.html *.do
- 全路径匹配 以 / 开始
-
针对 dispatcher 设置
REQUEST : 只要是请求过来,都拦截,默认就是REQUEST
FORWARD : 只要是转发都拦截。
ERROR : 页面出错发生跳转
INCLUDE : 包含页面的时候就拦截。
自动登录
- 需求分析
-
搭建环境
-
搭建数据库
-
搭建页面
登录servlet代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String userName = request.getParameter("username");
String password = request.getParameter("password");
String autoLogin = request.getParameter("auto_login");
UserBean user = new UserBean();
user.setUsername(userName);
user.setPassword(password);
UserDao dao = new UserDaoImpl();
UserBean userBean = dao.login(user);
if(userBean != null){
//成功了,进入首页
request.getSession().setAttribute("userBean", userBean);
response.sendRedirect("index.jsp");
}else{
//不成功...
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
过滤器代码
过滤器的核心不是完成拦截不给 , 还是放行显示。 它的核心是在放行之前,帮用户完成登录的功能。
- 实现思路
- 先判断session是否有效, 如果有效,就不用取cookie了,直接放行。
- 如果session失效了,那么就取 cookie。
- 没有cookie 放行
- 有cookie
- 取出来cookie的值,然后完成登录
- 把这个用户的值存储到session中
- 放行。
/**
-
@see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest request = (HttpServletRequest) req;//先判断,现在session中还有没有那个userBean.
UserBean userBean = (UserBean) request.getSession().getAttribute(“userBean”);
//还有,有效。
if(userBean != null){
chain.doFilter(request, response);
}else{
//代表session失效了。//2. 看cookie。 //1. 来请求的时候,先从请求里面取出cookie , 但是cookie有很多的key-value Cookie[] cookies = request.getCookies(); //2. 从一堆的cookie里面找出我们以前给浏览器发的那个cookie Cookie cookie = CookieUtil.findCookie(cookies, "auto_login"); //第一次来 if(cookie == null){ chain.doFilter(request, response); }else{ //不是第一次。 String value = cookie.getValue(); String username = value.split("#itheima#")[0]; String password = value.split("#itheima#")[1]; //完成登录 UserBean user = new UserBean(); user.setUsername(username); user.setPassword(password); UserDao dao = new UserDaoImpl(); userBean = dao.login(user); //使用session存这个值到域中,方便下一次未过期前还可以用。 request.getSession().setAttribute("userBean", userBean); chain.doFilter(request, response); }
}
} catch (Exception e) {
e.printStackTrace();
chain.doFilter(req, response);
}
}
- 取出来cookie的值,然后完成登录
BeanUtils的使用
BeanUtils.populate(bean, map);
//注册自己的日期转换器
ConvertUtils.register(new MyDateConverter(), Date.class);
//转化数据
Map map = request.getParameterMap();
UserBean bean = new UserBean();
转化map中的数据,放置到bean对象身上
BeanUtils.populate(bean, map);
总结
Listener
8个
三种类型
针对三个作用域的创建和销毁
针对三个作用域的值改变 【添加 | 替换 | 移除】
针对session中的值 【钝化 活化】 , 【绑定 解绑】
钝化 ( 序列化 )
内存中的对象存储到硬盘
超时失效。 session销毁了。
非正常关闭服务器, 钝化 。 正常关闭服务器 销毁
设置了session,多久时间。 context.xml
活化 (反序列化)
从硬盘里面读取到内存
ServletContextListner : 应用被部署的时候, 服务器加载这个项目的时候,做一些初始化工作, 任务调度。
HttpSessionListener : 统计在线人数
HttpSessionActivationListener : 钝化活化处理
Filter
使用频率更高
- 如果要写一个过滤器。
-
定义一个类,实现接口 Filter
-
注册 . web.xml . 与servlet相似。
- 过滤器放行。
chain.doFilter(request, response);
- 过滤器生命周期
创建: 服务器加载这个项目的时候创建实例
销毁: 关闭服务器或者从服务器中移除项目的时候。