最近由于公司项目抽出一个钉钉提醒的功能,上面需要添加某个模块的路径名字以及对应的方法名字。
类似于这种:
【本地环境】-----【模块1】-----【TestController.test()】---- 订单123456,请求上游失败。
类似于这种提醒。
这个问题就出在了获取模块路径名字的时候,因为自己之前有一个获取spring容器的工具类
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
applicationContext = arg0;
}
/**
* 获取applicationContext对象
* @return
*/
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 根据bean的id来查找对象
* @param id
* @return
*/
public static Object getBeanById(String id){
return applicationContext.getBean(id);
}
/**
* 根据bean的class来查找对象
* @param c
* @return
*/
public static Object getBeanByClass(Class c){
return applicationContext.getBean(c);
}
/**
* 根据bean的class来查找所有的对象(包括子类)
* @param c
* @return
*/
public static Map getBeansByClass(Class c){
return applicationContext.getBeansOfType(c);
}
/**
* 获取ApplicationName
*/
public static String getApplicationName() {
return getApplicationContext().getApplicationName();
}
/**
* 获取spring.profiles.active
*/
public static String getActiveProfile() {
return getApplicationContext().getEnvironment().getActiveProfiles()[0];
}
}
可以直接获取到容器的对象applicationContext,所以我就添加了一个公用方法getApplicationName()来获取对应的applicationName,本以为不会出什么问题,因为在我的模块里好多地方都用了,都能够获取到正常的模块路径名称,之后没有什么异常空字符串提示。但是换到其他同事的模块之后,发现获取不到他的模块路径名称,这个让我很费解,于是去查了一下这个项目模块获取路径名称的过程。
发现当同事调用
getApplicationName()的时候会请求到
AbstractApplicationContext类里的getApplicationName()方法
而在我的项目模块里会请求到
AbstractRefreshableWebApplicationContext类里的getApplicationName()方法大家在这里或许一眼看出来这俩请求的区别了吧?
对的!我的这里是有web容器的,而同事那里没有web容器。
大家如果还不确定,可以在启动的时候,看一下setApplicationContext()方法里注入的是什么类就一目了然了
同事的注入类为:AnnotationConfigApplicationContext
我的注入类为:AnnotationConfigEmbeddedWebApplicationContext
这样更清晰了吧,AnnotationConfigEmbeddedWebApplicationContext是springboot默认的web启动容器。
所以当调用getApplicationName()时请求的目标类不一样,因为同事的模块环境不是web环境,所以获取不到对应的项目模块路径名字了,只需要将对应的项目模块添加为web环境就可以获取到对应的applicationName路径名称了。
注意:由于我们共用的pom文件里包含了web环境,同事这边把springboot的启动方式改成web方式启动以后就好了,大家没必要都这样改,可以根据自己公司的项目需求将web环境加上,就可以使用web容器获取对应的项目路径名称了(server:context-path:)