在平时的开发工作中,一般会有三个开发环境,本地、测试和生产环境,很多时候每个环境对于Web项目的项目名会有不同的需求,可能生产环境不需要项目名,直接域名访问,但在测试环境中又需要带上项目名。这样的话,对于前端页面来说,资源的位置可能就产生变化,我们总不能每次上线都需要改资源文件的url,解决这个问题,方法有多种,下面只记录一下我的解决办法。
二、代码在Web整合Spring的过程中,会在web.xml中配置进入Spring的监听器(ContextLoaderListener),tomcat在初始化过程中的初始化顺序是:
在启动 Web 项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点和;
接着容器会创建一个 ServletContext (上下文),应用范围内,即整个Web项目都能使用这个上下文;
接着容器会将读取到 转化为键值对,并交给ServletContext;
容器创建 中的类实例,即创建监听(注:listener定义的类可以是自定义的类但必须
需要继承ServletContextListener);
在监听的类中会有一个 contextInitialized(ServletContextEvent event) 初始化方法,在这个方法中可以通
过 event.getServletContext().getInitParameter("contextConfigLocation") 来得到context-param
设定的值。在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法.
用于关闭应用前释放资源,比如说数据库连接的关闭;
得到这个context-param的值之后,你就可以做一些操作了,注意,这个时候你的Web项目还没有完全启动完成,
这个动作会比所有的Servlet都要早;
Spring所提供的监听器(org.springframework.web.context.ContextLoaderListener),实现了ServletContextListener接口,只要一个类实现了该接口,在Web应用对象初始化的时候,它就会被监听到并且执行它对应的方法,在它的方法当中,会调用初始化 webApplicationContext方法,在该方法中,会将整个Spring的环境进行初始化。
由上面的初始化过程可知容器对于 web.xml 的加载过程是 :listener >> context-param >> filter >> servlet (在Listener中加载context-param参数);
这里通过注册Listener的方式来将项目名获取到 application 域中,这样就可以在前端页面每次获取到同样的项目名。
我们自定义一个SeverStartUpListener监听器,该监听器实现ServletContextListener接口,并重写里面的方法,具体代码如下:
public class ServerStartupListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
// 将web应用名称(路径)保存到application范围中
ServletContext application = sce.getServletContext();
String path = application.getContextPath();
application.setAttribute("APP_PATH", path);
}
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
}
编写完Listener后,需要在web.xml中注册该监听器,好让tomcat把该监听器加载进来。
org.springframework.web.context.ContextLoaderListener
com.scorpios.atcrowdfunding.web.ServerStartupListener
通过上述的监听器,我们就把获取到的项目名放到了application域中,在前端页面引入资源文件前面时,只需要获取APP_PATH的值,就可以得到资源的访问路径了。引入示例如下:
三、总结
本文主要采用办法就是:基于 tomcat 加载 Listener 的顺序,在Listener中获取到项目名,然后将该名字放在应用的application域中,因为该域里面存放的字段在整个应用的范围内都有效。