Spring迁移为SpringBoot遇到的一些坑
由于公司需要,之前进行了Spring项目迁移为SpringBoot项目的工作。期间遇到了许多坑,一直没有解决,勉强采取其它方式绕过去了。在求助百度的过程中,发现了一句话:
Spring Boot的限制:
将现有或传统的Spring Framework项目转换为Spring Boot应用程序是一个非常困难和耗时的过程。它仅适用于全新Spring项目。
看完深有感触,这话说的太对了!
在此总结一下Spring迁移为SpringBoot遇到的那些坑,供大家参考:
1.SpringBoot无法动态注入xml
什么是动态注入xml呢?公司之前的Spring项目中,用到了大量的xml配置文件;在启动时,传入main方法中的args[]参数的不同,会加载不同的xml文件。实现原理大致如下:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(args);
其中,applicationContext为Spring的bean工厂对象,args为String[]数组,其中保存一些xml的路径。
但是,在SpringBoot下,你会发现,你只能这样启动SpringBoot对象并获得bean工厂对象:
ConfigurableApplicationContext context = SpringApplication.run(test.class, args);
其中,test.class为当前类,args为传入main方法的args[]参数,但是这个args即使包含xml的路径,SpringBoot也不会帮你加载。
找来找去,SpringBoot要想加载xml文件,只能通过注解实现了。
@ImportResource(locations={"classpath*:/spring/a/mubiao1*/*.xml","classpath*:/spring/test.xml"})
但是,注解怎么可能实现动态加载xml呢?又不能配置变量。
将xml转换为java文件?能否动态加载先不说,之前的项目可是有几百个xml,每个xml中有大量的bean,全部转换耗时耗力。
最后,只能勉强用@ImportResource与*符号,将所有的xml全部加载进去了,没有实现根据传入的args选择不同的xml加载的方式。
2.SpringBoot的xml文件中想使用符号“${}”实现动态替换会报错
在spring项目中,在xml文件直接使用“${}”是没有问题的,例如:
<bean id="a" class="com.a" >
<property name="username">
<value>
<![CDATA[
我的名字是${user}
]]>
</value>
</property>
</bean>
其中,${user}会在程序执行过程中,使用Template对象动态替换为map中相同键的值,例如:
String template = "我的名字是${user}";//这个String实际上从xml注入的对象获得的,为了简化就直接写了
Map<String, String> map = new HashMap();
map.put("user","小明");
StringWriter writer = new StringWriter();
new Template(null, new StringReader(template), new Configuration())
.process(map, writer);
System.out.println(writer.toString());
这样就会输出"我的名字是小明",如何替换取决于map中对应键的值,实现了程序运行中的动态替换。
但是,在SpringBoot中,如果你在xml中还是这么写,就会报错了:
Could not resolve placeholder 'a' in value "我的名字是${user}"
这时,如果你在application.properties中增加一行,就可以执行了:
user=小明
为什么呢?因为SpringBoot发现时"${}"会进行替换,如果无法替换则报错。
但是,在properties中配置好,并不符合在程序运行中动态替换的结果。
这也是我很不能理解的地方,我在xml中都用了CDATA标签了,你还要给我替换,这让我怎么实现在程序运行中用Template动态替换呢?
没办法,毕竟还得用SpringBoot完成任务,最终使用了这个折中的方法:
我的名字是@###@{user}
自定义一个特殊符号"@###@",后续在程序中准备使用Template替换时,先将"@###@"替换为"$",之后就可以用Template正常替换了。虽然不美观,但是功能实现了。
----------------------------------------------------------
新想到的第1个坑的解决办法(暂时没有想到更好的方法):
原理:springboot启动命令可以加载指定的application-*.properties,而注解可以使用${}读取properties中的数据。
步骤:
1.创建几百个application-*.properties
2.springboot启动类中使用注解:
@ImportResource(locations = {"classpath*:/spring/${mymsg.fileFolder}/*.xml"})
3.某个properties中写,例如application-file1.properties中写(mymsg.fileFolder对应的value):
mymsg.fileFolder=FileFolder1
4.启动jar包时,不同场景用不同命令,例如(加载application-file1.properties):
java -jar test.jar --spring.profiles.active=file1
总结:
这样,根据启动参数不同,读取不同properties,就可以加载不同xml了。