14. The use of listener in SpringBoot

Keywords: Programming Session Database Spring

1.1 introduction to monitor

What is a web listener? A web listener is a special class in a Servlet that helps developers listen to specific events in the web, such as ServletContext, 
Httpsession, creation and destruction of ServletRequest, creation, destruction and modification of variables can be added before and after certain actions to realize monitoring

1.2 example of monitor

There are many usage scenarios of web listener, such as listening to servlet context to initialize some data, listening to http session to obtain the current number of people online and listening to customers
 In this section, we mainly learn about Spring Boot through these three actual use scenarios 
Use of the monitor in

1.2.1 listening to Servlet context object

Listening servlet context object can be used to initialize data and cache. What do you mean? I take a very common scenario, for example, when a user clicks the homepage of a site,
Generally, some information of the homepage will be displayed, and the information will remain unchanged basically or most of the time, but the information is from the database. If the user's
 Click to get data from the database. If the number of users is small, it is acceptable. If the number of users is very large, it is also a big expense for the database

For this kind of homepage data, if most of them are not updated frequently, we can cache them completely. Every time a user clicks, we take them directly from the cache, so that we can
 If you are more flexible, you can add a timer to update the homepage cache regularly. It is similar to 
CSDN personal blog home page ranking changes the same

Next, we will write a demo for this function. In practice, readers can fully apply this code to realize the relevant logic of their own project. First, write a Service module
 To query data from the database
@Service  
public class UserService {  
  
    User getUser(){  
        return new User(1, "lwh", 25);  
    }  
}
Then write a listener, implement the applicationlistener < contextrefreshedevent > interface, rewrite the onApplicationEvent method, and
 The ContextRefreshedEvent object is passed in. If we want to refresh our preloaded resources when loading or refreshing the application context, we can
 To do this by listening to the ContextRefreshedEvent, as follows:
@Component  
public class MyServletContextListener implements ApplicationListener<ContextRefreshedEvent> {  
  
    @Override  
    public void onApplicationEvent(ContextRefreshedEvent event) {  
        // Get the applicationContext context first  
       ApplicationContext ctx = event.getApplicationContext();  
       UserService userService = ctx.getBean(UserService.class);  
       User user = userService.getUser();  
       // Get the application domain object and put it into the application domain  
       ServletContext application = ctx.getBean(ServletContext.class);  
       application.setAttribute("user", user);  
   }  
}
As described in the note, first get the application context through contextRefreshedEvent, and then get it through the application context
 The user service bean can get other beans according to the actual business scenario in the project, and then call your own business code to get the corresponding data,
Finally, it is stored in the application domain, so that when the front-end requests the corresponding data, we can directly obtain information from the application domain and reduce the pressure of the database 
Next write a Controller to get user information directly from the application domain to test
@Controller  
public class ListenerController {  
  
    @GetMapping("/listener/user")  
    @ResponseBody  
    public User getUser(HttpServletRequest request){  
        ServletContext application = request.getServletContext();  
        return (User) application.getAttribute("user");  
    }  
}
// Source code analysis
// Check for listener beans and register them.  
// In the Refresh method, this step registers the listener we defined into the container
registerListeners();  
  
// Instantiate all remaining (non-lazy-init) singletons.  
finishBeanFactoryInitialization(beanFactory);  
  
// Last step: publish corresponding event.  
// The ContextRefreshedEvent event will be published here, and our custom listener can get it
finishRefresh();
// registerListeners();  
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);  
for (String listenerBeanName : listenerBeanNames) {  
    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);  
}
protected void finishRefresh() {  
  
    // Publish the final event.  
    // Delete other code, and the event will be published in it, and our customized listening method will be called. For details, see the second listener mode
    publishEvent(new ContextRefreshedEvent(this));  
}

1.2.2 listening to HTTP Session object

There is also a common place for listeners to monitor session object,To get the number of online users,Many developers now have their own websites,Monitor 
session To get the current number of users is a very common use scenario,Here's how to use it.

@Component
public class MyHttpSessionListener implements HttpSessionListener {  
  
  // Record the number of online users  
  public Integer count = 0;  
  
  @Override
  public void sessionCreated(HttpSessionEvent httpSessionEvent) {  
      System.out.println("The user is online");  
      count++;  
      HttpSession session = httpSessionEvent.getSession();  
      session.setMaxInactiveInterval(1);  
      session.getServletContext().setAttribute("count", count);  
  }  
  
  @Override
  public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {  
      System.out.println("The user is offline");  
      count--;  
      httpSessionEvent.getSession().getServletContext().setAttribute("count", count);  
  }  
}

// Let the server remember the original session, that is, record the original sessionId in the browser, and transfer the sessionId to the next time you open it,
// So the server won't be recreated
@GetMapping("/listener/total2")  
@ResponseBody  
public String getTotalUser(HttpServletRequest request, HttpServletResponse response){  
    Cookie cookie;  
    try {  
        cookie = new Cookie("JSESSIONID", URLEncoder.encode(request.getSession().getId(), "UTF-8"));  
        cookie.setPath("/");  
        // Valid for two days  
        cookie.setMaxAge(48 * 60 * 60);  
        response.addCookie(cookie);  
    } catch (UnsupportedEncodingException e) {  
        e.printStackTrace();  
    }  
    Integer count = (Integer) request.getSession().getServletContext().getAttribute("count");  
    return "Current online population: " + count;  
}

1.3. Custom listener

In actual projects, we often need to customize some events and listeners to meet business scenarios. For example, in microservice, there will be A scenario: microservice A processes some logic,
Microservice B needs to be informed to process another logic, or microservice A needs to synchronize data to microservice B after processing A logic. This is A very common scenario. At this time,
We can customize events and listeners to monitor. Once an event in microservice A is detected, microservice B will be notified to process the corresponding logic
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;  
    }  
}
@Component  
public class MyEventListener implements ApplicationListener<MyEvent> {  
  
    @Override  
    public void onApplicationEvent(MyEvent event) {  
        // Get information about the event  
        User user = event.getUser();  
        // Handling events, notifying other microservices or handling other logic in the actual project, etc  
        System.out.println("User name: " + user.getName());  
        System.out.println("Age:" + user.getAge());  
    }  
}
@Service  
public class UserService {  
  
    @Resource  
    private ApplicationContext ctx;  

    User publishEvent(){  
        User user = new User(1, "lwh", 25);  
        // Release events  
        MyEvent myEvent = new MyEvent(this, user);  
        ctx.publishEvent(myEvent);  
        return user;  
    }  
}

Posted by avario on Sat, 22 Feb 2020 21:52:50 -0800