双亲委派机制简单运用和工具类获取配置文件属性

一.问题描述

最近项目需要对接其他公司的接口(SDK方式对接),SDK接入时需要特定的四个配置属性,该配置属性通过web.xml获取。在自己电脑调试通过之后,jar部署到服务器后发现无法正确读取到web.xml的内容。
由于没有日志的打印,所以不知道是因为路径不对还是什么原因导致无法正确读取web.xml(web.xml内容的读取代码在SDK依赖中)。于是只好自己本地覆盖依赖类,加上路径的日志打印。经过一番操作之后,发现打印的路径有问题,然后修改代码获取正确的路径还是无法读取web.xml。无奈,只能将四个配置放到配置文件中获取了。

二.解决思路

1 覆盖SDK依赖中获取web.xml内容的类,自己修改代码;
2 将四个配置属性放到配置文件获取;

三.解决方案

1 本地类覆盖依赖的类

只需要在自己的项目中建一个包路径、类名和依赖类完全相同的类即可。比如,依赖类的包路径 com.test.guess,类名为TestClazz,则在自己的项目新建一个包com.test.guess,将自己建的TestClazz类放到这个包下面即可(包路径、类名相同)。jar运行时,如果包路径、类名相同,则以项目中的优先

2 通过工具类获取配置文件中的配置属性

(1)创建工具类

其实jar启动时,spring会获取很多属性放到ApplicationContext上下文对象中(其中就包括配置文件的属性)。那么我们只需要在自己的项目中创建一个工具类就很容易处理了。工具类如下:

public class CommonUtils {
	//ApplicationContext对象
    public static ApplicationContext ac;
    private static Logger log = LoggerFactory.getLogger(CommonUtils.class);

    public CommonUtils() {
    }

    public static Object getBean(String name) {
        return StringUtils.isNoneBlank(new CharSequence[]{name}) ? ac.getBean(name) : null;
    }

    public static void setApplicationCtx(HttpServletRequest request) {
        if (ac == null) {
            log.info("ApplicationContext未被初始化");
        }

        Environment env = ac.getEnvironment();
        MutablePropertySources sources = ((ConfigurableEnvironment)env).getPropertySources();
        Iterator var4 = sources.iterator();

        while(var4.hasNext()) {
            PropertySource<?> propertySource = (PropertySource)var4.next();
            String key = propertySource.getName();
            if (key.indexOf("ckcest.js.") > -1) {
                request.setAttribute(key.replace("ckcest.js.", ""), propertySource.getProperty(key));
            }
        }

        request.setAttribute("ctx", request.getContextPath());
    }
	//获取配置的方法
    public static String getProperty(String name) {
        return ac.getEnvironment().getProperty(name);
    }
}

(2)工具类的ApplicationContext赋予实例

工具类有了,但是有个问题,如何让ac指向spring管理的ApplicationContext对象呢?需要如下处理:
① 启动类加上@ServletComponentScan注解(加上这个注解,@WebListener才有效)
② 监听,工具类的ac对象赋值

@WebListener
public class MyServletContextListener implements ServletContextListener {
    public MyServletContextListener() {
    }

    public void contextInitialized(ServletContextEvent sce) {
        ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext());
        //赋值
        CommonUtils.ac = ctx;
    }

    public void contextDestroyed(ServletContextEvent sce) {
    }
}

(3)获取配置源码查看

处理逻辑是在org.springframework.core.env下的PropertySourcesPropertyResolver类的getProperty方法。方法中会遍历PropertySourcesPropertyResolver的PropertySource属性
在这里插入图片描述

大致看下propertySource都有哪些属性吧
第一个属性是项目的端口
在这里插入图片描述

第二个属性就是配置文件的内容了:
在这里插入图片描述
在这里插入图片描述

注意:

PropertySource<?> propertySource = (PropertySource)var4.next(); 
Object value = propertySource.getProperty(key);

遍历获取下一个propertySource元素的时候,是带有泛型的,所以getProperty的逻辑不一样!这也是为什么,上面第一个元素和第二个元素的属性“结构”不同,但是还能获取的原因。具体的就要各位看官自己去看源码了。

完成以上步骤后,在服务器重试,对接正常。完美!

四.小结

1自己的项目覆盖某个依赖类,需要新建一个包名、类型相同的类即可;其实就是类加载机制;
2ApplicationContext会保存项目各种属性(最常用的配置文件等)
3为什么不用@value注解获取?
有两点原因
(1)因为SDK中被我覆盖的类,所有方法和属性都是static的。SDK其他类调用的时候该类的方法,是通过静态方法调用;
(2)工具类是公司框架现场的;

萌新发言,不喜勿喷,欢迎各位大佬指出不当之处!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值