简介
在使用SpringBoot构建项目的过程中,简化了第三方插件与Spring整合步骤,省略了繁琐的XML配置内容,只需要在pom.xml文件中引入模块化的Starter POMs,其中各个模块都有自己的默认配置,所以如果不是特殊应用场景,就只需要在application.properties中完成一些属性配置就能开启各模块的应用。
如果需要修改自定义修改默认配置,spring boot 提供了很简便的方法,只需要在application.properties 中添加修改相应的配置。(spring boot启动的时候会读取application.properties这份默认配置)
注意:application.properties 是springboot默认的全局变量配置文件,默认位置是src/main/resources(如果不存在可以手动创建),SpingBoot的全局配置文件的作用是对一些默认配置的配置值进行修改。
修改默认配置
在application.properties文件中可以完成日志信息、数据库连接池、自定义变量等信息的配置。完整的配置参考官方地址:SpringBoot属性文件application.properties配置文档(全部)
tomcat端口
springboot开发web项目的时候,默认的端口号是8080,如果需要修改该端口号,需要在application.properties 添加以下记录:
#tomcat 端口号设置,重启后生效
server.port=8888
重启之后可以看到端口号已经被修改:
2018-03-05 14:13:08.663 INFO 6672 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8888 (http) with context path ''
自定义属性和使用
在配置文件中定义
在配置文件application.properties增加如下信息:
#自定义属性信息并且在rest接口中返回使用
com.sunld.applicationp.chapter=springboot自定义属性
com.sunld.applicationp.course=《springboot系统化学习》
#在配置文件中可以使用属性传递
com.sunld.applicationp.learning=我们正在学习${com.sunld.applicationp.course}中的${com.sunld.applicationp.chapter}
测试用例
引用类-CourseLearningApplicationProperties
package com.sunld.conf;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//可以通过@Value("${属性值}")获取配置文件中的属性
@Component
public class CourseLearningApplicationProperties {
@Value("${com.sunld.applicationp.chapter}")
private String chapter;
@Value("${com.sunld.applicationp.course}")
private String course;
@Value("${com.sunld.applicationp.learning}")
private String learning;
public String getChapter() {
return chapter;
}
public void setChapter(String chapter) {
this.chapter = chapter;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String getLearning() {
return learning;
}
public void setLearning(String learning) {
this.learning = learning;
}
}
测试类与结果
@Test
public void contextLoads() {
}
@Autowired
private CourseLearningApplicationProperties courseLearningApplicationProperties;
//测试自定义属性的获取
@Test
public void testCourseLearningApplicationProperties() {
System.out.println("章节:" + courseLearningApplicationProperties.getChapter());
System.out.println("课程:" + courseLearningApplicationProperties.getCourse());
System.out.println("学习:" + courseLearningApplicationProperties.getLearning());
}
结果输出-乱码:
章节:springboot自定义属性
课程:《springboot系统化å¦ä¹ 》
学习:我们æ£åœ¨å¦ä¹ 《springboot系统化å¦ä¹ 》ä¸çš„springboot自定义属性
乱码解决
原因分析
在配置文件application.properties中配置中文,在读取时会出现乱码,但是application.yml就显示正常。
原因:Springboot是以iso-8859的编码方式读取的application.properties配置文件。
解决方案
增加properties文件
新增配置文件
重新配置一个文件“myconfig.properties”,在加载的实例类中增加如下代码:
@PropertySource(value = "classpath:/myconfig.properties" ,encoding = "UTF-8")
引用类-CourseLearningMyConfig
测试和输出
@Autowired
private CourseLearningMyConfig courseLearningMyConfig;
//测试自定义属性的获取
@Test
public void testCourseLearningMyConfig() {
System.out.println("章节:" + courseLearningMyConfig.getChapter());
System.out.println("课程:" + courseLearningMyConfig.getCourse());
System.out.println("学习:" + courseLearningMyConfig.getLearning());
}
输出:
章节:springboot自定义属性-myconfig
课程:《springboot系统化学习》-myconfig
学习:我们正在学习《springboot系统化学习》-myconfig中的springboot自定义属性-myconfig
使用yml配置文件替换默认的properties配置文件
配置文件
使用application.yml替换application.properties文件
com: #自定义属性信息并且在rest接口中返回使用
sunld:
applicationp:
chapter: springboot自定义属性-yml
course: 《springboot系统化学习》-yml
#在配置文件中可以使用属性传递
learning: 我们正在学习${com.sunld.applicationp.course}中的${com.sunld.applicationp.chapter}
引用类-CourseLearningApplicationYml
测试与结果
@Autowired
private CourseLearningApplicationYml courseLearningApplicationYml;
//测试自定义属性的获取
@Test
public void testCourseLearningApplicationYml() {
System.out.println("章节:" + courseLearningApplicationYml.getChapter());
System.out.println("课程:" + courseLearningApplicationYml.getCourse());
System.out.println("学习:" + courseLearningApplicationYml.getLearning());
}
输出结果:
章节:springboot自定义属性-yml
课程:《springboot系统化学习》-yml
学习:我们正在学习《springboot系统化学习》-yml中的springboot自定义属性-yml
@ConfigurationProperties读取自定义属性
在pom文件增加依赖信息
<!-- 增加使用@ConfigurationProperties读取自定义属性的依赖 -->
<!--spring boot 配置处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
增加解析配置文件的bean
参考代码如下
package com.sunld.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
//可以通过@Value("${属性值}")获取配置文件中的属性
@Component
@PropertySource(value = "classpath:/myconfig.properties" ,encoding = "UTF-8")
//@ConfigurationProperties注解主要用来把properties配置文件转化为bean来使用的,
//而@EnableConfigurationProperties注解的作用是@ConfigurationProperties注解生效。
@ConfigurationProperties(prefix="com.sunld.application")
public class CourseLearningMyConfigAuto {
private String chapter;
private String course;
private String learning;
public String getChapter() {
return chapter;
}
public void setChapter(String chapter) {
this.chapter = chapter;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String getLearning() {
return learning;
}
public void setLearning(String learning) {
this.learning = learning;
}
}
测试与结果
@Autowired
private CourseLearningMyConfigAuto courseLearningMyConfigAuto;
//测试自定义属性的获取
@Test
public void testCourseLearningMyConfigAuto() {
System.out.println("章节:" + courseLearningMyConfigAuto.getChapter());
System.out.println("课程:" + courseLearningMyConfigAuto.getCourse());
System.out.println("学习:" + courseLearningMyConfigAuto.getLearning());
}
结果:
章节:springboot自定义属性-myconfig
课程:《springboot系统化学习》-myconfig
学习:我们正在学习《springboot系统化学习》-myconfig中的springboot自定义属性-myconfig
注意:需要在应用类或者application类,加@EnableConfigurationProperties({BlogProperties.class})注解或者在bean中增加@Component。不能同时添加,会导致单例模式的失败。
发布到rest
controller
package com.sunld.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sunld.conf.CourseLearningMyConfigAuto;
//@RestController的意思就是controller里面的方法都以json格式输出,不用再写什么jackjson配置的了!
@RestController
public class PublishController {
@Autowired
private CourseLearningMyConfigAuto courseLearningMyConfigAuto;
@RequestMapping("/publishmyconfig")
public String publishMyConfig() {
System.out.println("章节:" + courseLearningMyConfigAuto.getChapter());
System.out.println("课程:" + courseLearningMyConfigAuto.getCourse());
System.out.println("学习:" + courseLearningMyConfigAuto.getLearning());
return courseLearningMyConfigAuto.toString();
}
}
测试
package com.sunld;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.sunld.controller.PublishController;
@RunWith(SpringRunner.class)
@SpringBootTest
/**
*
* @author sunliaodong
* 使用mockmvc进行,利用MockMvcResultHandlers.print()打印出执行结果。
* 使用MockServletContext来构建一个空的WebApplicationContext,
* 这样我们创建的HelloController就可以在@Before函数中创建并传递到MockMvcBuilders.standaloneSetup()函数中。
*/
public class PublishControllerTest {
@Autowired
private PublishController publishController;
@Before
public void setUp() throws Exception {
//使用new的方式会导致参数获取不到
//mvc = MockMvcBuilders.standaloneSetup(new PublishController()).build();
mvc = MockMvcBuilders.standaloneSetup(publishController).build();
}
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/publishmyconfig").accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("HelloWorld ...."))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
}
随机数
在一些情况下,有些参数我们需要希望它不是一个固定的值,比如密钥、服务端口等。Spring Boot的属性配置文件中可以通过${random}来产生int值、long值或者string字符串,来支持属性的随机值。
增加配置文件random.properties
#随机数配置文件
#获取随机字符串:${random.value}
com.sunld.randomValue=${random.value}
#获取随机int:${random.int}
com.sunld.randomInt=${random.int}
#获取10以内的随机数:${random.int(10)}
com.sunld.ranomdInt10=${random.int(10)}
#获取10-20的随机数:${random.int[10,20]}
com.sunld.randomInt10_20=${random.int[10,20]}
#获取随机long:${random.long}
com.sunld.randomLong=${random.long}
#获取随机uuid:${random.uuid}
com.sunld.randomUuid=${random.uuid}
增加bean
package com.sunld.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@PropertySource(value = {"classpath:/random.properties"}, encoding="UTF-8")
@Component
@ConfigurationProperties(prefix = "com.sunld")
public class RandomConfig {
//获取随机字符串:${random.value}
private String randomValue;
//获取随机int:${random.int}
private String randomInt;
//获取10以内的随机数:${random.int(10)}
private String ranomdInt10;
//获取10-20的随机数:${random.int[10,20]}
private String randomInt10_20;
//获取随机long:${random.long}
private String randomLong;
//获取随机uuid:${random.uuid}
private String randomUuid;
//get\set
public String getRandomValue() {
return randomValue;
}
public void setRandomValue(String randomValue) {
this.randomValue = randomValue;
}
public String getRandomInt() {
return randomInt;
}
public void setRandomInt(String randomInt) {
this.randomInt = randomInt;
}
public String getRanomdInt10() {
return ranomdInt10;
}
public void setRanomdInt10(String ranomdInt10) {
this.ranomdInt10 = ranomdInt10;
}
public String getRandomInt10_20() {
return randomInt10_20;
}
public void setRandomInt10_20(String randomInt10_20) {
this.randomInt10_20 = randomInt10_20;
}
public String getRandomLong() {
return randomLong;
}
public void setRandomLong(String randomLong) {
this.randomLong = randomLong;
}
public String getRandomUuid() {
return randomUuid;
}
public void setRandomUuid(String randomUuid) {
this.randomUuid = randomUuid;
}
@Override
public String toString() {
return "RandomConfig [randomValue=" + randomValue + ", randomInt=" + randomInt + ", ranomdInt10=" + ranomdInt10
+ ", randomInt10_20=" + randomInt10_20 + ", randomLong=" + randomLong + ", randomUuid=" + randomUuid
+ "]";
}
}
增加测试类
package com.sunld;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.sunld.conf.RandomConfig;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RandomConfigTest {
@Autowired
private RandomConfig randomConfig;
@Test
public void testGetRandomConfig() {
System.out.println(randomConfig);
}
}
多环境配置
说明
实际开发中可能会存在不能的环境:开发环境、测试环境、生产环境,而且每个环境的配置文件(数据库配置、日志配置、端口配置等)可能不同,如果每次切换springboot的配置文件相对比较麻烦,还容易出现错误。在spring boot中提供了多环境配置,使得我们切换环境变得简便。
实现
创建文件
在application.properties同目录下根据实际情况创建相关文件:
application-dev.properties//开发环境
application-test.properties//测试环境
application-prod.properties//生产环境
生效
在application.properties添加如下信息:
#多环境配置
spring.profiles.active=dev
#引用测试的配置文件
#spring.profiles.active=test
#引用生产的配置文件
#spring.profiles.active=prod
测试与总结
分别在application-dev.properties、application-test.properties、application-prod.properties中配置server.port为8888、8889、8890,然后使用如下命令测试端口使用情况。
命令 | 端口结果 | 执行文件 |
java -jar ***.jar | 8888 | application-dev.properties |
java -jar ***.jar –spring.profiles.active=test | 8889 | application-test.properties |
java -jar ***.jar –spring.profiles.active=prod | 8890 | application-prod.properties |
通过测试总结如下:
- application.properties中配置通用内容
- 在application.properties中设置spring.profiles.active={profile},比如(spring.profiles.active=dev)开启开发环境为默认文件
- application-{profile}.properties中配置各个环境不同的内容
- 通过命令启用不同的配置
- 文件格式要满足application-{profile}.properties
通过命令行方式修改参数
比如修改端口号,则可以执行以下命令:
java -jar ****.jar --server.port=9090
在命令号中连续输入两个减号+属性名=*,等同于在配置文件中直接配置。虽然通过命令行的方式配置参数比较便利,但是也带来了安全性问题,如果想禁用命令行输入,可以在启动类中增加如下代码:
springApplication.setAddCommandLineProperties(false);
完整代码参考如下:
package com.sunld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApplicationdemoApplication {
public static void main(String[] args) {
// SpringApplication.run(ApplicationdemoApplication.class, args);
/**
* 禁用命令行输入参数
*/
SpringApplication springApplication = new SpringApplication(ApplicationdemoApplication.class);
springApplication.setAddCommandLineProperties(false);
springApplication.run(args);
}
}
总结
配置方式和优先级
这些方式优先级如下:
a. 命令行参数
b. 来自java:comp/env的JNDI属性
c. Java系统属性(System.getProperties())
d. 操作系统环境变量
e. RandomValuePropertySource配置的random.*属性值
f. jar外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
g. jar内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
h. jar外部的application.properties或application.yml(不带spring.profile)配置文件
i. jar内部的application.properties或application.yml(不带spring.profile)配置文件
j. @Configuration注解类上的@PropertySource
k. 通过SpringApplication.setDefaultProperties指定的默认属性
参考地址
@ConfigurationProperties和@EnableConfigurationProperties配合使用
Spring Boot 系列(三)属性配置&自定义属性配置
Spring Boot属性配置文件详解
Spring Boot 属性配置和使用
代码地址
https://github.com/sld880311/springboot-learning/tree/master/applicationdemo