spring关于web容器获取ApplicationContext引用和Properties配置属性值

前言:考虑到Spring的强大是尽人皆知的,所以能用就不必造轮子了,只需要改造即可。

1、web中如何控制ApplicationContext

在spring框架整合下,自己写的代码中要使用ApplicationContext是不方便的,但是在org.springframework.web.context.support.WebApplicationContextUtils 中有一方法 getWebApplicationContext(ServletContext sc) 可以得到ApplicationContext引用;但此方法有一参数ServletContext,它是Servlet容器提供的上下文,所以非Servlet环境下是得不到的。

我们可以定义一个servlet,该servlet配置为被容器第一个加载,它可以得到ServletContext,从而得到ApplicationContext的引用
import org.springframework.context.ApplicationContext;
public class SpringBeanProxy {
    private static ApplicationContext applicationContext;
    
    public synchronized static void setApplicationContext(ApplicationContext arg) {
        applicationContext = arg;
    }
    
    public static Object getBean(String beanName){
        return applicationContext.getBean(beanName);
    }
}
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.springframework.web.context.support.WebApplicationContextUtils;
import SpringBeanProxy;
public class SpringBeanInitServlet  extends HttpServlet {
    public void init(ServletConfig arg) throws ServletException {
        SpringBeanProxy.setApplicationContext(WebApplicationContextUtils.getWebApplicationContext(arg.getServletContext()));
    }
}

 在web.xml中配置如下,即可

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
        <servlet-name>SpringBeanInitServlet</servlet-name>
        <servlet-class>
            SpringBeanInitServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

 由于listener先于servlet加载,所以可以确保SpringBeanInitServlet加载时spring已经初始化好了,如果你使用的是servlet加载spring就要注意调整这两个servlet的启动顺序了。代码中使用 SpringBeanProxy.getBean("bean name")即可得到bean实例。

还有其他方式,如

从指定目录加载:
ApplicationContext context = new FileSystemXmlApplicationContext("applicationContext.xml");  
从classpath路径加载:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml") 

2、web中如何控制基于ApplicationContext的配置文件读取信息值

关于程序中加载spring,自定义类实现spring 配置文件中通配符${jdbc.name}类似的正确解析;但是代码里如何使用读取到的配置文件呢?读源码 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 以及向上找父类和接口会发现,配置都定义好了,只是 protected Properties[] localProperties; 

是继承使用,没法调用。

于是就只定义啦,配置如下:

   <bean id="propertyConfigurer" class="com.jd.app.server.util.AutoPorpertiesConfigurer">
        <property name="locations">
            <list>
                <value>classpath:XXX.properties</value>
            </list>
        </property>
        <property name="propValueController" ref="genePropValueController"/>
        <property name="fileEncoding" value="GBK" />
    </bean>

 具体定制如下:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Created by on 2016/7/14.
 */
public class AutoPorpertiesConfigurer extends PropertyPlaceholderConfigurer {
    private static Map<String,Object> ctxPropertiesMap;
    private PropValueController propValueController;
    private PropValueController defaultPropValueController = new DefaultPropValueController();

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {

        super.processProperties(beanFactoryToProcess, props);
        ctxPropertiesMap = new HashMap<String,Object>();
         if (propValueController==null)
             propValueController = defaultPropValueController;

        long index=0;
        for (Object key : props.keySet()) {
            String keyStr = key.toString();
            Object value = propValueController.transform(index,keyStr,props.getProperty(keyStr));
            ctxPropertiesMap.put(keyStr, value);
            index++;
        }
    }

    public static Object getContextProperty(String name) {
        return ctxPropertiesMap.get(name);
    }

    public void setPropValueController(PropValueController propValueController) {
        this.propValueController = propValueController;
    }
}

/**
 * 配置值转化处理
 */
interface PropValueController{
    public Object transform(long index, String key, String value) throws BeansException;
}

/**
 * 配置默认返回原string
 */
class DefaultPropValueController implements PropValueController{
    @Override
    public Object transform(long index, String key, String value) throws BeansException {
        return value;
    }
此类即完成了PropertyPlaceholderConfigurer的任务,同时又提供了上下文properties访问的功能;于是在Spring配置文件中把PropertyPlaceholderConfigurer改成AutoPorpertiesConfigurer 。

PropValueController 接口可以为以后方便定制属性文件值转换灵活使用;

定义使用即可:

String gene = (String) propertyConfigurer.getContextProperty(cateid);

其实,通过

ServletContext servletContext = servlet.getServletContext();     
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);

 也能获取上下文并取得配置,但是如上定义更直接明了,简单易使用。

 转载原链接http://zl378837964.iteye.com/blog/2312241

猜你喜欢

转载自zl378837964.iteye.com/blog/2312241