banner
默认放在resources下就行
指定路径需要在yaml中配置,可以指定img和txt
spring:
banner:
location: classpath:static/banner/banner.txt
yaml配置文件
简介
YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
非常适合用来做以数据为中心的配置文件
基本语法‘
- ey: value;kv之间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- '#'表示注释
- 字符串无需加引号,如果要加,''与""表示字符串内容 会被 转义/不转义
数据类型
字面量:单个的、不可再分的值。date、boolean、string、number、null
k: v
对象:键值对的集合。map、hash、set、object
行内写法: k: {k1:v1,k2:v2,k3:v3}
#或
k:
k1: v1
k2: v2
k3: v3
数组:一组按次序排列的值。array、list、queue
行内写法: k: [v1,v2,v3]
#或者
k:
- v1
- v2
- v3
示例
@Data
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salarys;
private Map<String, List<Pet>> allPets;
}
@Data
public class Pet {
private String name;
private Double weight;
}
# yaml表示以上对象
person:
userName: zhangsan
boss: false
birth: 2019/12/12 20:12:33
age: 18
pet:
name: tomcat
weight: 23.4
interests: [篮球,游泳]
animal:
- jerry
- mario
score:
english:
first: 30
second: 40
third: 50
math: [131,140,148]
chinese: {first: 128,second: 136}
salarys: [3999,4999.98,5999.99]
allPets:
sick:
- {name: tom}
- {name: jerry,weight: 47}
health: [{name: mario,weight: 47}]
配置提示
自定义的类和配置文件绑定一般没有提示.
记得配置打包过滤
<!-- 加入提示依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- 配置打包过滤,这个jar只是为了提示,可有可无,让项目在打包的时候不打包这个提示依赖的jar -->
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
修改默认版本号
<!--1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。-->
<!--2、在当前项目里面重写配置-->
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
配置类设置
@Configuration
@Configuration注解表示这是一个配置类,等价与beans.xml
@Configuration有两种模式:
- Full:完全模式
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
- Lite:轻量级模式
- 配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
@Configuration
@Configuration(proxyBeanMethods = false)
public class MyConfig {
}
业务逻辑注解
与spring 一样:@Bean、@Component、@Controller、@Service、@Repository
扫描包
在启动类上有 @SpringBootApplication注解,@SpringBootApplication里面也有@ComponentScan会起冲突,所以一般使用在配置类上
@Configuration
@ComponentScan("com.qc.boot")
public class MyConfig {}
条件装配
@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
| 注解 | 判断 |
|---|---|
| @ConditionalOnBean | 容器内存在指定bean |
| @ConditionalOnClass | 容器中存在指定class |
| @ConditionalOnExpression | 基于Spel表达式作为条件判断 |
| @ConditionalOnJava | 基于jvm版本作为条件判断 |
| @ConditionalOnJndi | 在JNDI存在是查找指定的位置 |
| @ConditionalOnMissingBean | 容器中不存在指定的bean |
| @ConditionalOnMissingClass | 容器中不存在指定的Class |
| @ConditionalOnNotWebApplication | 不是web项目 |
| @ConditionalOnProperty | 指定的属性是否有指定的值 |
| @ConditionalOnResource | 类路径是否有指定的资源 |
| @ConditionalOnWebApplication | 是web项目 |
| @ConditionalOnSingleCandidate | 当指定bean在spring容器中只有一个,或者虽然有多个,但是指定首选的bean |
原生配置文件的引入
在SpringBoot项目中,如果有beans.xml配置文件,就需要使用 @ImportResource引入
@ImportResource("classpath:beans.xml") //引入名为beans.xml的配置文件
public class MyConfig {}
配置绑定
可以在properties(或者yaml)文件中定义属性,在类中使用 @ConfigurationProperties导入,前提是这个类必须在Spring容器中注册了,可以使用@Component注册,或者使用@EnableConfigurationProperties将类注入容器
@Component
@ConfigurationProperties(prefix = "mycar")//@ConfigurationProperties(prefix = "mycar")从配置文件中读取前缀为mycar的属性
@Data
public class Car {
private String name;
private Integer price;
}
@EnableConfigurationProperties({Car.class}) //开启绑定car配置绑定功能,把这个主键制动注册到容器,bean id为全限定名
关闭静态资源
spring:
web:
resources:
add-mappings: false 禁用所有静态资源规则
给静态资源加前缀
#会导致SpringBoot默认首页失效
spring:
mvc:
static-path-pattern: /res/**
静态资源目录
spring
resources:
#两种方式都可以,前面数组可以配置多个
static-locations: [classpath:/haha/]
static-locations: classpath:/b/
欢迎页支持
两种方式
静态资源路径下 index.html
- 可以配置静态资源路径
- 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
controller能处理/index
自定义 Favicon
favicon.ico 放在静态资源目录下即可。
加了静态资源前缀会导致favicon.ico失效。
请求参数处理
请求类型:
- @RequestMapping
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
SpringBoot表单提交默认只支持get和post,如果需要使用其他方法提交,需要手动开启:
开启页面表单的Rest功能
spring:
mvc:
hiddenmethod:
filter:
enabled: true #开启页面表单的Rest功能
还需要在表单中设置隐藏域,告诉Spring这是这是什么方法提交
必须设置为 <input name=“_method” type=“hidden” value=“DELETE”/>
<form action="/h" method="post">
<input name="_method" type="hidden" value="DELETE"/>
<input TYPE="submit" value="提交">
</form>
如果需要更改 _method 参数,则需要手动在配置类配置Bean:
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
hiddenHttpMethodFilter.setMethodParam("_c");
return hiddenHttpMethodFilter;
}
<form action="/hello" method="post">
<input name="_c" type="hidden" value="DELETE"/>
<input TYPE="submit" value="提交">
</form>
基本参数注解
- @PathVariable
- @RequestHeader
- @ModelAttribute
- @RequestParam
- @MatrixVariable
- @CookieValue
- @RequestBody
@RestController
public class ParameterTestController {
// car/2/owner/zhangsan
@GetMapping("/car/{id}/owner/{username}")
public Map<String,Object> getCar(@PathVariable("id") Integer id,
@PathVariable("username") String name,
@PathVariable Map<String,String> pv,
@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String,String> header,
@RequestParam("age") Integer age,
@RequestParam("inters") List<String> inters,
@RequestParam Map<String,String> params,
@CookieValue("_ga") String _ga,
@CookieValue("_ga") Cookie cookie){
Map<String,Object> map = new HashMap<>();
// map.put("id",id);
// map.put("name",name);
// map.put("pv",pv);
// map.put("userAgent",userAgent);
// map.put("headers",header);
map.put("age",age);
map.put("inters",inters);
map.put("params",params);
map.put("_ga",_ga);
System.out.println(cookie.getName()+"===>"+cookie.getValue());
return map;
}
@PostMapping("/save")
public Map postMethod(@RequestBody String content){
Map<String,Object> map = new HashMap<>();
map.put("content",content);
return map;
}
}
矩阵变量
配置
spring boot默认关闭矩阵变量的,如需使用,需要我们去定制:
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
//直接重写
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
//创建UrlPathHelper 修改removeSemicolonContent删除分号为false
UrlPathHelper urlPathHelper = new UrlPathHelper();
//设置不删除分号后面的内容
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
矩阵变量使用示例:
@RestController
public class ParameterTestController {
//1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd
//2、SpringBoot默认是禁用了矩阵变量的功能
// 手动开启:原理。对于路径的处理。UrlPathHelper进行解析。
// removeSemicolonContent(移除分号内容)支持矩阵变量的
//3、矩阵变量必须有url路径变量才能被解析
@GetMapping("/cars/{path}")
public Map carsSell(@MatrixVariable("low") Integer low,
@MatrixVariable("brand") List<String> brand,
@PathVariable("path") String path){
Map<String,Object> map = new HashMap<>();
map.put("low",low);
map.put("brand",brand);
map.put("path",path);
return map;
}
// /boss/1;age=20/2;age=10
@GetMapping("/boss/{bossId}/{empId}")
public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
@MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
Map<String,Object> map = new HashMap<>();
map.put("bossAge",bossAge);
map.put("empAge",empAge);
return map;
}
}
拦截器
实现 HandlerInterceptor 接口,实现preHandle()、postHandle()、afterCompletion()三个方法。
public class LoginInterceptor implements HandlerInterceptor {
/**
* 目标方法执行之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//在这里写处理逻辑比如登录校验。比如在登录mapping中将值放在session中,在这里验证有没有,没有统统跳转到login
//放行返回true,不放行放回false
return false;
}
/**
* 目标方法执行之后
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 页面渲染以后
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
实现WebMvcConfigurer,重写addInterceptors()方法
@Component
public class LoginInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//需要一个HandlerInterceptor,我们传入自己写的拦截器对象
registry.addInterceptor(new LoginInterceptor())
//拦截所有请求
.addPathPatterns("/**")
//不拦截的请求
.excludePathPatterns("/","/login","/toLogin","static/css","static/js","static/images");
}
}
文件上传
html
<form th:action="@{fileUpload}" method="post" ENCTYPE="multipart/form-data">
<input type="file" name="img" value="单个文件上传"/><br/>
<input type="file" name="moreFile" value="多个文件上传" multiple/><br/>
<input TYPE="submit" value="上传"/>
</form>
/**
* 表单文件上传 使用@RequestPart注解
* MultipartFile 文件上传实现
* List<MultipartFile> moreFile 多文件上传,把文件批量封装入list
* @param img
* @return 成功信息
*/
@PostMapping("/fileUpload")
@ResponseBody
public String fileUpload(@RequestPart("img") MultipartFile img,
@RequestPart("moreFile") List<MultipartFile> moreFile){
//打印一下信息
log.info("img.name={},img.getOriginalFilename={},img.size={}",img.getName(),img.getOriginalFilename(),img.getSize());
//路径前缀
String p = "D:\\";
//如果不为空
if (!img.isEmpty()){
try {
String path =p+img.getOriginalFilename();
log.info("path={}",path);
//copy
img.transferTo(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
}
//使用lambda遍历list 把所有文件挨个copy
moreFile.forEach(multipartFile -> {
if (!multipartFile.isEmpty()){
String path =p+multipartFile.getOriginalFilename();
try {
multipartFile.transferTo(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
}
});
return "yes";
}
MultipartFile默认限制大小
两种修改方式
在yaml中配置:
servlet:
multipart:
max-file-size: 512MB
max-request-size: 10GB
在 Configuration 中配置:
@Bean
public MultipartConfigElement multipartConfigElement(){
MultipartConfigFactory multipartConfigFactory = new MultipartConfigFactory();
//指定文件大小
multipartConfigFactory.setMaxFileSize(DataSize.ofBytes(10485760L *1024));
//设置上传文件大小
multipartConfigFactory.setMaxRequestSize(DataSize.ofBytes(10485760L*1024));
return multipartConfigFactory.createMultipartConfig();
}
错误处理
在resources中创建error文件夹,
放入自己实现的error页面(404、500等)
也可以将名字改为 4xx.html 、5xx.html
![]()
druid数据源配置
官方giuhub文档:
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_account
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
druid:
aop-patterns: com.atguigu.admin.* #监控SpringBean
filters: stat,wall # 底层开启功能,stat(sql监控),wall(防火墙)
stat-view-servlet: # 配置监控页功能
enabled: true #开启监控功能
login-username: admin #设置监控页面登录用户
login-password: admin #密码
resetEnable: false #重置功能
web-stat-filter: # 监控web
enabled: true #开启
urlPattern: /* #监控路径
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*' #排除
filter:
stat: # 对上面filters里面的stat的详细配置
slow-sql-millis: 1000
logSlowSql: true
enabled: true
wall: #防火墙
enabled: true #开启
config:
drop-table-allow: false #是否可以删除表
mybatis配置
mybatis官方文档:
传送门
# 配置mybatis规则
mybatis:
#如过要在xml中配置mybatis就需要导入配置文件
# config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
#也可以直接在yaml中配置,mybatis->configuration->~,但是指定了配置文件就不能使用yaml配置
configuration:
#开启驼峰,其他看官方文档
map-underscore-to-camel-case: true
redis配置
默认使用Lettuce
可以更换为jedis,需要导包(默认就行)
<!-- 导入jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
spring:
redis:
host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.com
port: 6379
password: lfy:Lfy123456
client-type: jedis
jedis:
pool:
#连接池最大
max-active: 10
直接在要使用的页面注入 StringRedisTemplate 就可以操作redis了
单元测试
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
idea->直接在要测试的类右键单击->GO TO->Test->Create New Test->填写信息,勾选要测试的方法-> 生成测试类
![]()
![]()
在测试类上加上 @SpringBootTest
常用注解
- @Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
- @ParameterizedTest :表示方法是参数化测试,下方会有详细介绍
- @RepeatedTest :表示方法可重复执行,下方会有详细介绍
- @DisplayName :为测试类或者测试方法设置展示名称
- @BeforeEach :表示在每个单元测试之前执行
- @AfterEach :表示在每个单元测试之后执行
- @BeforeAll :表示在所有单元测试之前执行
- @AfterAll :表示在所有单元测试之后执行
- @Tag :表示单元测试类别,类似于JUnit4中的@Categories
- @Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
- @Timeout :表示测试方法运行如果超过了指定时间将会返回错误
- @ExtendWith :为测试类或测试方法提供扩展类引用
断言
| 方法 | 说明 |
|---|---|
| assertEquals | 判断两个对象或两个原始类型是否相等 |
| assertNotEquals | 判断两个对象或两个原始类型是否不相等 |
| assertSame | 判断两个对象引用是否指向同一个对象 |
| assertNotSame | 判断两个对象引用是否指向不同的对象 |
| assertTrue | 判断给定的布尔值是否为 true |
| assertFalse | 判断给定的布尔值是否为 false |
| assertNull | 判断给定的对象引用是否为 null |
| assertNotNull | 判断给定的对象引用是否不为 null |
数组断言
@Test
@DisplayName("array assertion")
public void array() {
assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
组合断言
assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言,可以通过 lambda 表达式很容易的提供这些断言
@Test
@DisplayName("assert all")
public void all() {
assertAll("Math",
() -> assertEquals(2, 1 + 1),
() -> assertTrue(1 > 0)
);
}
异常断言
在JUnit4时期,想要测试方法的异常情况时,需要用@Rule注解的ExpectedException变量还是比较麻烦的。而JUnit5提供了一种新的断言方式Assertions.assertThrows() ,配合函数式编程就可以进行使用。
@Test
@DisplayName("异常测试")
public void exceptionTest() {
ArithmeticException exception = Assertions.assertThrows(
//扔出断言异常
ArithmeticException.class, () -> System.out.println(1 % 0));
}
超时断言
Junit5还提供了Assertions.assertTimeout() 为测试方法设置了超时时间
@Test
@DisplayName("超时测试")
public void timeoutTest() {
//如果测试方法时间超过1s将会异常
Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}
快速失败
通过 fail 方法直接使得测试失败
@Test
@DisplayName("fail")
public void shouldFail() {
fail("This should fail");
}
前置条件(assumptions)
JUnit 5 中的前置条件(assumptions【假设】)类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要。
@DisplayName("前置条件")
public class AssumptionsTest {
private final String environment = "DEV";
@Test
@DisplayName("simple")
public void simpleAssume() {
assumeTrue(Objects.equals(this.environment, "DEV"));
assumeFalse(() -> Objects.equals(this.environment, "PROD"));
}
@Test
@DisplayName("assume then do")
public void assumeThenDo() {
assumingThat(
Objects.equals(this.environment, "DEV"),
() -> System.out.println("In DEV")
);
}
}
assumeTrue 和 assumFalse 确保给定的条件为 true 或 false,不满足条件会使得测试执行终止。assumingThat 的参数是表示条件的布尔值和对应的 Executable 接口的实现对象。只有条件满足时,Executable 对象才会被执行;当条件不满足时,测试执行并不会终止。
嵌套测试
JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。
@DisplayName("A stack")
class TestingAStackDemo {
Stack<Object> stack;
@Test
@DisplayName("is instantiated with new Stack()")
void isInstantiatedWithNew() {
new Stack<>();
}
@Nested
@DisplayName("when new")
class WhenNew {
@BeforeEach
void createNewStack() {
stack = new Stack<>();
}
@Test
@DisplayName("is empty")
void isEmpty() {
assertTrue(stack.isEmpty());
}
@Test
@DisplayName("throws EmptyStackException when popped")
void throwsExceptionWhenPopped() {
assertThrows(EmptyStackException.class, stack::pop);
}
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
assertThrows(EmptyStackException.class, stack::peek);
}
@Nested
@DisplayName("after pushing an element")
class AfterPushing {
String anElement = "an element";
@BeforeEach
void pushAnElement() {
stack.push(anElement);
}
@Test
@DisplayName("it is no longer empty")
void isNotEmpty() {
assertFalse(stack.isEmpty());
}
@Test
@DisplayName("returns the element when popped and is empty")
void returnElementWhenPopped() {
assertEquals(anElement, stack.pop());
assertTrue(stack.isEmpty());
}
@Test
@DisplayName("returns the element when peeked but remains not empty")
void returnElementWhenPeeked() {
assertEquals(anElement, stack.peek());
assertFalse(stack.isEmpty());
}
}
}
}
参数化测试
参数化测试是JUnit5很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。
利用@ValueSource等注解,指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。
- @ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
- @NullSource: 表示为参数化测试提供一个null的入参
- @EnumSource: 表示为参数化测试提供一个枚举入参
- @CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
- @MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
当然如果参数化测试仅仅只能做到指定普通的入参还达不到让我觉得惊艳的地步。让我真正感到他的强大之处的地方在于他可以支持外部的各类入参。如:CSV,YML,JSON 文件甚至方法的返回值也可以作为入参。只需要去实现ArgumentsProvider接口,任何外部文件都可以作为它的入参。
@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {
System.out.println(string);
Assertions.assertTrue(StringUtils.isNotBlank(string));
}
@ParameterizedTest
@MethodSource("method") //指定方法名
@DisplayName("方法来源参数")
public void testWithExplicitLocalMethodSource(String name) {
System.out.println(name);
Assertions.assertNotNull(name);
}
static Stream<String> method() {
return Stream.of("apple", "banana");
}
迁移指南
在进行迁移的时候需要注意如下的变化:
- 注解在 org.junit.jupiter.api 包中,断言在 org.junit.jupiter.api.Assertions 类中,前置条件在 org.junit.jupiter.api.Assumptions 类中。
- 把@Before 和@After 替换成@BeforeEach 和@AfterEach。
- 把@BeforeClass 和@AfterClass 替换成@BeforeAll 和@AfterAll。
- 把@Ignore 替换成@Disabled。
- 把@Category 替换成@Tag。
- 把@RunWith、@Rule 和@ClassRule 替换成@ExtendWith。
Profile功能
在项目中针对不同的环境有不同的配置文件
比如:
application-prod.yaml 生产环境
application-test.yaml 测试环境
在默认配置文件中指定配置文件
#激活生产文件
spring.profiles.active=prod
命令行激活
#--spring.profiles.active=prod 启动jar时指定环境 --person.name=haha还可以给文件中定义的属性赋值
java -jar xxx.jar --spring.profiles.active=prod --person.name=haha
@Profile条件装配功能
@Configuration(proxyBeanMethods = false)
@Profile("prod") //如果是这个环境,这个类或者方法生效
public class ProductionConfiguration {
// ...
}
外部配置源
常用:Java属性文件、YAML文件、环境变量、命令行参数;
配置文件查找位置
- classpath 根路径
- classpath 根路径下config目录
- jar包当前目录
- jar包当前目录的config目录
- /config子目录的直接子目录
配置文件加载顺序
- 当前jar包内部的application.properties和application.yml
- 当前jar包内部的application-{profile}.properties 和 application-{profile}.yml
- 引用的外部jar包的application.properties和application.yml
- 引用的外部jar包的application-{profile}.properties 和 application-{profile}.yml
指定环境优先,外部优先,后面的可以覆盖前面的同名配置项