一、Spring Boot入门
1、Spring Boot简介
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
2、微服务
微服务:架构风格(服务微化)
一个应用应该是一组小型服务,可以通过HTTP的方式进行互通
单体应用:ALL IN ONE
微服务:每个功能元素最终都是一个可以独立替换和升级的软件单元
3、环境准备
环境约束
jdk1.8
maven 3.x :maven3.3以上
IDEA2017
SpringBoot 1.5.9RELEASE
1、MAVEN设置
nexus-aliyun 首选,放第一位,有不能下载的包,再去做其他镜像的选择
nexus-aliyun central Nexus aliyun http://maven.aliyun.com/nexus/content/groups/public<!-- 备选镜像,也是可以通过 url 去查找确定一下,
该镜像是否含有你想要的包,它比 spring-libs-milestone 快 -->
central-repository * typorCentral Repository http://central.maven.org/maven2/
2、IDEA设置
配置IDEA的Maven,指定Setting的Maven目录和MAVEN的setting.xml文件
快捷键:
Ctrl+D 复制一行
Ctrl+Y 删除一行
Ctrl+P 参数提示
Ctrl+Alt+V 自动补齐方法
Ctrl+N 查找类方法
Alt+Ins 构造器、getter/setter toString
Ctrl+O 重载方法提示
Alt+Enter 提示导入类etc
Shift+F6 :文件重命名
4、Spring Boot的Hello World
1、创建一个Maven工程
2、导入Spring Boot的相关依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3、编写个主程序
@SpringBootApplication
public class SpringBoot01HelloQuickApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot01HelloQuickApplication.class, args);
}
}
4、编写相应的Controller和Service
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "hello world";
}
}
5、运行主程序测试
访问 localhost:8080/hello
6、简化部署
在pom.xml文件中,导入build插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
5、HelloWorld深度理解
1.POM.xml文件
1、父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.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.0.1.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
下面有个属性,定义了对应的版本号
<properties>
<activemq.version>5.15.3</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.63</appengine-sdk.version>
<artemis.version>2.4.0</artemis.version>
<aspectj.version>1.8.13</aspectj.version>
<assertj.version>3.9.1</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<bitronix.version>2.1.4</bitronix.version>
<build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
。。。。。。。
Spring Boot的版本仲裁中心 会自动导入对应的版本,不需要我们自己导入依赖,没有dependencies里面管理的依赖自己声明
2、启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
**spring-boot-starter-web:**帮我们导入web模块正常运行所依赖的组件
spring boot将所有的功能场景都抽取出来,做成一个个的starter(启动器),只需要在项目里引入这些starter相关场景的所有依赖都会被导入进来,要用什么功能就导入什么场景的启动器。
2、主程序入口
@SpringBootApplication
public class SpringBoot01HelloQuickApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot01HelloQuickApplication.class, args);
}
}
@SpringBootApplication: 说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动应用
进入SpringBootApplication注解
@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:SpringBoot的配置类: 标准在某个类上,表示这是一个SpringBoot的配置类
@Configuration:配置类上,来标注这个注解; 配置类 ---- 配置文件,也是容器中的一个组件(@Component) @EnableAutoConfiguration:开启自动配置功能 以前需要自动配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动 配置功能;这样自动配置才能生效。
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自动配置包 @Import({Registrar.class}):底层注解,给容器导入组件; 将主配置类(@SpringBootApplication标注的类)的所在包及下面所有的子包里面的所有组件扫描到Spring容器;
@Import({AutoConfigurationImportSelector.class}): 给容器导入组件?
AutoConfigurationImportSelector:导入组件选择器
将所有需要导入的组件以及全类名的方式返回;这些组件将以字符串数组 String[] 添加到容器中;
会给容器非常多的自动配置类,(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置 好这些组件。
1.configuration
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations =
SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(),
this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META‐INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Spring Boot在启动的时候从类路径下的META-INF/spring.factorys中获取的EnableAutoConfiguration指定的值;
将这些值作为自动配置类导入到容器中,自动配置就生效了。 2.factories
J2EE的整体解决方案
org\springframework\boot\spring-boot-autoconfigure\2.0.1.RELEASE\spring-boot-autoconfigure-2.0.1.RELEASE.jar
6、使用Spring Initializer创建一个快速向导
1.IDE支持使用Spring Initializer
自己选择需要的组件:例如web
默认生成的SpringBoot项目
主程序已经生成好了,我们只需要完成我们的逻辑
resources文件夹目录结构
static:保存所有的静态文件;js css images
templates:保存所有的模板页面;(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP);可
以使用模板引擎(freemarker.thymeleaf);
application.properties:Spring Boot的默认配置,例如 server.port=9000
二、配置文件
1、配置文件
Spring Boot使用全局配置文件,配置文件名是固定的;
application.properties
application.yml
配置文件作用:修改Spring Boot在底层封装好的默认值;
YAML(YAML AIN’T Markup Language)
是一个标记语言
又不是一个标记语言
标记语言:
以前的配置文件;大多数使用的是 xxx.xml文件;
以数据为中心,比json、xml等更适合做配置文件
YAML:配置例子
server:
port: 9000
XML:
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一层级的
server:
port: 9000
path: /hello
属性和值也是大小写敏感
2、值的写法
字面量:普通的值(数字,字符串,布尔)
k: v:字面直接来写;
字符串默认不用加上单引号或者双引号
“”:双引号 不会转义字符串里的特殊字符;特殊字符会作为本身想要表示的意思
name:“zhangsan\n lisi” 输出:zhangsan换行 lisi
‘’:单引号 会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name:‘zhangsan\n lisi’ 输出:zhangsan\n lisi
对象、Map(属性和值)键值对
k :v :在下一行来写对象的属性和值的关系;注意空格控制缩进
对象还是k:v的方式
frends:
lastName: zhangsan
age: 20
行内写法
friends: {lastName: zhangsan,age: 18}
数组(List、Set): 用-表示数组中的一个元素
pets:
‐ cat
‐ dog
‐ pig
行内写法
pets: [cat,dog,pig]
组合变量
多个组合到一起
3、配置文件值注入
1、@ConfigurationProperties
1、application.yml 配置文件
person:
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: 12}
lists:
- lisi
- zhaoliu
dog:
name: wangwang
age: 2
last-name: wanghuahua
application.properties 配置文件(二选一)
idea配置文件utf-8
properties 默认GBK
person.age=12
person.boss=false
person.last-name=张三
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=wanghuahu
person.dog.age=15
所以中文输出乱码,改进settings–>file encoding -->[property–>utf-8 ,勾选转成ascii]
javaBean
/**
- 将配置文件的配置每个属性的值,映射到组件中
- @ConfigurationProperties:告诉SpringBoot将文本的所有属性和配置文件中的相关配置进行绑定;
- prefix = “person” 配置文件爱你的那个属性进行一一映射
-
只有这个组件是容器中的组件,才能提供到容器中
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
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>
2、@Value注解
更改javaBean中的注解
@Component
public class Person {
/**
* <bean class="Person">
* <property name="lastName" value="字面量/${key}从环境变量/#{spEL}"></property>
* </bean>
*/
@Value("${person.last-name}")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
@ConfigurationProperties @Value
功能 批量注入配置文件属性 单个指定
松散绑定(语法) 支持 不支持
spEL 不支持 支持
JSR303校验 支持 不支持
复杂类型 支持 不支持
松散语法:javaBean中last-name(或者lastName) -->application.properties中的last-name;
spEL语法:#{11*2}
JSR303:@Value会直接忽略,校验规则
JSR303校验:
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email
private String lastName;
复杂类型栗子:
@Component
public class Person {
/**
* <bean class="Person">
* <property name="lastName" value="字面量/${key}从环境变量/#{spEL}"></property>
* </bean>
*/
private String lastName;
private Integer age;
private Boolean boss;
// @Value("${person.maps}")
private Map<String,Object> maps;
以上会报错,不支持复杂类型
使用场景分析
如果说,我们只是在某个业务逻辑中获取一下配置文件的某一项值,使用@Value;
如果专门编写了一个javaBean和配置文件进行映射,我们直接使用@ConfigurationProperties
举栗子:
1、编写新的Controller文件
@RestController
public class HelloController {
@Value("${person.last-name}")
private String name;
@RequestMapping("/hello")
public String sayHello(){
return "Hello"+ name;
}
}
2、配置文件
person.age=12
person.boss=false
person.last-name=李四
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=wanghuahu
person.dog.age=15
3、测试运行
访问 localhost:9000/hello
结果为Hello 李四
3、其他注解
@PropertySource
作用:加载指定的properties配置文件
1、新建一个person.properties文件
person.age=12
person.boss=false
person.last-name=李四
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=wanghuahu
person.dog.age=15
2、在javaBean中加入@PropertySource注解
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
@ImportResource
作用:导入Spring配置文件,并且让这个配置文件生效
1、新建一个Spring的配置文件,bean.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.wdjr.springboot.service.HelloService"></bean>
2、编写测试类,检查容器是否加载Spring配置文件写的bean
@Autowired
ApplicationContext ioc;
@Test
public void testHelloService(){
boolean b = ioc.containsBean("HelloService");
System.out.println(b);
}
import org.springframework.context.ApplicationContext;
3、运行检测
结果为false,没有加载配置的内容
4、使用@ImportResource注解
将@ImportResource标注在主配置类上
@ImportResource(locations={"classpath:beans.xml"})
@SpringBootApplication
public class SpringBoot02ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot02ConfigApplication.class, args);
}
}
5、再次运行检测
结果为true
缺点:每次指定xml文件太麻烦
SpringBoot推荐给容器添加组件的方式:
1、配置类=====Spring的xml配置文件(old)
2、全注解方式@Configuration+@Bean(new)
4.MyAppConfig
/**
-
@Configuration:指明当前类是一个配置类;就是来代替之前的Spring配置文件
-
在配置文件中用标签添加组件
*/@Configuration public class MyAppConfig { //将方法的返回值添加到容器中;容器这个组件id就是方法名 @Bean public HelloService helloService01(){ System.out.println("配置类给容器添加了HelloService组件"); return new HelloService(); } } @Autowired ApplicationContext ioc; @Test public void testHelloService(){ boolean b = ioc.containsBean("helloService01"); System.out.println(b); }
容器这个组件id就是方法名
4、配置文件占位符
1、随机数
r
a
n
d
o
m
.
v
a
l
u
e
、
{random.value} 、
random.value、{random.int}、${random.long}
r
a
n
d
o
m
.
i
n
t
(
10
)
、
{random.int(10)}、
random.int(10)、{random.int[100,200]}
2、获取配置值
person.age=${random.int}
person.boss=false
person.last-name=张三${random.uuid}
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=${person.last-name}'s wanghuahu
person.dog.age=15
存在以下两种情况
没有声明person.last-name会报错,新声明的需要加默认值
person.age=${random.int}
person.boss=false
person.last-name=张三${random.uuid}
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=${person.hello:hello}'s wanghuahu
person.dog.age=15
结果:输出hello’s wanghuahua