目录
1.3 监听客户端请求 Servlet Request 对象
1、Spring Boot 监听器类型
Web 监听器的使用场景很多,比如监听 Servlet 上下文用来初始化一些数据、监听 HTTP Session 用来获取当前在线的人数、监听客户端请求的 ServletRequest 对象来获取用户的访问信息等。
1.1监听 Servlet 上下文对象
监听 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<ContextRefreshedEvent> {
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);
}
}
1.2监听 HTTP 会话 Session 对象
监听器还有一个比较常用的地方,就是用来监听 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);
}
}
1.3 监听客户端请求 Servlet Request 对象
使用监听器获取用户的访问信息。
/**
* 使用 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"));
}
}
2、Spring Boot 中自定义事件监听
在实际项目中,我们往往需要自定义一些事件和监听器来满足业务场景,比如在微服务中会有这样的场景:微服务 A 在处理完某个逻辑之后,需要通知微服务 B 去处理另一个逻辑,或者微服务 A 处理完某个逻辑之后,需要将数据同步到微服务 B。这种场景非常普遍,这时我们可以自定义事件以及监听器来监听,一旦监听到微服务 A 中的某事件发生,就去通知微服务 B 处理对应的逻辑。
2.1自定义事件
自定义事件需要继承 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 方法
}
2.2自定义监听器
接下来,自定义一个监听器来监听上面定义的 MyEvent 事件,自定义监听器实现 ApplicationListener 接口即可。如下:
/**
* 自定义监听器,监听 MyEvent 事件
* @author shengwu ni
* @date 2018/07/05
*/
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
@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;
}
}