个性化自己系统的ContextLoaderListener实现

本文介绍了一种优化Spring配置加载的方法,通过自定义ContextLoaderListener来实现按需加载配置文件,提高开发效率并减少不必要的资源消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题描述

     WEB项目在继承Spring时候,默认的配置的是ContextLoaderListener

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:spring/spring-context.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

这种配置会把Spring-context.xml配置的所有文件都加载进来,当spring-context.xml文件嵌入很多xml文件时候,加载非常的内容非常庞大,特别是涉及到后台定时任务时候,对开发来说非常不方便,还打印一大堆日志,影响开发效率,而且当发布项目的时候,可能在配置文件的修改忘记修改回来,导致发布出现BUG等。

二、问题分析:

      在本地开发的大多时候,是不需要启动一些配置的,例如:quartz的配置,此种情况下,系统可以在配置文件中设置一个开关器,当配置的时候设置值的时候启动,不配置不启动,方便开发,提升效率。

     通过开关器空值加载的spring文件,通过阅读ContextLoader源码发现,Spring在初始化Context的时候,获取到配置文件,只需要对:String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);这个地方修改即可:

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
   if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
      // The application context id is still set to its original default value
      // -> assign a more useful id based on available information
      String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
      if (idParam != null) {
         wac.setId(idParam);
      }
      else {
         // Generate default id...
         if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
            // Servlet <= 2.4: resort to name specified in web.xml, if any.
            wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                  ObjectUtils.getDisplayString(sc.getServletContextName()));
         }
         else {
            wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                  ObjectUtils.getDisplayString(sc.getContextPath()));
         }
      }
   }

   wac.setServletContext(sc);
   String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
   if (initParameter != null) {
      wac.setConfigLocation(initParameter);
   }
   customizeContext(sc, wac);
   wac.refresh();
}

        自定义ContextLoaderListener关系如下:


190917_Apih_996569.png


三、解决方案:

1、在web.xml配置文件时候,对配置文件拆分,分多个配置

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
      classpath:spring/wms-jdbc.xml,
      classpath:spring/wms-job.xml
   </param-value>
</context-param>

2、自定义ContextLoaderListener:

   自定义的ContextLoaderListener,重写configureAndRefreshWebApplicationContext方法,通过配置文件控制获取配置XML的内容:

package com.oneplus.wms.mvc;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ContextLoaderListener;

import javax.servlet.ServletContext;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

/**
 * 功能描述:Spring启动时, WMS控制加载Spring配置文件
 *
 * @author: Zhenbin.Li
 * Date: 16/1/8 Time: 10:45
 */
public class OneplusContextLoaderListener extends ContextLoaderListener {

    /**
     * sl4j
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(OneplusContextLoaderListener.class);

    /**
     * 配置文件名称
     */
    private static final String LOADER_CONFIG_FILE = "env-config.properties";

