“This is the 14th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
First, the listener
1.1 define
Servlet listeners are a special class defined in the Servlet specification that listens for creation and destruction events of domain objects such as ServletContext, HttpSession, and ServletRequest, as well as for property changes in these domain objects. A listener is an application of the watcher mode, which focuses on a particular thing and waits for its chance, so it has the asynchronous nature of the listener.
The Servlet Listener listens for creation and destruction events of three domain objects:
- ServletContext: Application level. There is only one application and you can configure the application globally.
- HttpSession: Session level, for each session, such as counting the total number of sessions.
- ServletRequest: Request level, for each customer request,
1.2 Application Scenarios
The function of Servlet specification design listener is to do some processing before and after the event occurs. Generally, it can be used to count the number of online people and users, count the number of visits to the website, and initialize the information when the system starts. We can initialize Log4j information at container startup, add our own monitoring of container state, initialize Spring components, and so on.
1.3 Implementation of listener
Create a ServletRequest listener (other listeners are created similarly)
@WebListener
@Slf4j
public class Customlister implements ServletRequestListener{
@Override
public void requestDestroyed(ServletRequestEvent sre) {
log.info("Request Listener: Destroy");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
log.info("Request listener: This is where you can log the number of visits."); }}Copy the code
Add @ServletComponentScan to the startup class for automatic registration.
Two, filter
2.1 define
A filter is reusable code that transforms HTTP request, response, and header information. In layman’s terms, a filter preprocesses the request header before it reaches the server and postprocesses the response from the server before the response content reaches the client. Given this definition, it is easy to understand why it is downstream of the Listener, upstream of the Servlet. The filter must be processed after the container is started and the request is received, so it is executed after the Listener; The request is preprocessed before it reaches the Servlet, so it is in the position before the Servlet. In terms of its name, it filters the data content of requests and responses. It does not receive all data sent from the front end, but filters the data in principle to ensure the security of back-end server services.
2.2 Application Scenarios
Servlet 3.1 defines several common filter components:
The filter | role |
---|---|
The Authentication filters: | Authorization classes, such as user login session verification; |
Logging and auditing filters: | Log and security audit classes; |
Image conversion filters: | Picture conversion; |
Data compression will filters: | Data compression; |
Encryption filters: | Encryption, decryption class; |
Tokenizing filters: | Lexical classes; |
Filters that trigger resource access events: | Trigger resource access event class; |
XSL/T filters that transform XML content: | XML file conversion class; |
MIME -type chain filters: | MIME file; |
Caching filters: | The cache class; |
Or the kind of sensitive word filtering that we often need in social applications. The main feature of a filter is its ability to change the requested content.
2.3 Implementation of filters
The Filter is a useful technique for servlets. Filters can be used to intercept requests. For example, session can be read to determine whether a user logs in and whether the accessed request URL has access permission (blacklist and whitelist). The main thing is that requests can be preprocessed. Here’s how to implement filters in SpringBoot.
1.1 Implementation Method 1: Use WebFilter annotations for configuration
@webfilter is a new annotation in Servlet3.0. It was originally implemented in web.xml to configure filters, but now it is automatically scanned and registered when starting up.
Write the Filter class:
// The name of the registry is customFilter, and the intercepted url is all
@WebFilter(filterName="customFilter",urlPatterns={"/*"})
@Slf4j
public class CustomFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("Filter initialization");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
log.info("Before customFilter request is processed");
// Perform some preprocessing on request and response
// Set the request encoding
// request.setCharacterEncoding("UTF-8");
// response.setCharacterEncoding("UTF-8");
// The link passes directly to the next filter
chain.doFilter(request, response);
log.info("After the customFilter request is processed");
}
@Override
public void destroy(a) {
log.info("Filter destroyed"); }}Copy the code
Then add the @ServletComponentScan annotation to the bootstrap class. In this way, when multiple filters are registered, the Order of execution cannot be specified. Originally, the Order of execution can be specified when the web. XML filter is configured, but the @webFilter does not have this configuration attribute (it needs to be carried out together with @ORDER). So let’s look at registering filters with FilterRegistrationBean.
– Tip – Use the Java class name of the filter to specify the order of the convention, such as LogFilter and AuthFilter. In this case, the AuthFilter is executed before LogFilter because the first letter is A before L.
1.2. Is FilterRegistrationBean springboot FilterRegistrationBean way, these provide setOrder method, sorting value can be set for the filter, Have Spring sort web Filters before registering them and then register them in sequence. The first thing I need to do is rewrite filter, except for the @webFilter annotation. Nothing else has changed. FilterRegistrationBean is registered with @Bean in the launch class
@Configuration
public class FilterRegistration {
@Bean
public FilterRegistrationBean filterRegistrationBean(a) {
FilterRegistrationBean registration = new FilterRegistrationBean();
// When the filter has injected other bean classes, the entity class filter can be directly injected via @bean, so that the other bean classes used by the filter cannot be automatically injected.
// Of course, if no other beans need to be fetched, you can either directly new CustomFilter() or use getBean.
registration.setFilter(customFilter());
// Filter name
registration.setName("customFilter");
// Intercept the path
registration.addUrlPatterns("/ *");
// Set the sequence
registration.setOrder(10);
return registration;
}
@Bean
public Filter customFilter(a) {
return newCustomFilter(); }}Copy the code
When you register multiple FilterRegistrationBeans, you simply register multiple FilterRegistrationBeans, and when started, the effect is the same as the first one.
Third, the servlet
3.1 definition:
When Java programmers did Web development 10 years ago, all requests were received and responded to by servlets. For each request, you write a servlet. This approach is cumbersome, and people want to be able to map to different methods based on the request path and parameters, so that multiple requests can be handled in a servlet class, each request is a method. This idea was later developed into structs, SpringMVC.
3.2 Application Scenarios
Currently, the scenarios used by servlets are fully covered by the springMVC architecture. However, it does not rule out the case that old projects need to support servlets when migrating to Spring Boot projects.
3.3 implementation
Let’s take a look at how servlets are implemented in Spring Boot.
@WebServlet(name = "firstServlet", urlPatterns = "/firstServlet") // mark it as servlet for the initiator to scan.
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().append("firstServlet"); }}Copy the code
Then add the @ServletComponentScan annotation to the bootstrap class.
4. Interceptor
4.1 define
There is no concept of an interceptor in the Servlet specification, but it is an application of section-oriented programming: in scenarios where methods need to be enhanced, such as executing a piece of code before a method is called, or performing an additional operation after the method is completed, an interceptor is implemented as a dynamic proxy. I find it pointless to compare filters and interceptors together, they are fundamentally different concepts and not comparable, they are downstream of filters and are servlet-oriented.
4.2 Application Scenarios
AOP programming ideas deal with horizontal dimensions, not vertical business. To take a simple example, in the process of each method, in addition to the business logic, we will have some same operations: parameter verification, log printing, etc. Although these processing code is not much, but each method has to write this kind of thing, the workload is not small. Is it possible to use a program to integrate such operations without the programmer writing them by hand? This is where the idea of faceted programming is applied, using Java proxies to add some additional enhancements before or after the actual methods are called.
4.3 Implementation of interceptor
The above filters and listeners all belong to the Servlet API. We can also use the HandlerInterceptor provided by Spring for more detailed control when we use the above to filter Web requests.
Write custom interceptor classes
@Slf4j
public class CustomHandlerInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
log.info("PreHandle: call before request");
// Interrupt if false is returned
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("PostHandle: Call after request");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("AfterCompletion: Callback method after request invocation, that is, after view rendering is complete."); }}Copy the code
Register the interceptor by inheriting the WebMvcConfigurerAdapter. The WebMvcConfigurerAdapter class has been deprecated. Implement the WebMvcConfigurer interface to register the interceptor.
@Configuration
Public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter{public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter{
public class MyWebMvcConfigurer implements WebMvcConfigurer
@Override
public void addInterceptors(InterceptorRegistry registry) {
// Register the interceptor rule
// Multiple interceptors are executed in this order
registry.addInterceptor(getHandlerInterceptor()).addPathPatterns("/ *");
}
@Bean
public static HandlerInterceptor getHandlerInterceptor(a) {
return newCustomHandlerInterceptor(); }}Copy the code
Custom event and custom listener classes
Custom events: inherit from the ApplicationEvent abstract class and then define your own constructor custom listeners: implement the ApplicationListener interface and then implement the onApplicationEvent method
There are four ways for SpringBoot to listen for events: 1. Manually add listener 2 to ApplicationContext. Load listeners into the Spring container. 3. Configure listener 4 in application.properties. Implement event listening via the @EventListener annotation
5.1 Code implementation
Here are the concrete implementations of the four kinds of event listening
Methods 1.
Start by creating the MyListener1 class
@Slf4j
public class MyListener1 implements ApplicationListener<MyEvent> {
public void onApplicationEvent(MyEvent event) {
log.info(String.format("%s listening on event source: %s.", MyListener1.class.getName(), event.getSource())); }}Copy the code
Then in springboot application startup class for ConfigurableApplicationContext context, load monitoring
@SpringBootApplication
public class BootLaunchApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(BootLaunchApplication.class, args);
// Load listener
context.addApplicationListener(newMyListener1()); }}Copy the code
Method 2 (recommended).
Create the MyListener2 class and load it into the Spring container using the @Component annotation
@Component
@Slf4j
public class MyListener2 implements ApplicationListener<MyEvent> {
public void onApplicationEvent(MyEvent event) {
log.info(String.format("%s listening on event source: %s.", MyListener2.class.getName(), event.getSource())); }}Copy the code
3.
Start by creating the MyListener3 class
@Slf4j
public class MyListener3 implements ApplicationListener<MyEvent> {
public void onApplicationEvent(MyEvent event) {
log.info(String.format("%s listening on event source: %s.", MyListener3.class.getName(), event.getSource())); }}Copy the code
Then configure the listener in application.yml
context:
listener:
classes: club.krislin.customlistener.MyListener3
Copy the code
Method 4 (recommended).
Create the MyListener4 class that does not need to implement the ApplicationListener interface and decorates the concrete methods with @EventListener
@Slf4j
@Component
public class MyListener4 {
@EventListener
public void listener(MyEvent event) {
log.info(String.format("%s listening on event source: %s.", MyListener4.class.getName(), event.getSource())); }}Copy the code
Custom event codes are as follows:
@SuppressWarnings("serial")
public class MyEvent extends ApplicationEvent
{
public MyEvent(Object source)
{
super(source); }}Copy the code
5.2 test listening event release
Given the applicationContext, can you publish events wherever you want
@RunWith(SpringRunner.class)
@SpringBootTest
public class CustomListenerTest {
@Resource private
ApplicationContext applicationContext;
@Test
public void testEvent(a){
applicationContext.publishEvent(new MyEvent("Test event.")); }}Copy the code
After the startup, logs are displayed as follows: (The following screenshot is taken after the event of launching the class. In the unit test, listener 1 fails to listen and the execution sequence is out of order) :
It can be seen from the log printing that the implementation of SpringBoot’s four events is orderly. It doesn’t matter how many times you do it.
summary
We’ve covered listeners, filters, servlets, interceptors, and the # custom event and custom listener classes. By learning about the above operations, you can accomplish some special scenarios.