目录
入门部分
1.Spring Boot 简介
简化Spring应用开发的一个框架;
整个Spring技术栈的一个大整合;
J2EE开发的一站式解决方案;
2.微服务
2014,martin fowler
微服务:架构风格(服务微化)
一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;
单体应用:ALL IN ONE
微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;
3.环境准备
SpringBoot2.0环境约束
- jdk1.8+;java version “1.8.0_112”
- maven 3.3+;Apache Maven 3.5.4
- A favorite text editor or IDE:IntelliJ IDEA 2018.2.6
- SpringBoot 2.1.1.RELEASE
4.Maven配置
给$M2_HOME\conf\settings.xml
配置文件t添加如下内容
- 在之间添加如下内容
- 作用:国内maven仓库镜像(众所周知的原因国内不能很好的访问maven中央仓库)
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
- 在 之间添加如下内容
- 作用:指定项目编译运行使用的JDK版本
<profile>
<id>jdk-1.8</id>
<activation>
<jdk>1.8</jdk>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
<!-- 如果是在学校或公司有maven私服,可以在这里配置私服 -->
<repositories>
<repository>
<id>accp</id>
<name>accp</name>
<url>http://192.168.1.48:8081/repository/accp/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<!-- 如果没有私服,这里不用配置 -->
</profile>
5.IDEA配置
整合Maven进来
6.修改Banner
| |
文字Banner可以从这个网站生成(有很多种字体样式可以选择)
http://patorjk.com/software/taag
${AnsiColor.BLUE} 表示Banner文字的颜色
${spring-boot.version} 当前使用的SpringBoot版本
7.使用IDEA创建一个项目
- 目录结构说明
- src/main/java: Java代码的目录
- src/main/resources: 资源目录
- src/test/java: 测试代码的目录
- src/test/resources: 测试资源目录
- POM文件说明
8.添加Banner文件
在resources目录下创建banner.txt文件,添加以下内容
可以更换成你自己的banner
${AnsiColor.BLUE}
_______ _______ ______
| || || |
|____ || ___|| _ |
____| || |___ | | | |
| ______|| ___|| |_| |
| |_____ | |___ | |
|_______||_______||______|
-----版本号-----${spring-boot.version}
9.创建Controller类
- 文件模板修改
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloWorld {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
@ResponseBody //不加这行注解返回的是字符串其实是一个逻辑的说明,拼接了前缀后缀去找真正的视图,要想返回文本就需要加上这个注解
public String hello() {
return "hello SpringBoot";
}
}
直接右上角运行
- 注解的方式还有一种,和上面的效果一样
如果这个类下面的所有方法都是加了@ResponseBody注解,我们可以把@Controller和@ResponseBody去掉,仅使用@RestController注解
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorld {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return "hello SpringBoot";
}
}
- 还可以简化
如果我们使用的是@RequestMapping的GET请求可以简化使用@GetMapping注解
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorld {
@GetMapping("/hello")
public String hello() {
return "hello SpringBoot";
}
}
注解说明:
@RestController: 处理http请求:等同于@Controller+@ResponseBody @RequestMapping: value = "访问的路由" method = 请求方法 @GetMapping:以GET方式请求 相当于对@RequestMapping配置的缩写
10.一个方法映射多个URL地址
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorld {
@GetMapping({"/hello", "/hi"}) //注意这里的{}
public String hello() {
return "hello SpringBoot";
}
}
11.窄化请求
类和方法都有value时,访问的地址是类上的地址拼接上方法上的地址。
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")//这个地址就叫做窄化请求
public class HelloWorld {
@GetMapping("/hello")
public String hello() {
return "hello SpringBoot";
}
}
http://localhost:8080/user/hello
12.其他创建方式
- SPRING INITIALIZR:通过IDEA或者STS工具创建INITIALIZR项目(上面所写的项目创建就是这样)
- 创建Maven项目手动添加依赖
- 通过https://start.spring.io/ 生成定制项目
下面我们演示,创建Maven项目手动添加依赖
手动添加依赖
启动类需要自己手动编写,类名叫什么无所谓,但是必须添加一个注解叫@SpringBootApplication,然后在写一个main方法,
然后再编写一下他的控制器类,跟之前我们写的一样
启动,启动完成后会扫描的类
下面我们演示,通过https://start.spring.io/ 生成定制项目
最后会下载一个ZIP包,我们可以解压到桌面然后通过IDEA导入这个项目
选择刚才解压的文件夹,一直下一步就行了
然后跟之前一样分开写类也可以跟下面一样写一起。
13.其他运行方式
- 在IDE中直接运行
- 发布Jar包运行
在pom/xml文件引用插件
<!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
导入这个maven插件,利用idea打包,
生成的jar包,可以使用java -jar xxx.jar
启动
Spring Boot 使用嵌入式的Tomcat无需再配置Tomcat
讲原理部分
1、从POM文件讲原理
父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
spring-boot-starter-parent他的父项目是:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
这是真正管理Spring Boot应用里面所依赖的版本
Spring Boot的版本仲裁中心;
以后我们导入依赖默认是不需要写版本;
(没有在dependencies里面管理的依赖自然需要声明版本号)
太多了就放两张图感受一下就行啦。
2、启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
我们去他的官网看一下
spring-boot-starter-web:
spring-boot-starter:spring-boot场景启动器,帮我们导入了web模块正常运行所依赖的组件;
点击进去可以看到帮我们引入很多web相关的依赖
Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter相关场景的所有依赖都会导入进来,要用什么功能就导入什么场景的启动器
3、主程序类,主入口类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication : Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
点进去这个注解可以看到下面的源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
- @SpringBootConfiguration : Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类
- @Configuration : 配置类上来标注这个注解,配置类也是容器中的一个组件@Component
- @EnableAutoConfiguration:开启自动配置功能
点击@SpringBootConfiguration可以看到下面的源码,这是SpringBoot的底层的注解叫@Configuration,之前我们在使用Spring的时候会出现大量的XML文件,后来在使用SpringBoot之后推荐我们使用类+注解的形式来使用配置,就再也不会出现大量的XML文件了,所以某些类要是做配置类必须加上@Configuration来标注他是配置类
点击@EnableAutoConfiguration可以看到下面的源码
- 将主配置类(@SpringBootApplication标注的类 )的所在包及下面所有子包里面的所有组件都可以扫描到Spring容器;
下面我们做个试验
可以看到在启动类和控制器类在不同的包下面,那么我们在访问控制器类发现找不到了
所以我们一般会把启动类放在外层
- 调用了
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader)
; - Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;
- 以前我们需要自己配置的东西,自动配置类都帮我们;
- 有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;
- J2EE的整体整合解决方案和自动配置都在
spring-boot-autoconfigure-1.5.9.RELEASE.jar
;
4、自动配置原理
1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2)、@EnableAutoConfiguration 作用:
-
利用EnableAutoConfigurationImportSelector给容器中导入一些组件?
-
可以查看selectImports()方法的内容;
-
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下 META-INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中
将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中
精髓:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
xxxxAutoConfigurartion:自动配置类(给容器中添加组件);
xxxxProperties:封装配置文件中相关属性;
参数传递
参数传递可以说是服务端和外界沟通的主要方式
本段内容包括:
通过url传参
|---get方式Url传参
|---@PathVariable 即:url/id/1994 形式
|---@RequestParam 即:url?username=zed形式
|---POST方式传参
|---@RequestParam
|---请求体中加入文本
配置文件传参
1.get方式Url传参:
@PathVariable 路径传参,可以在路径上拼接参数的
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello/{name}")
public String hello(@PathVariable("name") String name) {
// 最后一个name是形参name,名字可以随意,但是前两个要保持一致
return "hello " + name;
}
}
2.get方式Url传参:
@RequestParam
如果请求参数的名字跟方法中的形参名字一致可以省略@RequestParam(“name”)
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam("name") String name) {
System.out.println("获取到的name是:" + name);
return "hello " + name;
}
}
如果请求参数的名字跟方法中的形参名字一致可以省略@RequestParam(“name”),如下
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(String name) {
System.out.println("获取到的name是:" + name);
return "hello " + name;
}
}
3.get方式Url传参:
@RequestParam+默认参数
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "admin") String n) {
System.out.println("获取到的name是:" + n);
return "hello " + n;
}
}
注意:如果没有指定默认值,并且没有传递参数将会报错
Required String parameter 'name' is not present
:name参数没有提供
- 解决方案
- 1.defaultValue = “xxx” :使用默认值
- 2.required = false :标注参数是非必须的
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", required = false) String n) {
System.out.println("获取到的name是:" + n);
return "hello " + n;
}
}
4.POST方式传递数据
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
Logger log = LoggerFactory.getLogger(HelloController.class);
@PostMapping("/hello")
public String add(@RequestParam("name") String name, @RequestParam("age") Integer age) {
log.info(name + " " + age);
log.info(age.getClass().getSimpleName()); //打印age的类型,可以自动帮我们转的
return "name:" + name + "\nage:" + age;
}
}
因为POST请求不好通过浏览器模拟,所以我们使用Postman软件来实现
5.POST传递字符串文本
通过HttpServletRequest获取输入流
package com.example.demo.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@RestController
public class HelloController {
@PostMapping("/postString")
public String postString(HttpServletRequest request) {
ServletInputStream is = null;
StringBuilder sb = null;
try {
is = request.getInputStream(); //所有请求体中的内容会封装到request上。
sb = new StringBuilder();
byte[] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) != -1) {
sb.append(new String(buf, 0, len));
}
System.out.println(sb.toString());
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
6.@requestbody接收参数
- @requestbody可以接收GET或POST请求中的参数
- 把json作为参数传递,要用【RequestBody】
- 附带着说一下使用postman方式设置content-type为application/json方式测试后台接口
下面是User的pojo类
package com.example.demo.pojo;
public class User {
private String username;
private String age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
package com.example.demo.controller;
import com.example.demo.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
Logger log = LoggerFactory.getLogger(HelloController.class);
@PostMapping("/user")
public String user(@RequestBody User user) {
log.info(user.toString());
return null;
}
}
SwaggerAPI框架
为了方便上面的API接口调试,我们可以使用:
- Postman:模拟POST请求
- Swagger:描述和测试API接口
1.添加依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
2.Swagger配置
yml配置文件
swagger:
title: SpringBoot学习
description: SpringBoot快速入门
version: 1.0.0
name: jenrey
url: https://jenrey.csdn.net
email: jenrey@foxmail.com
新建一个config包,下面新建一个SwaggerConfig.java文件,内容如下
package com.example.demo.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration //配置类必须要加这个注解
@EnableWebMvc //必须加上
@EnableSwagger2 //必须加上
@ConfigurationProperties(prefix = "swagger") //把yml里面的基本信息导入到我们的配置类中,并制定前缀
@Data
//因为我们是API接口文档它必须要扫描控制器层,而控制器这些类在哪个包下面我们必须指定一下,通过一个组件扫描指定一下控制器所在的包
@ComponentScan(basePackages = {"com.example.demo.controller"})
public class SwaggerConfig {
private String title; //下面这些值我们直接在配置文件里面去写
private String description;
private String version;
private String name;
private String url;
private String email;
@Bean //用注解的方式创建的Bean,生成的Bean是放到容器里面了,生成一个docker,docker要配置一个API的基本信息info
public Docket customDocket() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
Contact contact = new Contact(name, url, email); //然后基本信息里面有个联系人,需要联系人的姓名,url地址,邮箱
return new ApiInfoBuilder() //返回一个ApiInfoBuilder
.title(title)
.description(description)
.contact(contact)
.version(version)
.build(); //是用创建者方式调用build方法,帮我们返回一个ApiInfo给它放到容器里面
}
}
新建一个WebMvcConfig.java文件,写入下面代码
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
class WebMvcConfig implements WebMvcConfigurer {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
上面两个写好了之后就可以使用Swagger注解了,比如我们写一个控制类,来测试一下Swagger
3.使用注解
在控制器API上添加接口描述的注解
package com.example.demo.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Api(value = "用户模块的控制器")//注释这个类是干嘛的,我们使用Swagger下面的@Api注解
public class HelloSwagger {
Logger log = LoggerFactory.getLogger(HelloSwagger.class);
@GetMapping("/hello")
@ApiOperation(value = "测试Swagger") //描述接口作用的
/*
@ApiImplicitParams(
{@ApiImplicitParam(),@ApiImplicitParam()}
) //有多参数用这个
*/
public String hello() {
return "hello SpringBoot-Swagger";
}
}
然后我们运行一下SpringBoot
输入上述的地址可以看到是Swagger的描述信息
http://localhost:8080/v2/api-docs
http://localhost:8080/swagger-ui.html
Swagger的具体用法,请参照 B站Swagger视频
4.Webjars的使用
其实就是把我们常用的一些,像jquery,BootStrap等组件都有Webjars的引入方式
把下面的配置写的pom中其实就是在我们的项目中添加了jquery
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1-1</version>
</dependency>
通过jar包的方式引入了jQuery
再浏览器中可以通过如下地址访问到
地址说明:/webjars/jquery/3.3.1-1/jquery.js
对应上面的 webjars/ artifactId/version/文件名
可以到项目中的jar包中具体查看。
所以我们通过这样的一个路径就可以请求到JQ了,是一种通过jar包来引入的方式,并不是向之前一样从官网或者其他地方下载一个JQ添加到我们的项目工程资源路径下。现在根本不需要了,直接引入jar包
springboot-配置文件的使用
1、配置文件的使用
修改配置方式1:src\main\resources\application.properties**
#修改端口号
server.port=8081
#端口号后需额外添加字符
server.servlet.context-path=/demo
@RestController
public class HelloWorld {
@GetMapping("/hello")
public String say() {
return "HelloWorld!";
}
}
修改配置方式2:src\main\resources\application.yml
server:
port: 8081
servlet:
context-path: /zed
个人比较喜欢yml
2、切换配置文件
1、多配置文件
src\main\resources\application-dev.yml
server:
port: 8081
src\main\resources\application-prod.yml
server:
port: 8080
src\main\resources\application.yml
- 根据active:来切换配置文件
spring:
profiles:
active: prod
注意active后面写那个就是激活那个配置文件
2、单配置文件(分块)
- 在单一文件中,可用连续三个连字号(—)区分多个文件。
- 根据active:来切换配置文件
server:
port: 8081
spring:
profiles: prod
---
server:
port: 8080
spring:
profiles: dev
---
spring:
profiles:
active: prod
spring profiles是配置块的名称。
3、激活指定profile
1、在配置文件中指定 spring.profiles.active=dev
2、命令行:
java -jar ***.jar –spring.profiles.active=dev
可以直接在测试的时候,配置传入命令行参数
3、虚拟机参数,在IDEA或Eclipse中的run configuration中可以进行配置
-Dspring.profiles.active=dev
4、配置文件加载位置
springboot 启动后扫描以下位置的application.properties或者application.yml文件,
作为Spring boot的默认配置文件
位置 | 说明 |
---|---|
–file:./config/ | 项目目录下的config |
–file:./ | 项目目录下 |
–classpath:/config/ | resources目录下的config |
–classpath:/ | resources目录下 |
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;
指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar ***.jar –spring.config.location=E:/application.yml
从spring的运行日志中可以看到:
Loaded config file 'file:./config/application.yml' (file:./config/application.yml)
Loaded config file 'file:./application.yml' (file:./application.yml)
Loaded config file 'file:/C:/Users/Administrator/Desktop/demo3/target/classes/config/application.yml' (classpath:/config/application.yml)
Loaded config file 'file:/C:/Users/Administrator/Desktop/demo3/target/classes/application.yml' (classpath:/application.yml)
配置文件的加载顺序:
- ./config/application.yml 项目目录下的config目录下的配置文件
- ./application.yml 项目目录下的配置文件
- classpath:/config/application.yml 资源路径下的config 目录下的配置文件
- classpath:/application.yml 资源路径下的配配置文件
总结:
- 先加载的优先级最高,后面的优先级低。
- 后面的配置文件中如果有不同的配置项,也会读取进来。
springboot-配置文件详解
1.YML是什么
SpringBoot使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
配置文件的作用:修改SpringBoot自动配置的默认值;
YAML(YAML Ain’t Markup Language)
YAML A Markup Language:是一个标记语言
YAML isn’t Markup Language:不是一个标记语言
标记语言:
以前的配置文件;大多都使用的是 xxx.xml文件;
YAML:以数据为中心,比json、xml等更适合做配置文件;
- YAML:配置例子
server:
port: 8081
- XML:配置例子
<server>
<port>8081</port>
</server>
2.YML语法
k:(空格)v:表示一对键值对(空格必须有);
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
server:
port: 8081
path: /hello
属性和值也是大小写敏感;
字面量
普通的值(数字,字符串,布尔)
k: v 字面量直接来写
字符串默认不用加上单引号或者双引号;
"":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi":输出;zhangsan 换行 lisi
'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
总结:
对于字串的值,直接写和加上单引号的效果是一样,字串的内容原样输出,如果要使用特殊的字符的功能,需要加上双引号,比如说:\n如果是再双引号中的就作为换行了。
对象、Map
(属性和值)(键值对):
k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan, age: 18}
数组
(List、Set):
用 - 值表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法
pets: [cat, dog, pig]
springboot-配置文件的注入
1、单值注入
使用@Value注解注入单个属性的值
- yml配置文件
swagger:
title: SpringBoot学习
description: SpringBoot快速入门
version: 1.0.0
name: jenrey
url: http://jenrey.csdn.net
email: jenrey@foxmail.com
#server:
# #端口号
# port: 8888
person:
name: jenrey
age: 24
- java代码
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ValueTest {
@Value("${person.name}")
private String name;
@Value("${person.age}")
private String age;
Logger log = LoggerFactory.getLogger(ValueTest.class);
@GetMapping("/value")
public String user() {
log.info("name=" + name + ",age=" + age);
return "Hello 配置文件参数注入";
}
}
${key} :来引用属性文件中key对应的值
2、批量注入
使用@ConfigurationProperties注解批量注入配置文件中的多个值
- yml配置文件
person:
lastName: 大汤圆
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1, k2: 12}
lists:
- 张三
- 李四
dog:
name: 小奶狗
age: 2
@Data是一个lomlok插件,免去了getter/setter和toString这些繁琐的东西
在POM文件的节点中间添加
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
- 新建一个Person的Pojo类,代码如下
package com.example.demo.pojo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
//封装配置文件中person中的数据
@ConfigurationProperties(prefix = "person")
@Component
@Data
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<String> lists;
private Dog dog;
}
- 新建一个Dog的Pojo类,代码如下
package com.example.demo.pojo;
import lombok.Data;
@Data
public class Dog {
private String name;
private Integer age;
}
使用@ConfigurationProperties注解必须同时添加@Component将当前的配置类放入IOC容器中
在编写yml文件的时候没有出现属性提示:
我们可以导入配置文件处理器,以后编写配置就有提示了
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
发现变成了下面的灰色
我们重新启动IDEA,点击一下 隐藏通知 就行啦。
- 测试代码
package com.example.demo.controller;
import com.example.demo.pojo.Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigurationPropertiesTest {
Logger log = LoggerFactory.getLogger(ConfigurationPropertiesTest.class);
//把容器里的装配进来
@Autowired
private Person person;
@GetMapping("/test")
public String hello() {
log.info(person.toString());//toString()方法我们不用写,@Data自动帮我们写了
return "hello";
}
}
- 控制台的输出
Person(lastName=大汤圆, age=18, boss=false, birth=Tue Dec 12 00:00:00 CST 2017, maps={k1=v1, k2=12}, lists=[张三, 李四], dog=Dog(name=小奶狗, age=2))
javaBean:
- 将配置文件中配置的每一个属性的值,映射到这个组件中
- @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
- prefix = “person”:配置文件中哪个下面的所有属性进行一一映射
- 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
- @Data是一个插件,,免去了getter/setter和toString这些繁琐的东西
3、两种注入的区别
@Value获取值和@ConfigurationProperties获取值的区别
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL: #{} | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
松散语法绑定:last_name = last-name = lastName 他们取的值都是相同的
配置文件yml还是properties他们都能获取到值;
总结:
- 如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
- 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
4、注入值的数据校验
@ConfigurationProperties(prefix = "person")
@Component
@Data
@Validated //数据校验
public class Person {
@Email(message = "用户名必须是一个正确的邮箱格式")
private String lastName;
@Max(value = 200,message = "年龄不能超过200岁")
@Min(value = 0,message = "年龄必须大于0岁")
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<String> lists;
private Dog dog;
}
经过刚才的测试得出,两个注解不能同时作用在一个属性上。
springboot-其他配置文件
1、@PropertySource
@PropertySource:加载指定的配置文件;
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
// lastName必须是邮箱格式
// @Email
// @Value("${person.last-name}")
private String lastName;
// @Value("#{11*2}")
private Integer age;
// @Value("true")
private Boolean boss;
请注意 [字串,bool,时间,列表可以注入],map不能注入,
简单的数据类型Spring注入数据后进行了类型转换
断点查看可以知道注入的数据
person.lastName=hehe@foxmail.com
person.age=18
person.boss=false
person.birth=2017/12/12
person.lists=lisi,zhaoliu
People(lastName=hehe@foxmail.com, age=18, pets=null, boss=false, birth=Tue Dec 12 00:00:00 CST 2017, lists=[[lisi, zhaoliu]])
IDEA设置*.properties文件的默认编码
Settings
–> Editor
–> File Encoding
–> Properties Files(*.properties)
–> Default encoding for properties files:
UTF-8
–> OK
2、@ImportResource
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
想让Spring的配置文件生效,@ImportResource标注在一个配置类上
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
- Spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="p123" class="site.accp.demo7.pojo.People">
<property name="lastName" value="123"/>
</bean>
</beans>
- 测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo7ApplicationTests {
@Autowired
ApplicationContext ioc;
@Test
public void contextLoads() {
boolean p123 = ioc.containsBean("p123");
System.out.println(p123);
}
}
3、@Bean
SpringBoot推荐使用全注解的方式给容器中添加组件
1、配置类@Configuration –> Spring配置文件
2、使用@Bean给容器中添加组件
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
* 在配置文件中用<bean><bean/>标签添加组件
*/
@Configuration
public class MyAppConfig {
// 将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new HelloService();
}
}
测试:
@Test
public void testHelloService() {
boolean b = ioc.containsBean("helloService02");
System.out.println(b); // true
}
输出:配置类@Bean给容器中添加组件了… 同时返回true
4、配置文件占位符
- 随机数
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
- 占位符获取之前配置的值
如果没有可以使用的:指定默认值
person.last-name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
# 没有取到:后面是默认值
person.dog.name=${person.hello:hello}_dog
person.dog.age=15