首页 > 编程笔记 > Java笔记 阅读:1

Spring Boot监听器的用法(非常详细)

Web 监听器是 Servlet 中特殊的类,能帮助开发者监听 Web 中的一些特定事件,比如 ServletContext、HttpSession、ServletRequest 的创建和销毁,在某些动作前后增加处理,以及实现监控等。

按照监听对象,Web 监听器可分为三类:
Web 监听器的使用场景很多,比如监听 Servlet 上下文来初始化一些数据,监听 Session 会话获取当前系统在线人数,监听客户端请求的 ServletRequest 来获取用户的一些访问信息。

接下来我们将通过实际例子和实际场景讲解这三类监听器以及自定义监听器。

监听ServletContext对象

监听 ServletContext 对象主要用于初始化一些不经常改变的数据,比如网站首页的一些菜单信息、用户账号相关信息等,将这些数据存进 application 作用域中,在一定程度上会起到缓存的作用。

页面上使用数据的时候直接从 application 作用域获取,而不是每次获取数据都要从数据库中获取。如果用户量大,那么每次首页菜单加载对于数据库来说都是很大的一笔开销。

下面将针对首页展示用户账号信息这个场景,来对 ServletContext 监听器做实际讲解。

1) 模拟数据库查询用户信息,参考代码如下:
@Service
public class UserServiceImpl implements UserService {
    @Override
    public User getUser() {
        return new User(111L, "tudoudou", "aaa");
    }
}

2) 定义一个监听 ServletContext 的监听器,需要实现 ServletContextListener 接口,并且重写 onApplicationEvent 方法,参考代码如下:
/**
* Servlet上下文监听器
*/
@Component
public class ServletContextListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        // 获取 application 上下文信息
        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
        // 获取 userService 对象
        UserServiceImpl userServiceImpl = applicationContext.getBean(UserServiceImpl.class);
        User user = userServiceImpl.getUser();
        // 将获取的 user 对象放入 application 域中
        ServletContext applicationScope = applicationContext.getBean(ServletContext.class);
        applicationScope.setAttribute("user", user);
    }
}

3) 创建一个接口,从 application 作用域中获取初始化的 User 信息,返回到页面中,参考代码如下:
@GetMapping("/user")
public User getUser(HttpServletRequest request){
    ServletContext applicationScope = request.getServletContext();
    User user = (User)applicationScope.getAttribute("user");
    return user;
}

接口请求结果如下图所示:

监听HTTP会话Session对象

Web 监听器还有一个比较常用的作用就是监听 Session 对象,以统计当前Web应用在线用户总数量。下面将通过统计在线用户数量来具体讲解 Session 会话监听器。

1) 创建 Session 会话监听器,需要实现 HttpSessionListener 接口,并且按照自身需求重写 sessionCreated() 方法和 sessionDestroyed() 方法,参考代码如下:
/**
* httpSession 监听对象
*/
@Component
public class SessionListener implements HttpSessionListener {
    // 用于记录在线用户数量
    public static Integer count = 0;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("新用户上线!");
        count++;
        se.getSession().getServletContext().setAttribute("count", count);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("用户下线!");
        count--;
        se.getSession().getServletContext().setAttribute("count", count);
    }
}

2) 创建一个接口测试该监听器,参考代码如下:
@GetMapping("/countOnlineUser")
public String getOnlineUserCount(HttpServletRequest request, HttpServletResponse response) {
    Cookie cookie;
    try {
        // 将 sessionId 记录到浏览器中,防止在服务器找不到原有的用户信息,重新创建 session
        cookie = new Cookie("JSESSIONID", URLEncoder.encode(request.getSession().getId(), "utf-8"));
        cookie.setPath("/");
        // 设置 cookie 有效期为 1 天
        cookie.setMaxAge(24 * 60 * 60);
        response.addCookie(cookie);
    } catch (Exception e) {
        e.printStackTrace();
    }
    Integer count = (Integer) request.getSession().getServletContext().getAttribute("count");
    return "total user online:" + count;
}
测试结果如下图所示:

监听ServletRequest对象

监听客户端请求,主要是为了获取用户的一些请求信息,具体操作如下。

1) 创建监听 ServletRequest 对象的监听器,需要实现 ServletRequestListener 接口,按照自身需求重写 requestInitialized() 方法和 requestDestroyed() 方法,参考代码如下:
/**
* request 请求 listener,获取请求访问信息
*/
@Component
public class RequestListener implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("此次请求开始");
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        System.out.println("sessionId:" + request.getRequestedSessionId() + " url:" + request.getRequestURL());
        String username = (String) request.getAttribute("username");
        if (username == null) {
            request.setAttribute("username", "tudoudou");
        }
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("此次请求结束");
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        String username = (String) request.getAttribute("username");
        System.out.println("requestScope 中 username 为:" + username);
    }
}

2) 新增一个接口,测试 ServletRequest 对象的监听器,参考代码如下:
@GetMapping("/testRequest")
public String testRequest(HttpServletRequest request){
    String username = (String)request.getAttribute("username");
    System.out.println("init requestScope username:"+username);
    return "success";
}
测试结果如下图所示:


自定义监听器

实现自定义监听器需要做三步操作:
1) 自定义事件,参考代码如下:
/**
* 自定义监听事件
*/
public class MyEvent extends ApplicationEvent {
    private User user;

    public MyEvent(Object source, User user) {
        super(source);
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

2) 自定义监听器,参考代码如下:
/**
* 自定义监听器
*/
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent myEvent) {
        // 获取事件中的信息
        User user = myEvent.getUser();
        // 打印获取到的信息
        System.out.println("username:" + user.getUsername());
    }
}

3) 发布事件,参考代码如下:
/**
* User 用户 service 接口类实现类
*/
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private ApplicationContext applicationContext;
    @Override
    public User publishMyEvent() {
        User user = new User(100L, "doudou", "111");
        // 发布自定义事件
        MyEvent myEvent = new MyEvent(this, user);
        applicationContext.publishEvent(myEvent);
        return user;
    }
}

4) 创建接口测试自定义监听器,参考代码如下:
@GetMapping("/publish")
public User publishMyEvent(HttpServletRequest request) {
    return userService.publishMyEvent();
}

相关文章