Spring framework learning record 6 integrating Junit and Web Environment

Keywords: Java Spring Spring Boot

Integrated Junit:

Example:

(1) Import dependent

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.5.RELEASE</version>
    <scope>test</scope>
</dependency>

It should be noted that the version of spring test should be consistent with the previously introduced version of spring context

(2) Create test class SpringJunitTest

import Service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringJunitTest {

	@Autowired
	private UserService userService;

	@Test
	public void test1() {
		userService.say();
	}

}

@RunWith(SpringJUnit4ClassRunner.class) is used to let the test execute in the Spring container environment

@ContextConfiguration is used to specify xml configuration files or configuration classes, as follows

@ContextConfiguration(locations = "classpath:applicationContext.xml")
@ContextConfiguration(classes = SpringConfiguration.class)

analysis:  

After Spring integrates Junit, unit testing can be carried out in the above way. The program automatically creates a Spring container. We only need to inject the bean s to be tested through @ Autowired annotation

Integrated Web environment:

Example:

(1) Create the Web layer and write the UserServlet class

 

package Web;

import Config.SpringConfiguration;
import Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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 {
		ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
		UserService userService = app.getBean(UserService.class);
		userService.say();
	}

}

Override the doGet method to create a Spring container, get the Service layer object userService, and call its say method

(2) Configuring servlet mapping in web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>UserServlet</servlet-name>
        <servlet-class>Web.UserServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>UserServlet</servlet-name>
        <url-pattern>/userServlet</url-pattern>
    </servlet-mapping>

</web-app>

Map the access path to the corresponding servlet

(3) Test by visiting localhost:8080/userService in the browser

Start Tomcat and access it in the browser   localhost:8080/userService

The console successfully outputs the results

Disadvantages analysis:

When there are many interfaces in the Web layer, a Spring container needs to be created in the processing method of each servlet, resulting in the configuration file / class being loaded many times and the Spring container being created many times, affecting the performance

Solution:

In the Web project, use the ServletContextListener to listen to the start of the Web application. When the Web application starts, create an ApplicationContext object and store it in the servletContext field, so as to access the ApplicationContext object anywhere

(1) Create listener ContextLoaderListener

package Listener;

import Config.SpringConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener implements ServletContextListener {

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
		sce.getServletContext().setAttribute("app", app);
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {

	}
}

The listener class implements the ServletContextListener interface and overrides the contextInitialized method, which will be called when the Web application starts. The Spring container is created in the method and stored in the servletContext domain

(2) Configuring listeners in web.xml

<listener>
    <listener-class>Listener.ContextLoaderListener</listener-class>
</listener>

(3) In the doGet method of UserServlet class, obtain the ApplicationContext object through the servletContext field

package Web;

import 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");
		UserService userService = app.getBean(UserService.class);
		userService.say();
	}

}

There are two ways to obtain ServletContext objects

ServletContext servletContext = req.getServletContext();
ServletContext servletContext = this.getServletContext();

Profile decoupling:

For the creation of ApplicationContext in the listener, you need to specify the configuration file. You can configure the global parameter in web.xml and specify the configuration file as the global parameter to realize the decoupling of the configuration file

(1) Configuring global parameters in web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>applicationContext.xml</param-value>
</context-param>

(2) Get the parameters in the listener and create the ApplicationContext object

public void contextInitialized(ServletContextEvent sce) {
	ServletContext servletContext = sce.getServletContext();
	String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
	ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
	sce.getServletContext().setAttribute("app", app);
}

The global parameters can be obtained through the getInitParameter method of the ServletContext object

Get ApplicationContext optimization

(1) Write the tool class WebApplicationContextUtils

package Util;

import org.springframework.context.ApplicationContext;

import javax.servlet.ServletContext;

public class WebApplicationContextUtils {
	public static ApplicationContext getWebApplicationContext(ServletContext servletContext) {
		return (ApplicationContext) servletContext.getAttribute("app");
	}
}

For the static method getWebApplicationContext, just pass in the ServletContext to return the ApplicationContext object

(2) Modify the access to ApplicationContext in the doGet method

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	ServletContext servletContext = this.getServletContext();
	ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
	UserService userService = app.getBean(UserService.class);
	userService.say();
}

Directly call the static method of WebApplicationContextUtils to obtain the ApplicationContext object

Use Spring tools to obtain ApplicationContext objects:

For the created above   ContextLoaderListener, WebApplicationContextUtils and Spring provide exactly the same functions and are encapsulated in the Spring web package

(1) Import dependent

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>

  Note that the version of Spring web needs to be the same as that of other Spring packages imported earlier

(2) Configuring listener and profile global parameters in web.xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

  The configuration file path here needs to be added with classpath

(3) Get the ApplicationContext object using WebApplicationContextUtils

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	ServletContext servletContext = this.getServletContext();
	ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
	UserService userService = app.getBean(UserService.class);
	userService.say();
}

Posted by vlcinsky on Sun, 19 Sep 2021 04:21:26 -0700