一、使用Spring Initializr 快速创建 Spring Boot 项目
IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目,在创建的过程中,可以选择我们需要的模块(如Spring Web等),向导会联网创建Spring Boot项目
默认生成的Spring Boot项目:
主程序已经生成好了,我们只需要编写自己的业务逻辑,如
package com.hz.spingboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @ResponseBody ://这个类的所有方法返回的数据直接写给浏览器(如果是对象则转为json数据)
* @Controller
* * 上面两个注解等价于@RestController
*/
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello world quick.";
}
}
resources文件夹的目录结构
static:保存所有的静态资源(js,css,images)
templates:保存所有的模板页面(Spring Boot默认jar包使用嵌入式的TomCat,默认不支持JSP页面),可以使用模板引擎(freemarker,thymeleaf)
application.properties:Spring Boot 应用的配置文件,可以修改默认配置,如server.port=8081,将Tomcat的访问端口修改为8081
配置文件:Spring Boot使用一个全局的配置文件,配置文件名固定:
application.properties
application.yml
配置文件的作用:修改SpringBoot自动配置的默认值,SpringBoot在底层都给我们自动配置好
二、YAML(YAML Ain’t Markup Language)
Yet Another Markup Language:仍是一种标记语言
YAML isn’t Markup Language:不是一种标记语言(强调以数据为中心而不是以标记为中心)
以前的配置文件,大多都使用的是 xxx.xml文件,而YAML以数据为中心,比json、xml更适合做配置文件(可以有效的降低各种封闭符号,如引号、各种括号等符号在复杂的嵌套结构中的辨认难度)
YAML配置:
server:
port: 8081
1
2
XML配置:
<server>
<port>8081</port>
</server>
1
2
3
三、YAML语法
1、基本语法
k:(空格)v : 表示一对键值对(空格必须有)
以空格的缩进来控制层级关系,只要是左对齐的一列数据,都是同一个层级的
server:
port: 8081
path: .../hello
1
2
3
属性和值也是大小写敏感的
2、YAML 支持的三种数据结构
字面量 :单个的、不可再分的值(普通的值,如数字,字符串等)
k: v # 字面量直接来写,字符串默认不用加上单引号或双引号
# "":双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi" # 输出 zhangsan 换行 lisi
# ‘’:单引号,会转义特殊字符,特殊字符最终只是一个普通的字符串数
name: 'zhangsan \n lisi' # 输出 zhangsan \n lisi
对象,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]
四、配置文件注入
配置文件(application.yml):
Person:
lastName: 张三
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: v2}
lists:
- 李四
- 王五
dog:
name: 小狗
age: 2
javaBean:
/**
* 将yml配置文件的每一个属性的值,映射到这个组件中
* @ConfigurationProperties : 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
* prefix = "person" : 配置文件中person下面的所有属性进行一一映射
*
* @Component : 只有这个组件是容器中的组件,才能使用容器提供的 @ConfigurationProperties功能
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
我们可以导入配置文件处理器的依赖,以后编写配置就会有提示信息了
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
五、编写单元测试
SpringBoot02ConfigApplicationTests.java
package com.hz.springboot;
import com.hz.springboot.bean.Person;
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;
/**
* SpingBoot单元测试
*
* 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigApplicationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person); // 打印对象会调用对象的toString()方法,若未重写toString()方法,则打印对象的存储地址
}
}
单元测试的打印信息(成功获取到配置文件中的数据):
Person{lastName='张三', age=18, boss=false, birth=Tue Dec 12 00:00:00 CST 2017, maps={k1=v1, k2=v2}, lists=[李四, 王五], dog=Dog{name='小狗', age=2}}
1
使用application.properties配置文件
#idea properties默认使用的是utf-8,出现中文乱码要修改Settings中的File Encodings 将Transparent native-to-ascii conversion 勾上
#配置person的值
person.last-name=张三
person.age=18
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=dog
person.dog.age=15
Tips:若打印时出现中文乱码的情况,修改Settings中的File Encodings 将Transparent native-to-ascii conversion(运行时转换为ASCII码) 勾上
除了使用@ConfigurationProperties(prefix = “person”)注解来绑定person对象的值,还可以使用@Value()注解:
@Value("${person.last-name}")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
测试输出如下:
Person{lastName='张三', age=22, boss=true, birth=null, maps=null, lists=null, dog=null}
1
六、@Value获取值与@ConfigurationProperties获取值的比较
Feature @ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持
配置文件是yml还是properties,两种注解都能获取到值
松散语法绑定(lastName可以写成last-name,X,-x)
SpEL(Spring表达式)
JSR303校验(可以校验数据格式)
复杂类型封装(如map集合)
配置文件注入值数据校验
@Component
@ConfigurationProperties(prefix = "person")
@Validated //数据校验
public class Person {
/**
* <bean>
* <property name="lastName" value="字面量"/${key}从环境变量、配置文件中获取值/#{SpEl}></property>
* </bean>
*/
//@Value("${person.last-name}")
//校验规则:lastName必须是邮箱格式
@Email
private String lastName;
//@Value("#{11*2}")
private Integer age;
//@Value("true")
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
测试输出(数据已校验,报出异常):
总结:
如果我们只是在某个业务逻辑中需要获取一下配置文件中的某项值时,我们才使用@Value注解
package com.hz.springboot.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Value("${person.last-name}")
private String name;
@RequestMapping("/sayHello")
public String sayHello(){
return "Hello "+name;
}
}
如果说,我们专门编写了一个javaBean来和配置文件映射,我们就直接使用@ConfigurationProperties注解
七、@PropertySource&@ImportSource
1、@ConfigurationProperties注解,默认从全局配置文件(application.properties)中获取值,我们在写业务代码时不能将所有的配置信息都写在application.properties中,那样会使得代码结构不清晰,这时我们就需要编写指定的配置文件
@PropertySource(value = {“classpath:person.properties”}):加载指定的配置文件,
然后@ConfigurationProperties(prefix = “person”)就会从person.properties配置文件中获取值
person.properties:
person.last-name=李四
person.age=19
person.birth=2017/12/16
person.boss=true
person.maps.k1=13
person.maps.k2=14
person.lists=a,b,c,d
person.dog.name=二哈
person.dog.age=1
Person.java
@Component
@PropertySource(value = {"classpath:person.properties"})
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
单元测试输出获取到的数据:
Person{lastName='李四', age=19, boss=true, birth=Sat Dec 16 00:00:00 CST 2017, maps={k1=13, k2=14}, lists=[a, b, c, d], dog=Dog{name='二哈', age=1}}
1
2、Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别,@ImportSource:导入Spring的配置文件,让配置文件里面的内容生效(老方法)
beans.xml
<?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="HelloService" class="com.hz.springboot.service.HelloService"></bean>
</beans>
HelloService.java
package com.hz.springboot.service;
public class HelloService {
}
单元测试
@Autowired
ApplicationContext ioc;
@Test
public void testHelloService(){
System.out.println(ioc.containsBean("HelloService"));
}
单元测试输出:
想让Spring的配置文件生效,加载进来,就需要@ImportSource注解,将该注解加在主配置类上@ImportResource(locations = {"classpath:beans.xml"})
package com.hz.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class SpringBoot02ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot02ConfigApplication.class, args);
}
}
再次运行单元测试,观察测试结果:
3、SpringBoot推荐给容器中添加组件的方式:推荐使用全注解的方式
配置类==========Spring配置文件
使用@Bean注解给容器中添加组件(在配置文件中用标签来添加组件,配置类用@Bean注解)
package com.hz.springboot.config;
import com.hz.springboot.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Configuration : 指明当前类是一个配置类,就是来替代之前的Spring配置文件
*
* 在配置文件中用<bean></bean>标签来添加组件
* 配置类用@Bean注解
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
@Bean
public HelloService HelloService(){
System.out.println("配置类@Bean给容器中添加组件了!");
return new HelloService();
}
}