一、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设置
jdk18 true 1.8nexus-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:
9000 2、YAML语法 1、基本语法 k:(空格)v:表示一堆键值对(空格必须有);以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一层级的
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: wanghuahuaapplication.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=153、测试运行
访问 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=152、在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
