目录
1、Spring Boot 监听器类型
1.1监听 Servlet 上下文对象
1.2监听 HTTP 会话 Session 对象
1.3 监听客户端请求 Servlet Request 对象
2、Spring Boot 中自定义事件监听
2.1自定义事件
2.2自定义监听器
Web 监听器的使用场景很多,比如监听 Servlet 上下文用来初始化一些数据、监听 HTTP Session 用来获取当前在线的人数、监听客户端请求的 ServletRequest 对象来获取用户的访问信息等。
监听 Servlet 上下文对象可以用来初始化数据,用于缓存。demo如下所示:
首先写一个 Service,模拟一下从数据库查询数据:
@Service
public class UserService {
/**
* 获取用户信息
* @return
*/
public User getUser() {
// 实际中会根据具体的业务场景,从数据库中查询对应的信息
return new User(1L, "Jack", "123456");
}
}
然后写一个监听器,实现 ApplicationListener 接口,重写 onApplicationEvent 方法,将 ContextRefreshedEvent 对象传进去。如果我们想在加载或刷新应用上下文时,也重新刷新下我们预加载的资源,就可以通过监听 ContextRefreshedEvent 来做这样的事情。代码如下:
@Component
public class WebContextListener implements ApplicationListener {
private static final Logger logger= LoggerFactory.getLogger(WebContextListener.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// 先获取到 application 上下文
ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
// 获取对应的 service
UserService userService = applicationContext.getBean(UserService.class);
User user = userService.getUser();
// 获取 application 域对象,将查到的信息放到 application 域中
ServletContext application = applicationContext.getBean(ServletContext.class);
application.setAttribute("user", user);
}
}
监听器还有一个比较常用的地方,就是用来监听 Session 对象,以获取在线用户数量。
**
* 使用 HttpSessionListener 统计在线用户数的监听器
* @author shengwu ni
* @date 2018/07/05
*/
@Component
public class MyHttpSessionListener implements HttpSessionListener {
private static final Logger logger = LoggerFactory.getLogger(MyHttpSessionListener.class);
/**
* 记录在线的用户数量
*/
public Integer count = 0;
@Override
public synchronized void sessionCreated(HttpSessionEvent httpSessionEvent) {
logger.info("新用户上线了");
count++;
httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
}
@Override
public synchronized void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
logger.info("用户下线了");
count--;
httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
}
}
使用监听器获取用户的访问信息。
/**
* 使用 ServletRequestListener 获取访问信息
* @author shengwu ni
* @date 2018/07/05
*/
@Component
public class MyServletRequestListener implements ServletRequestListener {
private static final Logger logger = LoggerFactory.getLogger(MyServletRequestListener.class);
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
logger.info("session id为:{}", request.getRequestedSessionId());
logger.info("request url为:{}", request.getRequestURL());
request.setAttribute("name", "Jack");
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
logger.info("request end");
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
logger.info("request域中保存的name值为:{}", request.getAttribute("name"));
}
}
在实际项目中,我们往往需要自定义一些事件和监听器来满足业务场景,比如在微服务中会有这样的场景:微服务 A 在处理完某个逻辑之后,需要通知微服务 B 去处理另一个逻辑,或者微服务 A 处理完某个逻辑之后,需要将数据同步到微服务 B。这种场景非常普遍,这时我们可以自定义事件以及监听器来监听,一旦监听到微服务 A 中的某事件发生,就去通知微服务 B 处理对应的逻辑。
自定义事件需要继承 ApplicationEvent 对象,在事件中定义一个 User 对象来模拟数据,构造方法中将 User 对象传进来初始化。如下:
/**
* 自定义事件
* @author shengwu ni
* @date 2018/07/05
*/
public class MyEvent extends ApplicationEvent {
private User user;
public MyEvent(Object source, User user) {
super(source);
this.user = user;
}
// 省去 get、set 方法
}
接下来,自定义一个监听器来监听上面定义的 MyEvent 事件,自定义监听器实现 ApplicationListener 接口即可。如下:
/**
* 自定义监听器,监听 MyEvent 事件
* @author shengwu ni
* @date 2018/07/05
*/
@Component
public class MyEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(MyEvent myEvent) {
// 把事件中的信息获取到
User user = myEvent.getUser();
// 处理事件,实际项目中可以通知别的微服务或者处理其他逻辑等
System.out.println("用户名:" + user.getUsername());
System.out.println("密码:" + user.getPassword());
}
}
然后重写 onApplicationEvent 方法,将自定义的 MyEvent 事件传进来,因为该事件中,我们定义了 User 对象(该对象在实际中就是需要处理的数据,在下文来模拟),然后就可以使用该对象的信息了。
OK,定义好了事件和监听器之后,需要手动发布事件,这样监听器才能监听到,这需要根据实际业务场景来触发,针对本节课的例子,我写个触发逻辑,如下:
/**
* UserService
* @author shengwu ni
*/
@Service
public class UserService {
@Resource
private ApplicationContext applicationContext;
/**
* 发布事件
* @return
*/
public User getUser2() {
User user = new User(1L, "Jack", "123456");
// 发布事件
MyEvent event = new MyEvent(this, user);
applicationContext.publishEvent(event);
return user;
}
}
https://blog.csdn.net/taojin12/article/details/88338199