Apache Shiro学习笔记(七)Servlet3.0 Listener介绍
鲁春利的工作笔记,好记性不如烂笔头当Web应用在Web容器中运行时,Web应用内部会不断地发生各种事件:如Web应用被启动、Web应用被停止、用户session开始、用户session结束等。通常这些Web操作对开发者是透明的,但Servlet API也提供了相应的接口来监控这些变化。
当我们要使用Listener时,只需要两个步骤:
① 定义Listener实现类(实现对应的接口)
② 通过Annotation或在web.xml文件中配置Listener
1、实现Listener接口
不同的Web事件对应的监听器也不同,常用的Web事件监听器接口有如下几个:
[*] 1.1 Servlet Context Events
->ServletContextListener:用于监听Web应用的启动和关闭
->ServletContextAttributeListener:用于监听ServletContext范围(application)内属性的改变
[*] 1.2 Http Session Events
->HttpSessionListener:用于监听用户session的开始和结束
->HttpSessionAttributeListener:用于监听HttpSession范围(session)内属性的改变
->HttpSessionActivationListener:session的passivation是指非活动的session被写入持久设备,activate是反过程。
一般情况下和HttpSessionBindingListener一起使用。
->HttpSessionBindingListener:实现HttpSessionBindingListener接口的对象被绑定到session时
触发valueBound事件,解除绑定时触发valueUnbound事件。
[*] 1.3 Servlet Request Events
->ServletRequestListener:用于监听用户请求
->ServletRequestAttributeListener:用于监听ServletRequest范围(request)内属性的改变 一般来说,需要监听哪些Web事件就实现对应接口的方法即可。
2、配置Listener
实现了Listener类之后,还需要配置Listener,可以选择Annotaion方式或web.xml方式。
[*] Annotation方式
只需使用@WebListener修饰Listener实现类即可(要求Servlet3.0以上)
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {......}
[*] web.xml方式
com.invicme.apps.shiro.listener.XXXListener
说明:
在线人数统计网上一般的实现方式是实现HttpSessionListener,监控session的创建(create)和销毁(destroy),但在实际的使用过程中,发现destroy并不及时并且在session.invalidate()的时候还会调用一次sessionCreated()。
package com.invicme.apps.shiro.listener;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class OnlineUserBindingListener implements HttpSessionBindingListener {
String username;
public OnlineUserBindingListener(String username){
this.username = username;
}
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 把用户名放入在线列表
List onlineUserList = (List) application.getAttribute("onlineUserList");
// 第一次使用前,需要初始化
if (onlineUserList == null) {
onlineUserList = new ArrayList();
application.setAttribute("onlineUserList", onlineUserList);
}
onlineUserList.add(this.username);
}
public void valueUnbound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 从在线列表中删除用户名
List onlineUserList = (List) application.getAttribute("onlineUserList");
onlineUserList.remove(this.username);
System.out.println(this.username + "退出。");
}
} 在LoginController中,每次登录成功之后可以执行一次,session.setAttribute("loginUserLS", new OnlineUserBindingListener(username))。
3、Listener示例
[*] 3.1 Servlet Context Events
package com.invicme.apps.shiro.listener.context;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about ServletContext lifecycle changes.
*/
@WebListener
public class MyServletContextListener implements ServletContextListener {
private static final Logger logger = Logger.getLogger(MyServletContextListener.class);
public MyServletContextListener() {
logger.info("MyServletContextListener() was invoke...");
}
// Web容器启动的时候执行改方法
public void contextInitialized(ServletContextEvent sce){
logger.info("contextInitialized() was invoke.");
}
// Web容器reload应用时,首先destroy,然后再initialize
public void contextDestroyed(ServletContextEvent sce){
logger.info("contextDestroyed() was invoke.");
}
}
package com.invicme.apps.shiro.listener.context;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about ServletContext attribute changes.
*/
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
private static final Logger logger = Logger.getLogger(MyServletContextAttributeListener.class);
/**
* Default constructor.
*/
public MyServletContextAttributeListener() {
logger.info("MyServletContextAttributeListener() was invoke...");
}
// context.setAttribute()
public void attributeAdded(ServletContextAttributeEvent event){
logger.info("attributeAdded() was invoke...");
}
// context.setAttribute(已设置过的属性)
public void attributeReplaced(ServletContextAttributeEvent event){
logger.info("attributeReplaced() was invoke...");
}
// context.removeAttribute()
public void attributeRemoved(ServletContextAttributeEvent event){
logger.info("attributeRemoved() was invoke...");
}
}
[*] 3.2 Http Session Events
package com.invicme.apps.shiro.listener.session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about HttpSession lifecycle changes.
*/
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
private static final Logger logger = Logger.getLogger(MyHttpSessionListener.class);
/**
* Default constructor.
*/
public MyHttpSessionListener() {
logger.info("MyHttpSessionListener() was invoke...");
}
// 会话建立(如:request.getSession())
public void sessionCreated(HttpSessionEvent se){
logger.info("sessionCreated() was invoke...");
}
public void sessionDestroyed(HttpSessionEvent se){
logger.info("sessionCreated() was invoke...");
}
}
package com.invicme.apps.shiro.listener.session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about HttpSession attribute changes.
*/
@WebListener
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
private static final Logger logger = Logger.getLogger(MyHttpSessionAttributeListener.class);
/**
* Default constructor.
*/
public MyHttpSessionAttributeListener() {
logger.info("MyHttpSessionAttributeListener() was invoke...");
}
// session.setAttribute()
public void attributeAdded(HttpSessionBindingEvent event){
logger.info("attributeAdded() was invoke...");
}
// session.setAttribute(已经设置过的属性)
public void attributeReplaced(HttpSessionBindingEvent event){
logger.info("attributeReplaced() was invoke...");
}
// session.removeAttribute()
public void attributeRemoved(HttpSessionBindingEvent event){
logger.info("attributeRemoved() was invoke...");
}
}
package com.invicme.apps.shiro.listener.session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Causes an object to be notified when it is bound to or unbound from a session.
*/
@WebListener
public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
private static final Logger logger = Logger.getLogger(MyHttpSessionBindingListener.class);
/**
* Default constructor.
*/
public MyHttpSessionBindingListener() {
logger.info("MyHttpSessionBindingListener() was invoke...");
}
public void valueUnbound(HttpSessionBindingEvent event){
logger.info("valueUnbound() was invoke...");
}
public void valueBound(HttpSessionBindingEvent event){
logger.info("valueBound() was invoke...");
}
}
[*] 3.3 Servlet Request Events
package com.invicme.apps.shiro.listener.request;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about requests coming into and going out of scope of a web application.
*/
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
private static final Logger logger = Logger.getLogger(MyServletRequestListener.class);
/**
* Default constructor.
*/
public MyServletRequestListener() {
logger.info("MyServletRequestListener() was invoke...");
}
// 每次Http请求都是一个request,方法调用一次
public void requestInitialized(ServletRequestEvent sre){
logger.info("requestInitialized() was invoke...");
}
// 一次request请求执行完毕
public void requestDestroyed(ServletRequestEvent sre){
logger.info("requestDestroyed() was invoke...");
}
}
package com.invicme.apps.shiro.listener.request;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about ServletRequest attribute changes.
*/
@WebListener
public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
private static final Logger logger = Logger.getLogger(MyServletRequestAttributeListener.class);
/**
* Default constructor.
*/
public MyServletRequestAttributeListener() {
logger.info("MyServletRequestAttributeListener() was invoke...");
}
public void attributeAdded(ServletRequestAttributeEvent srae){
logger.info("attributeAdded() was invoke...");
}
public void attributeReplaced(ServletRequestAttributeEvent srae){
logger.info("attributeReplaced() was invoke...");
}
public void attributeRemoved(ServletRequestAttributeEvent srae){
logger.info("attributeRemoved() was invoke...");
}
}
4、Listener监听测试Servlet
package com.invicme.apps.shiro.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import com.invicme.apps.shiro.listener.session.MyHttpSessionBindingListener;
/**
* @author lucl
*/
@WebServlet("/httpServlet")
public class MyHttpServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(MyHttpServlet.class);
public MyHttpServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Servlet Context Attribute Event
{
ServletContext servletContext = request.getServletContext();
// attributeAdded
logger.info("=============servletContext.setAttribute");
servletContext.setAttribute("sc_name", "sc_value");
logger.info("=============servletContext.attributeReplaced");
servletContext.setAttribute("sc_name", "sc_value");
logger.info("=============servletContext.removeAttribute");
servletContext.removeAttribute("sc_name");
}
// Session Event
{
logger.info("=============request.getSession()=>sessionCreated");
HttpSession session = request.getSession();
logger.info("=============session.setAttribute()");
session.setAttribute("s_name", "s_value");
logger.info("=============session.attributeReplaced()");
session.setAttribute("s_name", "s_value");
logger.info("=============session.removeAttribute()");
session.removeAttribute("s_name");
// 实现HttpSessionBindingListener接口的对象被绑 定到session时触发valueBound事件,解除绑定时触发valueUnbound事件。
MyHttpSessionBindingListener bindingListener = new MyHttpSessionBindingListener();
logger.info("=============session.setAttribute(\"bind\", bindingListener)");
session.setAttribute("bind", bindingListener);
logger.info("=============session.removeAttribute(\"bind\")");
session.removeAttribute("bind");
logger.info("=============session.invalidate()=>sessionDestroyed");
session.invalidate();
}
// Request Event
{
logger.info("=============request.setAttribute()");
request.setAttribute("r_name", "r_value");
logger.info("=============request.attributeReplaced()");
request.setAttribute("r_name", "r_value");
logger.info("=============request.removeAttribute()");
request.removeAttribute("r_name");
}
}
}
页:
[1]