如何把Spring Boot 项目变成一个XML配置的Spring项目
现在大家都追赶新的技术潮流,我来逆行一下。
其实Spring Boot 隐藏了大量的细节,有大量的默认配置,其实通过xml配置的方式也可以达到和Spring Boot一样的效果。
Profile
在Spring Boot项目中我们通过application.properties
中的设置来配置使用哪个配置文件application-dev.properties
,application-prod.properties
等等
spring.profiles.active=dev
Spring 3.0以后就包含了Profile功能,在xml中可以这么写,不过所有的bean需要显式的配置。需要弄清楚自己项目的依赖关系,在Spring中第三方包如何初始化。
<beans profile="dev,test"><bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:application-dev.properties" /></bean>
</beans><beans profile="prod"><bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:application-prod.properties" /></bean>
</beans>
在Spring Boot中大量的Jave Bean都包含了默认初始化的功能,只需要配置预先设置好的属性名称,但是在xml中需要显式的初始化Bean,并且可以在初始化的时候用Placeholder
来配置。
Environment
在 Spring Boot 项目中application.properties
和application-xxx.properties
中的变量会自动放到 Environment中,并且可以通过@Value
直接注入到变量中。
如果使用 ClassPathXmlApplicationContext 初始化项目,可以看到源代码里 Environment 是一个 StandardEnvironment 实例,仅仅包含系统变量和环境变量,为了把application-xxx.properties
放到 Environment 当中我们需要扩展一下 ClassPathXmlApplicationContext,下面是CustomApplicationContext
和CustomEnvironment
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;public class CustomApplicationContext extends ClassPathXmlApplicationContext {public CustomApplicationContext(){super();}public CustomApplicationContext(String configLocation) {super(new String[]{configLocation}, true, null);}@Overridepublic ConfigurableEnvironment createEnvironment() {return new CustomEnvironment();}
}
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePropertySource;import java.io.IOException;public class CustomEnvironment extends StandardEnvironment {private static final String APPCONFIG_PATH_PATTERN = "classpath:application-%s.properties";@Overrideprotected void customizePropertySources(MutablePropertySources propertySources) {super.customizePropertySources(propertySources);try {propertySources.addLast(initResourcePropertySourceLocator());} catch (IOException e) {logger.warn("failed to initialize application config environment", e);}}private PropertySource<?> initResourcePropertySourceLocator() throws IOException {String profile = System.getProperty("spring.profiles.active", "dev");String configPath = String.format(APPCONFIG_PATH_PATTERN, profile);System.out.println("Using application config: " + configPath);Resource resource = new DefaultResourceLoader(this.getClass().getClassLoader()).getResource(configPath);PropertySource resourcePropertySource = new ResourcePropertySource(resource);return resourcePropertySource;}
}
日志配置
Spring Boot 默认使用的是logback,在logback-spring.xml 的配置文件中可以使用Spring Profile,而且还有一个默认的CONSOLE Appender
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProfile name="dev,test"><logger name="org.springframework" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</springProfile>
<springProfile name="prod"><logger name="org.springframework" level="INFO" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</springProfile>
</configuration>
在没有使用Spring Boot的情况下,不能在logback的config中使用Spring Profile,只能分拆成多个文件,然后根据环境变量读取不同的配置文件,需要添加依赖org.logback-extensions
。
<dependency><groupId>org.logback-extensions</groupId><artifactId>logback-ext-spring</artifactId><version>0.1.4</version>
</dependency>
logback-dev.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n}"/><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><logger name="org.springframework" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</configuration>
logback-prod.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n}"/><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><logger name="org.springframework" level="INFO" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</configuration>
下面的代码根据环境变量读取不同的配置文件
private static final String LOGCONFIG_PATH_PATTERN = "classpath:logback-%s.xml";public static void main(String[] args) throws FileNotFoundException, JoranException {String profile = System.getProperty("spring.profiles.active", "dev");System.setProperty("file.encoding", "utf-8");// logback configString logConfigPath = String.format(LOGCONFIG_PATH_PATTERN, profile);System.out.println("Using logback config: " + logConfigPath);LogbackConfigurer.initLogging(logConfigPath);SLF4JBridgeHandler.removeHandlersForRootLogger();SLF4JBridgeHandler.install();ConfigurableApplicationContext context = new CustomApplicationContext("classpath:applicationContext.xml");}
测试
有Spring Boot 的时候TestCase写起来很方便,在类上添加两行注解即可,在src\test\resources
下的application.properties
中设置spring.profiles.active=test
即可指定Profile为test
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestStockService {@AutowiredStockService stockService;@Beforepublic void setUp() {}@Afterpublic void tearDown() {}@Testpublic void testMissingBbTickerEN() {}
}
不使用Spring Boot的情况下,需要指定好几个配置。
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@ActiveProfiles(profiles = "test")
@TestPropertySource("classpath:application-test.properties")
public class TestStockService {@AutowiredStockService stockService;@Beforepublic void setUp() {}@Afterpublic void tearDown() {}@Testpublic void testMissingBbTickerEN() {}
}
打包
Spring Boot 会把项目和所依赖的 Jar 包打包成一个大 Jar 包,直接运行这个 Jar 包就可以。这个功能是通过spring-boot-maven-plugin
实现的。
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
不使用Spring Boot 之后,我们需要配置maven-jar-plugin
,但是依赖包无法像Spring Boot一样打包成一个大的 Jar 包,需要我们指定classpath。
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.6</version><configuration><archive><manifest><mainClass>com.exmaple.demo.DemoApplication</mainClass><addClasspath>true</addClasspath><classpathPrefix>lib/</classpathPrefix></manifest></archive></configuration>
</plugin>
注意:
当用java -jar yourJarExe.jar来运行一个经过打包的应用程序的时候,你会发现如何设置-classpath参数应用程序都找不到相应的第三方类,报ClassNotFound错误。实际上这是由于当使用-jar参数运行的时候,java VM会屏蔽所有的外部classpath,而只以本身yourJarExe.jar的内部class作为类的寻找范围。所以需要在jar包mainfest中添加classpath。
依赖包
使用下面的maven配置帮你把所有的依赖包复制到targetlib目录下,方便我们部署或者是测试时复制依赖包。
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy-dependencies</id><phase>prepare-package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>target/lib</outputDirectory><overWriteIfNewer>true</overWriteIfNewer><excludeGroupIds>junit,org.hamcrest,org.mockito,org.powermock,${project.groupId}</excludeGroupIds></configuration></execution></executions><configuration><verbose>true</verbose><detail>true</detail><outputDirectory>${project.build.directory}</outputDirectory></configuration>
</plugin>
运行
运行时通过指定命令行参数 -Dspring.profiles.active=prod 来切换profile
java -jar -Dspring.profiles.active=prod demo.jar
总结
Spring Boot很大程度上方便了我们的开发,但是隐藏了大量的细节,我们使用xml配置spring可以达到差不多同样的效果,但是在结构和配置上更加清晰。
如何把Spring Boot 项目变成一个XML配置的Spring项目相关推荐
- Spring Boot入门系列(六)Spring Boot如何使用Mybatis XML 配置版【附详细步骤】
前面介绍了Spring Boot 中的整合Thymeleaf前端html框架,同时也介绍了Thymeleaf 的用法.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/z ...
- (转)Spring Boot(二十):使用 spring-boot-admin 对 Spring Boot 服务进行监控
http://www.ityouknow.com/springboot/2018/02/11/spring-boot-admin.html 上一篇文章<Spring Boot(十九):使用 Sp ...
- [Spring Boot]Druid datasource整合及配置
[Spring Boot]Druid datasource整合及配置 创建Spring Boot项目 这里使用默认配置创建一个空项目 demo-druid 用作演示,可跳过这一段: 只勾选基本的Spr ...
- springboot日志写入mysql_44. Spring Boot日志记录SLF4J【从零开始学Spring Boot】
学院中有Spring Boot相关的课程!点击「阅读原文」进行查看! SpringSecurity5.0视频:http://t.cn/A6ZadMBe Sharding-JDBC分库分表实战: 在开发 ...
- 14. Spring Boot定时任务的使用【从零开始学Spring Boot】
[视频 & 交流平台] à SpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008& ...
- Spring Boot 面试,一个问题就干趴下了!
最近栈长面试了不少人,其中不乏说对 Spring Boot 非常熟悉的,然后当我问到一些 Spring Boot 核心功能和原理的时候,没人能说得上来,或者说不到点上,可以说一个问题就问趴下了! 这是 ...
- Spring Boot(5)---第一个Spring Boot应用程序
Spring Boot入门:开发您的第一个Spring Boot应用程序 本节介绍如何开发一个简单的"Hello World!"Web应用程序,该应用程序重点介绍Spring Bo ...
- java application.xml_第4章 零XML配置的Spring Boot Application
第4章 零XML配置的Spring Boot Application Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性properties文件.YAML 文件.环境变 ...
- Spring Boot 面试,一个问题就干趴下了
最近栈长面试了不少人,其中不乏说对 Spring Boot 非常熟悉的,然后当我问到一些 Spring Boot 核心功能和原理的时候,没人能说得上来,或者说不到点上,可以说一个问题就问趴下了! 这是 ...
最新文章
- ocp 042 第十一章:管理oracle网络配置
- 黑客攻防:从入门到入狱_每日新闻摘要:游戏服务黑客被判入狱27个月
- LeetCode 1450. 在既定时间做作业的学生人数
- linux实现防止恶意扫描 PortSentry
- Chelly的串串专题
- simulink教程(自动控制原理)
- js截取中英文字符串
- 服务器的上行带宽和下行带宽是什么意思
- 扑克牌排序(结构体)
- 代理IP是什么意思?浏览器代理和代理服务器是什么(小白必看,看了必会,不看血亏)
- zz我们都回不去了-南大校门被拆
- rqt_publisher包用法详解
- 流行和声(4)Major7和弦
- Maven打包Excel等资源文件损坏问题
- 使用U盘启动盘安装Imperva MX13.0
- 深入理解MyBatis(七)—MyBatis事务
- java hgetall_详解Java使用Pipeline对Redis批量读写(hmsethgetall)
- 如何给网站做SEO优化?
- 很抱歉,OneDrive服务器出现问题,请稍后重试。(错误代码:0x8004def5)
- 如何恢复录音删除的录音文件_电脑录音软件如何定时自动录音