小结:
- 容器不再是每一次都要获取创建, 也就是说, spring的配置文件或者配置类不再需要被多次加载. 而是设计在web应用一启动就创建出app对象
- 可以忽略配置名, 也就说, 配置名不一样只需要去修改web.xml文件, 不用动源代码
- 可以隐藏app对象的键名(在域中)
spring与web环境的集成
现在pom.xml中导入jar包
一个是serlvet一个是jsp
<dependency>
<!--Servlet的jar包-->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<!--jsp的jar包-->
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
当有了这两个包之后, 可以写web层的东西了
注意: 这里回顾一下什么是Mvc设计模式, 什么是软件开发的三层架构
此时存在的弊端
当写控制器代码时, 对于app这个对象的获取方式, 当业务一多时, 加载spring配置文件(或者是主配置类)的次数就会很多, 其实这是没有意义的, 其实loc容器只需要创建一次即可
解决方法
在web项目中, 可以使用ServletContextListener监听web应用的启动, 我们可以在web应用的启动时, 就加载spring的loc容器, 也即是app对象, 并将其存放到最大的域ServletContext中, 这样就可以在任意的位置获取app对象了
代码实例
/*
* 实现这个接口目的是为了监听当web应用启动时*/
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("app",app);
System.out.println("loc容器创建好了...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
这里使用maven的tomcat插件run会报错, 要在idea中为这个项目配置本地tomcat来启动
E:\Tomcat\apache-tomcat-8.5.66\bin\catalina.bat run
[2021-12-20 12:28:39,234] Artifact lea:war exploded: Waiting for server connection to start artifact deployment...
Using CATALINA_BASE: "C:\Users\LYD\.IntelliJIdea2018.3\system\tomcat\Unnamed_lea"
Using CATALINA_HOME: "E:\Tomcat\apache-tomcat-8.5.66"
Using CATALINA_TMPDIR: "E:\Tomcat\apache-tomcat-8.5.66\temp"
Using JRE_HOME: "C:\Java\jdk-13.0.2"
Using CLASSPATH: "E:\Tomcat\apache-tomcat-8.5.66\bin\bootstrap.jar;E:\Tomcat\apache-tomcat-8.5.66\bin\tomcat-juli.jar"
Using CATALINA_OPTS: ""
NOTE: Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
20-Dec-2021 12:28:40.472 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本: Apache Tomcat/8.5.66
20-Dec-2021 12:28:40.473 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器构建: May 8 2021 22:44:01 UTC
20-Dec-2021 12:28:40.474 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器版本号: 8.5.66.0
20-Dec-2021 12:28:40.474 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 操作系统名称: Windows 10
20-Dec-2021 12:28:40.474 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS.版本: 10.0
20-Dec-2021 12:28:40.475 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 架构: amd64
20-Dec-2021 12:28:40.475 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java 环境变量: C:\Java\jdk-13.0.2
20-Dec-2021 12:28:40.475 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java虚拟机版本: 13.0.2+8
20-Dec-2021 12:28:40.475 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM.供应商: Oracle Corporation
20-Dec-2021 12:28:40.475 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: C:\Users\LYD\.IntelliJIdea2018.3\system\tomcat\Unnamed_lea
20-Dec-2021 12:28:40.475 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: E:\Tomcat\apache-tomcat-8.5.66
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.lang=ALL-UNNAMED
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.io=ALL-UNNAMED
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.util=ALL-UNNAMED
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.util.logging.config.file=C:\Users\LYD\.IntelliJIdea2018.3\system\tomcat\Unnamed_lea\conf\logging.properties
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote=
20-Dec-2021 12:28:40.476 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.port=1099
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.ssl=false
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcom.sun.management.jmxremote.authenticate=false
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.rmi.server.hostname=127.0.0.1
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djdk.tls.ephemeralDHKeySize=2048
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dignore.endorsed.dirs=
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcatalina.base=C:\Users\LYD\.IntelliJIdea2018.3\system\tomcat\Unnamed_lea
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Dcatalina.home=E:\Tomcat\apache-tomcat-8.5.66
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数: -Djava.io.tmpdir=E:\Tomcat\apache-tomcat-8.5.66\temp
20-Dec-2021 12:28:40.477 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent 使用APR版本[1.7.0]加载了基于APR的Apache Tomcat本机库[1.2.28]。
20-Dec-2021 12:28:40.478 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR功能:IPv6[true]、sendfile[true]、accept filters[false]、random[true]。
20-Dec-2021 12:28:40.478 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL配置:useAprConnector[false],useOpenSSL[true]
20-Dec-2021 12:28:40.481 信息 [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL成功初始化 [OpenSSL 1.1.1k 25 Mar 2021]
20-Dec-2021 12:28:40.529 信息 [main] org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-nio-8080"]
20-Dec-2021 12:28:40.831 信息 [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
20-Dec-2021 12:28:40.845 信息 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 822 ms
20-Dec-2021 12:28:40.891 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina]
20-Dec-2021 12:28:40.892 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/8.5.66]
20-Dec-2021 12:28:40.903 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"]
20-Dec-2021 12:28:40.915 信息 [main] org.apache.catalina.startup.Catalina.start Server startup in 68 ms
Connected to server
[2021-12-20 12:28:41,339] Artifact lea:war exploded: Artifact is being deployed, please wait...
20-Dec-2021 12:28:42.364 信息 [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
20-Dec-2021 12:28:42.595 信息 [RMI TCP Connection(3)-127.0.0.1] org.springframework.context.support.AbstractApplicationContext.prepareRefresh Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@57765b41: startup date [Mon Dec 20 12:28:42 CST 2021]; root of context hierarchy
loc容器创建好了...
20-Dec-2021 12:28:43.416 警告 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom 使用[SHA1PRNG]创建会话ID生成的SecureRandom实例花费了[290]毫秒。
[2021-12-20 12:28:43,443] Artifact lea:war exploded: Artifact is deployed successfully
[2021-12-20 12:28:43,443] Artifact lea:war exploded: Deploy took 2,105 milliseconds
20-Dec-2021 12:28:50.905 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [E:\Tomcat\apache-tomcat-8.5.66\webapps\manager]
20-Dec-2021 12:28:50.946 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[E:\Tomcat\apache-tomcat-8.5.66\webapps\manager]的部署已在[41]毫秒内完成
使用ServletContext域中的app对象
@WebServlet("/saveUserServlet")
public class SaveUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ApplicationContext app = (ApplicationContext)servletContext.getAttribute("app");
UserService userService = (UserService)app.getBean("userService");
userService.save();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
打开浏览器访问
http://localhost:8080/lea_war_exploded/saveUserServlet
控制台打印
20-Dec-2021 16:36:45.943 警告 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom 使用[SHA1PRNG]创建会话ID生成的SecureRandom实例花费了[294]毫秒。
[2021-12-20 04:36:45,965] Artifact lea:war exploded: Artifact is deployed successfully
[2021-12-20 04:36:45,965] Artifact lea:war exploded: Deploy took 5,504 milliseconds
20-Dec-2021 16:36:47.217 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [E:\Tomcat\apache-tomcat-8.5.66\webapps\manager]
20-Dec-2021 16:36:47.257 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[E:\Tomcat\apache-tomcat-8.5.66\webapps\manager]的部署已在[40]毫秒内完成
这是Orale的实现方法
调用了持久层的方法
万一有的人的项目的spring配置文件不叫applicationContext.xml或者说spring的主配置类不叫SpringConfiguration. 这时原代码中获取app的地方就要修改代码. 怎样可以让代码忽略spring的配置文件名或者主配置类名呢?
在web.xml中配置全局变量
例如
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--全局初始化变量-->
<context-param>
<param-name>contextConfiguration</param-name>
<param-value>SpringConfiguration.class</param-value>
</context-param>
<!--配置监听器-->
<listener>
<listener-class>web.listener.ContextLoaderListener</listener-class>
</listener>
</web-app>
小结 : 这里注意一个地方, 设置全局初始化变量只能在最上面, 不然会报错
然后修改一下监听器处的代码:
/*
* 实现这个接口目的是为了监听当web应用启动时*/
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
//读取参数
String contextConfiguration = servletContext.getInitParameter("contextConfiguration");
//利用全局变量来获取app对象, 就算spring配置的名称不一样, 只用修改web.xml
ApplicationContext app = new AnnotationConfigApplicationContext(contextConfiguration);
servletContext.setAttribute("app",app);
System.out.println("loc容器创建好了...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
这里再进一步考虑更细, 如果不知道存放进ServletContext域中的app的键名也就叫app呢?怎么样不用去记住这个键名?
写一个工具类
package utils;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
public class WebApplicationContextUtils {
public static ApplicationContext getApp(ServletContext servletContext){
return (ApplicationContext)servletContext.getAttribute("app");
}
}
在用到app对象的地方修改代码
@WebServlet("/saveUserServlet")
public class SaveUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
/*ApplicationContext app = (ApplicationContext)servletContext.getAttribute("app");*/
//使用这个工具类就可以完全忽略域中app的键名
ApplicationContext app = WebApplicationContextUtils.getApp(servletContext);
UserService userService = (UserService)app.getBean("userService");
userService.save();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
本文介绍如何将Spring容器与Web应用集成,通过监听Web应用启动加载Spring容器,并将其存储在ServletContext中,以便在整个Web应用中复用。同时讨论了如何忽略配置文件名和容器键名。
257

被折叠的 条评论
为什么被折叠?



