前期我们已经创建了监听器,为解决在每次调用Servlet时重复创建决配置文件的问题。
监听器代码如下
public class ContextLoaderListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext app = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//将spring存入servletcontext域
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("app",app);
System.out.println("Spring容器创建完毕.......");
}
public void contextDestroyed(ServletContextEvent sce) {
}
}
web层代码如下
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ApplicationContext app = new ClassPathXmlApplicationContext("ApplicationContext.xml");
ServletContext servletContext = req.getServletContext();
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
UserService userService = app.getBean(UserService.class);
userService.save();
}
}
但ApplicationContext未完成与监听器的解耦,于是我们在xml中引入全局初始化参数
1.修改web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>ApplicationContext.xml</param-value>
</context-param>
2.修改监听器
public class ContextLoaderListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
//读取web.xml中的全局参数
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
//将已有的ApplicationContext传入new中,实现解耦
ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
//将spring存入servletcontext域
servletContext.setAttribute("app",app);
System.out.println("Spring容器创建完毕.......");
}
public void contextDestroyed(ServletContextEvent sce) {
}
}
如此实现了ApplicationContext与监听器的解耦
进一步,为解决每一个服务需要记住attribute名字的问题,我们对代码进行优化,建立了一个工具类完成ApplicationContext的调取,并在Servlet直接调取这个工具类的方法
1.创建工具类如下
public class WebApplicationContextUtils {
public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
return (ApplicationContext) servletContext.getAttribute("app");
}
}
2.Servlet引用如下
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ApplicationContext app = new ClassPathXmlApplicationContext("ApplicationContext.xml");
ServletContext servletContext = req.getServletContext();
// ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
}
}
以上优化无需手动书写,Spring已经提供了监听器对上述功能进行封装(写到这我才知道Spring有了这个功能,淦!)
只需三步
1.在pom.xml中加载spring-web
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
2.在web.xml中配置ContextLoaderListener
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
3.使用WebApplicationContextUtils获得应用上下文
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ApplicationContext app = new ClassPathXmlApplicationContext("ApplicationContext.xml");
ServletContext servletContext = req.getServletContext();
// ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
// ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
}
}
此文为黑马SSM视频教学笔记,建议配合使用。