文章目录
Listener
监听器
- 能做什么事?
监听某一个事件的发生。 状态的改变。
- 监听器的内部机制
其实就是接口回调.
监听器实现原理——观察者模式
- 需求:
A在执行循环,当循环到5的时候, 通知B。
事先先把一个对象传递给 A , 当A 执行到5的时候,通过这个对象,来调用B中的方法。 但是注意,不是直接传递B的实例,而是传递一个接口的实例过去。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OuDBaKhs-1571359824198)(img/img01.png)]
Web监听器介绍
在JavaWeb开发中监听器总共有8个
按照使用方法来划分可以分为两类
第一类 实现接口然后通过注册生效
具体配置步骤
- 实现对应的监听器接口
- 重写接口中的方法
- 然后在web.xml或者注解的方式注册到容器中来使用
适用的监听器类型
ServletRequestListener、HttpSessionListener、ServletContextListener、ServletRequestAttributeListener、HttpSessionAttributeListener、SerlvetContextAttributeListener
第二类 让需要监听Session中的特定类型实现监听接口,不需要注册生效
具体配置步骤
- 让需要监听Session中的特定类型,如UserInfo实现监听接口
- 实现接口中的方法
适用的监听器类型
HttpSessionBindingListener、HttpSessionActivationListener
按照监听器的作用可以划分为三类
监听三个作用域创建和销毁
- request —HttpServletRequest
- session —HttpSession
- application — ServletContext
ServletRequestListener
- 监听事件
request创建:
访问服务器上的任意资源都会有请求出现。
访问 html: 会
访问 jsp: 会
访问 servlet : 会
request销毁:
服务器已经对这次请求作出了响应。
- 实现示例
- 新建Java类,实现ServletRequestListener接口
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class RequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("request请求结束");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("request请求开始");
}
}
- 在web.xml中注册监听器
<listener>
<listener-class>com.lanou3g.demo.RequestListener</listener-class>
</listener>
HttpSessionListener
- 监听事件
session的创建
只要调用getSession
html: 不会
jsp: 会 getSession();
servlet: 会
session的销毁
超时 30分钟
非正常关闭 销毁
正常关闭服务器(序列化)
- 应用场景
统计在线人数.
- 实现示例
- 新建Java类,实现HttpSessionListener接口
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class SessionLinsener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("session被创建了");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session销毁了");
}
}
- 在web.xml中注册监听器
<listener>
<listener-class>com.lanou3g.demo.SessionLinsener</listener-class>
</listener>
ServletContextListener
- 监听事件
- ServletContext创建:启动服务器的时候
- ServletContext销毁:关闭服务器. 从服务器移除项目
- 应用场景
在servletcontext创建的时候,
- 完成自己想要的初始化工作
- 执行自定义任务调度。 执行某一个任务。 Timer
- 实现示例
新建Java类,实现ServletContextListener接口
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁");
}
}
在web.xml中注册监听器
<listener>
<listener-class>com.lanou3g.demo.ContextListener</listener-class>
</listener>
监听三个作用域属性状态变更
可以监听在作用域中值 添加 | 替换 | 移除的动作。
servletContext — ServletContextAttributeListener
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NyuhNR0p-1571359824202)(img/img03.png)]
request — ServletRequestAttributeListener
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1pJ6x97-1571359824226)(img/img04.png)]
session — HttpSessionAttributeListener
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1syJv6Yi-1571359824232)(img/img02.png)]
监听httpSession里面存值的状态变更
这一类监听器不用注册。
HttpSessionBindingListener
监听特定类型对象与session 绑定和解除绑定 的动作,注意此监听器是让JavaBean实现监听接口,即表示当session中此类型的value状态发生变更时,此JavaBean会收到通知
与HttpSessionAttributeListener监听器不同的是,该监听器只对Session中的某种特定类型的属性变化感兴趣
// 注意:是让JavaBean实现该接口,不需要添加任何注解或在web.xml中配置
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Man implements HttpSessionBindingListener {
private String name;
private String nickName;
private int age;
public Man() {
}
public Man(String name, String nickName, int age) {
this.name = name;
this.nickName = nickName;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
Man man = (Man) event.getValue();
System.out.println("man对象绑定到session中 name: " + man.getName() + ", value: " + event.getValue());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
Man man = (Man) event.getValue();
System.out.println("man对象从session中解绑 name: " + man.getName() + ", value: " + event.getValue());
}
}
HttpSessionActivationListener
用于监听现在session的值 是 钝化 (序列化)还是活化 (反序列化)的动作
- 钝化 (序列化)
把内存中的数据 存储到硬盘上
- 活化 (反序列化)
把硬盘中的数据读取到内存中。
- session的钝化活化的用意何在
session中的值可能会很多, 并且我们有很长一段时间不使用这个内存中的值, 那么可以考虑把session的值可以存储到硬盘上【钝化】,等下一次在使用的时候,在从硬盘上提取出来。 【活化】
- 如何让session的在一定时间内钝化.
钝化、活化监听需要修改Tomcat配置
修改的地方有三个可选,主要是作用范围不一样
1. 在tomcat里面 conf/context.xml 里面配置
对所有的运行在这个服务器的项目生效
2. 在conf/Catalina/localhost/context.xml 配置
对 localhost生效。 localhost:8080
3. 在自己的web工程项目中的 META-INF/context.xml
只对当前的工程生效。
修改方法:
<!--
参数说明:
# maxIdleSwap : 1分钟不用就钝化
# directory : 钝化后的那个文件存放的目录位置。
-->
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="F:/temp"/>
</Manager>
</Context>
监听器使用步骤
- 与HttpSessionBindingListener类似, HttpSessionActivationListener也是针对特定类型监听的。那我们需要让需要监听钝化、活化状态的特定的JavaBean实现HttpSessionActivationListener接口
- 上面提到的几种配置方法,任选一种告诉Tomcat当Session不活跃、或者容器停止时Session钝化的策略
做好上面两步,当Session中有监听的特定类型,并且Session钝化、活化时就能触发通知
Filter
过滤器 , 其实就是对客户端发出来的请求进行过滤。 浏览器发出, 然后服务器派servlet处理。 在中间就可以过滤, 其实过滤器起到的是拦截的作用。
-
作用
- 对一些敏感词汇进行过滤
- 统一设置编码
- 自动登录
…
如何使用Filter
- 定义一个类, 实现Filter
public class FilterDemo implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("来到过虑器了。。。");
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
- 注册过滤器
在web.xml里面注册,注册的手法与servlet基本一样。
<filter>
<display-name>FilterDemo</display-name>
<filter-name>FilterDemo</filter-name>
<filter-class>com.itheima.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在Servlet3.0里可以通过 @WebFilter注解配置
Filter的生命周期
- 创建
在服务器启动的时候就创建。
- 销毁
服务器停止的时候。
Filter执行顺序
- 客户端发出请求,先经过过滤器, 如果过滤器放行,那么才能到servlet
- 如果有多个过滤器, 那么他们会按照注册的映射顺序 来 排队。 只要有一个过滤器, 不放行,那么后面排队的过滤器以及咱们的servlet都不会收到请求。
Filter细节
- init方法的参数 FilterConfig , 可以用于获取filter在注册的名字 以及初始化参数。 其实这里的设计的初衷与ServletConfig是一样的。
- 如果想放行,那么在doFilter 方法里面操作,使用参数 chain
chain.doFilter(request, response); 放行, 让请求到达下一个目标。
-
/* 写法格式与servlet一样。
-
全路径匹配 以 / 开始
/LoginServlet
-
以目录匹配 以 / 开始 以 * 结束
/demo01/*
-
以后缀名匹配 以 * 开始 以后缀名结束
*.jsp *.html *.do
注意:*号只能代表一段目录或者文件名,不能代替单词中的部分字母
-
-
针对 dispatcher 设置
REQUEST : 只要是请求过来,都拦截,默认就是REQUEST
FORWARD : 只要是转发都拦截。
ERROR : 页面出错发生跳转
INCLUDE : 包含页面的时候就拦截。
案例一 实现自动登录
- 需求分析
- 用户正常登录过一次以后,只要session不失效,用户可以直接访问网站中的其他页面,而不用再次登录。
- 如果没有登录或者session失效了, 那直接访问其他页面重定向到登录页面
1. 搭建环境
- 搭建数据库
- 搭建页面
2. 部分后台代码
登录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是否有效, 如果失效了,直接把请求重定向到登录页,让用户完成手动登录
- 如果session没有失效,那么就从session中获取用户登录信息和数据库中做对比,如果正确就可以正常登录。否则重定向到登录页,让用户手动登录。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession();
// 如果session里没有登录信息,无法自动登录,重定向到登录页,让用户手动登录
if(session.getAttribute("username") == null) {
resp.sendRedirect("login.jsp");
return;
}
String username = (String) session.getAttribute("username");
String password = (String) session.getAttribute("password");
// 检查session中的登录信息是否正确
if(checkValid(username, password)) {
chain.doFilter(request, response);
}
}
总结
Listener
8个
三种类型
针对三个作用域的创建和销毁
针对三个作用域的值改变 【添加 | 替换 | 移除】
针对session中的值 【钝化 活化】 , 【绑定 解绑】
钝化 ( 序列化 )
内存中的对象存储到硬盘
超时失效。 session销毁了。
非正常关闭服务器, 钝化 。 正常关闭服务器 销毁
设置了session钝化策略:context.xml
活化 (反序列化)
从硬盘里面读取到内存
应用场景:
ServletContextListner : 应用被部署的时候, 服务器加载这个项目的时候,做一些初始化工作, 任务调度。
HttpSessionBindingListener : 统计在线人数
HttpSessionActivationListener : 钝化活化处理
Filter
使用频率更高
- 如果要写一个过滤器。
- 定义一个类,实现接口 Filter
- 注册 web.xml . 与servlet相似。
- 过滤器放行。
chain.doFilter(request, response);
-
过滤器生命周期
创建: 服务器加载这个项目的时候创建实例
销毁: 关闭服务器或者从服务器中移除项目的时候。