Analysis of Spring integrated web environment ContextLoaderListener listener

1, Integration of Spring and Web Environment

1. ApplicationContext application context acquisition method

  • Pass last time Spring integrated web environment - Construction of basic three-tier architecture environment In this article, we can learn that the application context object is obtained through the new ClasspathXmlApplicationContext(spring configuration file), but each time we get a Bean from the container, we have to write the new ClasspathXmlApplicationContext(spring configuration file). This disadvantage is that the configuration file is loaded many times and the application context object is created many times.
  • In the Web project, you can use ServletContextListener to monitor the startup of Web application. When the Web application starts, we can load the configuration file of Spring, create the application context object ApplicationContext, and store it in the largest domain servletContext domain, so that the application context ApplicationContext object can be obtained from the domain at any location.

2. Customize ContextLoaderLister

package com.itheima.listener;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener implements ServletContextListener {

    //contextInitialized method
    //As soon as the server starts, this method will be executed as long as it listens
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //Store the application context object of Spring in the ServletContext domain
        ServletContext servletContext = servletContextEvent.getServletContext();
        servletContext.setAttribute("app",app);
        System.out.println("spring Container creation completed...");
    }
    //Method of contextDestroyed context destruction
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}
  • Configure the web in src\main\webapp\WEB-INF XML, add listener listener
<!--Configure listener-->
<listener>
    <listener-class>com.itheima.listener.ContextLoaderListener</listener-class>
</listener>
  • At this time, if we run the tomcat server, we can see the results through the console, which means that the server is started at this time, but we will successfully create the spring container without access. If we access the server, we will not create it again. Just take it directly from the server.

3. Custom ContextLoaderLister code optimization ①

  • ❌❌❌ In the above file, we can see that ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); Is written dead, and ApplicationContext XML files are randomly named and can be named in other forms; It's just here that we conventionally name it ApplicationContext XML, in case we don't apply this name later, use other names; Then it won't work ❌❌❌
  • Therefore, we need to add ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); Extract to the configuration file
  • On the web Add the following configuration to the XML file
<!--Global tooth initialization parameters-->
<context-param>
    <param-name>contextConfigLocation</param-name><!--You can name any type-->
    <param-value>applicationContext.xml</param-value><!--Fill in the name of the profile-->
</context-param>
  • Then modify src\main\java.com itheima. Contextloaderlistener under listener package Java file
package com.itheima.listener;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener implements ServletContextListener {

    //contextInitialized method of context initialization
    //Once the server starts, this method will be executed as long as it listens
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();//👈 Extract the ServletContext first

        //👇 Then read the web Global parameters in XML
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");

        ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
        //Store the application context object of Spring in the ServletContext domain
        servletContext.setAttribute("app",app);
        System.out.println("spring Container creation completed...");
    }
    //Method of contextDestroyed context destruction
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {}
}

4. Custom ContextLoaderLister code optimization ②

  • In src\main\java file com itheima. Userservlet under Web package Java file
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
  • ❌❌❌ The "app" is also dead coupled, which makes us need to remember the app every time, and then create it in other files. ❌❌❌
  • In the src/main/java file com itheima. Create webapplicationcontextutils in the listener package Java tool class
package com.itheima.listener;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;

public class WebApplicationContextUtils {
    public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
        return (ApplicationContext) servletContext.getAttribute("app");
    }
}
  • In the src/main/java file com itheima. Modify userservlet in Web package Java file
package com.itheima.web;

import com.itheima.listener.WebApplicationContextUtils;
import com.itheima.service.UserService;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();

        //ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
        //👇 At this time, the specific string "app" has been replaced and decoupled ❗❗❗
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);

        UserService userService = app.getBean(UserService.class);
        userService.save();
    }
}
  • The above is our step-by-step understanding and implementation of the underlying encapsulation of the context acquisition tool provided by Spring, which is convenient for us to understand and master.
  • Next, we can directly use the tool for obtaining application context automatically provided by Spring

5. Spring provides tools for obtaining application context

  • The above analysis does not need to be implemented manually. Spring provides a listener ContextLoaderListener, which encapsulates the above functions. The listener internally loads the spring configuration file, creates the application context object, and stores it in the ServletContext domain. It provides a client tool WebApplicationContextUtils for users to obtain the application context object.

  • So there are only two things we need to do:
    ① On the web Configure ContextLoaderListener listener in XML (import spring web coordinates)
    ② Get the application context using the webcontextutils object

(1) Coordinates of importing Spring integrated web

  • In POM Import coordinates from XML file
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

(2) Configure the ContextLoaderListener listener

  • On the web Configure listener in XML file
<!--Global parameters-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--Spring Monitor for-->
<listener>
	<listener-class>
       org.springframework.web.context.ContextLoaderListener
   </listener-class>
 </listener>

(3) Obtain the application context object through the tool

  • In the web layer code, the src\mian\java file contains com itheima. Userservlet in Web package Java file
ApplicationContext applicationContext =    
    WebApplicationContextUtils.getWebApplicationContext(servletContext);
    Object obj = applicationContext.getBean("id");
package com.itheima.web;

import com.itheima.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();

		//Call org springframework. web. context. The WebApplicationContextUtils tool class under the support package has been encapsulated for us by Spring
        ApplicationContext app = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);

        UserService userService = app.getBean(UserService.class);
        userService.save();
    }
}

Posted by jkurrle on Mon, 18 Apr 2022 10:20:07 +0930