例如:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);
userService.getUser();
}
这样导致的问题是频繁创建容器导致的性能低下,那么该如何解决这个问题呢?
在原生的servlet中,提供了接口ServletContextListener,我们可以将applicationContext容器放在web的最大作用域servletContext中,我们就可以在任意位置拿到spring上下文容器(Spring源码思想)
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("app",applicationContext);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ApplicationContext app =(ApplicationContext) servletContext.getAttribute("app");
UserService service = app.getBean(UserService.class);
service.getUser();
}
代码仍然存在的问题:
spring核心配置文件名称是由用户定义的,名称不确定applicationContext上下文在servletContext中的名称具有耦合性,用户在不查看源码的情况下无法知晓名称,不方便使用 解决方案 1.将spring核心配置文件名称提取到web.xml中
applicationContext applicationContext.xml
这些参数会在servlet作为初始化参数优先加载到servletContext中,通过initParam获取
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
String context = servletContext.getInitParameter("applicationContext");
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(context);
servletContext.setAttribute("app",applicationContext);
}
2.通过工具类的方式获取spring上下文对象,这样用户就无需知道在servletContext中applicationContext的名称是什么
package com.vmware.util;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
public class WebApplicationContextUtils {
public static ApplicationContext getContext(ServletContext context) {
return (ApplicationContext) context.getAttribute("app");
}
}
使用:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ApplicationContext applicationContext = WebApplicationContextUtils.getContext(servletContext);
UserService userService = applicationContext.getBean(UserService.class);
userService.getUser();
}
使用spring-web自带的监听器与上下文工具类
1.导入依赖
org.springframework spring-web 5.3.15
2.注册监听器,将applicationContext对象加载到servletContext全局上下文中
org.springframework.web.context.ContextLoaderListener
3.配置spring核心配置文件名称
contextConfigLocation classpath:applicationContext.xml
4.使用spring提供的WebApplicationContextUtils获取spring容器
package com.vmware.controller;
import com.vmware.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 UserControllerSpring extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(context);
UserService userService = applicationContext.getBean(UserService.class);
userService.getUser();
}
}



