java监听器模式使⽤场景_14、SpringBoot中监听器的使⽤1.1、监听器介绍
什么是web监听器? web监听器是⼀种Servlet中特殊的类,它们能帮助开发者监听web中特定的事件,⽐如ServletContext,
HttpSession,ServletRequest的创建和销毁. 变量的创建、销毁和修改等,可以在某些动作前后增加处理,实现监控
1.2、监听器使⽤例⼦
web 监听器的使⽤场景很多,⽐如监听 rvlet 上下⽂⽤来初始化⼀些数据、监听 http ssion ⽤来获取当前在线的⼈数、监听客
户端请求的 rvlet request 对象来获取⽤户的访问信息等等. 这⼀节中,我们主要通过这三个实际的使⽤场景来学习⼀下 Spring Boot
中监听器的使⽤.
1.2.1、监听Servlet上下⽂对象笔记本电脑壁纸
监听 rvlet 上下⽂对象可以⽤来初始化数据,⽤于缓存. 什么意思呢?我举⼀个很常见的场景,⽐如⽤户在点击某个站点的⾸页时,
⼀般都会展现出⾸页的⼀些信息,⽽这些信息基本上或者⼤部分时间都保持不变的,但是这些信息都是来⾃数据库. 如果⽤户的每次
点击,都要从数据库中去获取数据的话,⽤户量少还可以接受,如果⽤户量⾮常⼤的话,这对数据库也是⼀笔很⼤的开销.
针对这种⾸页数据,⼤部分都不常更新的话,我们完全可以把它们缓存起来,每次⽤户点击的时候,我们都直接从缓存中拿,这样既可以
提⾼⾸页的访问速度,⼜可以降低服务器的压⼒. 如果做的更加灵活⼀点,可以再加个定时器,定期的来更新这个⾸页缓存. 就类似与
馨而乐CSDN 个⼈博客⾸页中排名的变化⼀样.
下⾯我们针对这个功能,来写⼀个 demo,在实际中,读者可以完全套⽤该代码,来实现⾃⼰项⽬中的相关逻辑. ⾸先写⼀个 Service,模
拟⼀下从数据库查询数据
@Service
public class UrService {
Ur getUr(){
return new Ur(1, "lwh", 25);
}
}
然后写⼀个监听器,实现ApplicationListener接⼝,重写onApplicationEvent⽅法,将
ContextRefreshedEvent对象传进去. 如果我们想在加载或刷新应⽤上下⽂时,也重新刷新下我们预加载的资源,就可
以通过监听ContextRefreshedEvent来做这样的事情.如下:
@Component
public class MyServletContextListener implements ApplicationListener {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 先获取到applicationContext上下⽂
ApplicationContext ctx = ApplicationContext();
UrService urService = Bean(UrService.class);
Ur ur = Ur();
// 获取application域对象,将其放⼊application域中
ServletContext application = Bean(ServletContext.class);
application.tAttribute("ur", ur);
}
}
正如注释中描述的⼀样,⾸先通过contextRefreshedEvent来获取application上下⽂,再通过application上下⽂来获取UrService这个bean,项⽬中可以根据实际业务场景,也可以获取其他的bean,然后再调⽤⾃⼰的业务代码获取相应的数据,最后存储到application域中,这样前端在请求相应数据的时候,我们就可以直接从application域中获取信息,减少数据库的压⼒.下⾯写⼀个Controller直接从application域中获取ur信息来测试⼀下.
雪克来提扎克尔@Controller
public class ListenerController {
@GetMapping("/listener/ur")
@ResponBody
public Ur getUr(HttpServletRequest request){
ServletContext application = ServletContext();
return (Ur) Attribute("ur");
}
}
// 源码分析
// Check for listener beans and register them.
// 在Refresh⽅法中,这⼀步会将我们定义的监听器注册到容器中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 这⾥⾯会发布ContextRefreshedEvent事件,我们⾃定义的监听器就可以获取到了
finishRefresh();
// registerListeners();
阅兵观后感
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, fal);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
protected void finishRefresh() {
// Publish the final event.
// 删掉其他代码,这⾥⾯发布事件,会调⽤到我们⾃定义的监听⽅法,具体可以看第⼆篇监听器模式
publishEvent(new ContextRefreshedEvent(this));
}记事本怎么打开
1.2.2、监听HTTP会话Session对象
监听器还有⼀个⽐较常⽤的地⽅就是⽤来监听 ssion 对象,来获取在线⽤户数量,现在有很多开发
者都有⾃⼰的⽹站,监听ssion 来获取当前在下⽤户数量是个很常见的使⽤场景,下⾯来介绍⼀下如何来使⽤.
@Component
public class MyHttpSessionListener implements HttpSessionListener {
// 记录在线⽤户数量
public Integer count = 0;
@Override
public void ssionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("⽤户上线了");
count++;
HttpSession ssion = Session();
ssion.tMaxInactiveInterval(1);
}
@Override
public void ssionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("⽤户下线了");
count--;
}
}
// 让服务器记得原来那个ssion,即把原来的ssionId记录在浏览器中,下次再打开时,把这个 ssionId 传过去,负什么顽抗
// 这样服务器就不会重新再创建了
@GetMapping("/listener/total2")
@ResponBody
public String getTotalUr(HttpServletRequest request, HttpServletRespon respon){
Cookie cookie;
try {
cookie = new Cookie("JSESSIONID", Session().getId(), "UTF-8"));
cookie.tPath("/");
// 有效期设置两天
cookie.tMaxAge(48 * 60 * 60);
respon.addCookie(cookie);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Integer count = (Integer) Session().getServletContext().getAttribute("count");
return "当前在线⼈数: " + count;
}
1.3、⾃定义监听器
在实际项⽬中,我们往往需要⾃定义⼀些事件和监听器来满⾜业务场景,⽐如在微服务中会有这样的场景:微服务 A 在处理完某个逻辑之后,需要通知微服务 B 去处理另⼀个逻辑,或者微服务 A 处理完某个逻辑之后,需要将数据同步到微服务 B,这种场景⾮常普遍,这个时候,
我们可以⾃定义事件以及监听器来监听,⼀旦监听到微服务 A 中的某事件发⽣,就去通知微服务 B 处理对应的逻辑.什么是数量关系
public class MyEvent extends ApplicationEvent {
private Ur ur;
public MyEvent(Object source, Ur ur) {
super(source);
this.ur = ur;
}
public Ur getUr() {
坐便堵了怎么办return ur;
}
public void tUr(Ur ur) {
this.ur = ur;
}
}
@Component
public class MyEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(MyEvent event) {
// 把事件的信息获取到
Ur ur = Ur();
// 处理事件,实际项⽬中可以通知别的微服务或者处理其他逻辑等等
System.out.println("⽤户名: " + ur.getName());
System.out.println("年龄:" + ur.getAge());
}
}
@Service
public class UrService {
@Resource
private ApplicationContext ctx;
Ur publishEvent(){
Ur ur = new Ur(1, "lwh", 25);
// 发布事件
MyEvent myEvent = new MyEvent(this, ur); ctx.publishEvent(myEvent);
return ur;
}
}