    @Override
    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
            // The application context id is still set to its original default value
            // -> assign a more useful id based on available information
            String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
            if (idParam != null) {
                wac.setId(idParam);
            } else {
                // Generate default id...
                if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
                    // Servlet <= 2.4: resort to name specified in web.xml, if any.
                    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getServletContextName()));
                } else {
                    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
                }
            }
        }

        wac.setServletContext(sc);
        String initParameter = assemblyInitParameter(sc.getInitParameter(CONFIG_LOCATION_PARAM));
        if (initParameter != null) {
            wac.setConfigLocation(initParameter);
        }
        customizeContext(sc, wac);
        wac.refresh();
    }

    /**
     * WMS对Spring启动设置开关加载配置文件
     *
     * @param webXmlConfigInitParameter web.xml配置的Spring文件
     * @return
     */
    protected String assemblyInitParameter(String webXmlConfigInitParameter) {
        String initParameter = webXmlConfigInitParameter;

        ClassPathResource resource = new ClassPathResource(LOADER_CONFIG_FILE);
        Properties configureProps;
        try {
            configureProps = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException e) {
            throw new RuntimeException("加载" + LOADER_CONFIG_FILE + "配置文件失败!", e);
        }

        Object configJobDebug = configureProps.get(ContextLoaderListenerConfigType.JOB_DEBUG.getType());
        if (configJobDebug == null) {
            LOGGER.debug("当前未配置加载Spring定时任务启动参数" + ContextLoaderListenerConfigType.JOB_DEBUG.getType() + ", 系统直接启动.");
            return initParameter;
        }

        String jobDebug = String.valueOf(configJobDebug).toUpperCase();
        ContextLoaderListenerStatus listenerStatus = ContextLoaderListenerStatus.getByStatus(jobDebug);
        if (listenerStatus == null) {
            throw new RuntimeException("配置Spring定时任务启动参数" + ContextLoaderListenerConfigType.JOB_DEBUG.getType() + ", ON或者OFF, 当前配置:" + jobDebug);
        }

        String[] configures = StringUtils.split(initParameter, ",");
        if (ArrayUtils.isEmpty(configures)) {
            throw new RuntimeException("配置Spring启动文件为空!");
        }
        LOGGER.debug(LOADER_CONFIG_FILE + "配置" + ContextLoaderListenerConfigType.JOB_DEBUG.getType() + "设置为:" + jobDebug);

        // 校验配置文件是否存在
        Object jobFileName = configureProps.get(ContextLoaderListenerConfigType.JOB_CONFIG_FILE.getType());
        if (jobFileName == null) {
            throw new RuntimeException(LOADER_CONFIG_FILE + "配置" + ContextLoaderListenerConfigType.JOB_CONFIG_FILE.getType() + "设置为空!");
        }
        if (!StringUtils.contains(webXmlConfigInitParameter, String.valueOf(jobFileName))) {
            throw new RuntimeException("web.xml无" + jobFileName + "配置信息!");
        }

        if (StringUtils.equals(jobDebug, ContextLoaderListenerStatus.OFF.getStatus())) {
            LOGGER.debug(LOADER_CONFIG_FILE + "配置" + ContextLoaderListenerConfigType.JOB_DEBUG.getType() + "设置为:" + jobDebug + ", WMS不加载配置文件" + jobFileName);
            // 获取过滤之后的配置文件
            List<String> filterConfigs = Lists.newArrayList();
            for (String configure : configures) {
                if (!StringUtils.contains(configure, String.valueOf(jobFileName))) {
                    filterConfigs.add(configure);
                }
            }
            initParameter = Joiner.on(",").join(filterConfigs);
        }

        return initParameter;
    }

    /**
     * 启动过滤配置文件类型
     */
    protected enum ContextLoaderListenerConfigType {
        JOB_DEBUG("JOB.DEBUG"),
        JOB_CONFIG_FILE("JOB.CONFIG.FILE");

        private String type;

        ContextLoaderListenerConfigType(String type) {
            this.type = type;
        }

        public String getType() {
            return type;
        }
    }

    /**
     * 开关状态值
     */
    protected enum ContextLoaderListenerStatus {
        ON("ON"),
        OFF("OFF");
        private String status;

        ContextLoaderListenerStatus(String status) {
            this.status = status;
        }

        public String getStatus() {
            return status;
        }

        public static ContextLoaderListenerStatus getByStatus(String statusCode) {
            if (StringUtils.isEmpty(statusCode)) {
                return null;
            }

            for (ContextLoaderListenerStatus status : ContextLoaderListenerStatus.values()) {
                if (status.getStatus().equals(statusCode)) {
                    return status;
                }
            }
            return null;
        }
    }

}

3、配置文件中开关配置:

# 开启定时任务调试,ON:打开,OFF:关闭
JOB.DEBUG=OFF
JOB.CONFIG.FILE=wms-job.xml

四、系统启动加载结果

  1、设置为OFF

2016-01-12 18:56:25.827 [main] INFO  /-Initializing Spring root WebApplicationContext
2016-01-12 18:56:25.869 [main] DEBUG com.oneplus.wms.mvc.OneplusContextLoaderListener-env-config.properties配置JOB.DEBUG设置为:OFF
2016-01-12 18:56:25.869 [main] DEBUG com.oneplus.wms.mvc.OneplusContextLoaderListener-env-config.properties配置JOB.DEBUG设置为:OFF, WMS不加载配置文件wms-job.xml

  2、设置为ON

2016-01-12 18:57:22.081 [main] INFO  /-Initializing Spring root WebApplicationContext
2016-01-12 18:57:22.125 [main] DEBUG com.oneplus.wms.mvc.OneplusContextLoaderListener-env-config.properties配置JOB.DEBUG设置为:ON
...
2016-01-12 19:00:00.105 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1] DEBUG org.mybatis.spring.SqlSessionUtils-Creating a new SqlSession
20



转载于:https://my.oschina.net/198608082556/blog/601526

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值