什么是SpringBoot
Spring的发展史:Spring是2003年兴起的一个轻量级的Java开源框架,这个框架最初是为了解决企业级应用开发笨重臃肿的问题,宗旨就是简化开发; SpringBoot的诞生:随着Spring越来越火,Spring也慢慢从一个小而精的框架变成了一个覆盖面广又全的框架,大量繁琐的XML配置和第三方整合配置,让Spring使用者痛苦不已,这个时候急需一个解决方案来解决这些问题,故SpringBoot应运而生,2013年SpringBoot开始研发,2014年4月Spring Boot1.0正式发布
- SpringBoot对于Spring来说是一套全新的框架,它来自于Spring大家族,因此Spring所有具备的功能它都有并且更容易使用;同时还简化了基于Spring的应用开发,通过少量的代码就能创建一个独立的、产品级别的Spring应用.
- SpringBoot默认配置了很多框架的使用方式,就像Maven整合了所有的jar包,SpringBoot整合了所有的框架.它的核心设计思想是:约定优于配置,SpringBoot所有开发细节都是依据此思想进行实现的.
Springboot 特性
- 搭建项目快,几秒钟就可以搭建完成
- 没有冗余代码生成和XML配置的要求
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌容器,省去了配置Tomcat的繁琐
- Starter自动依赖和版本控制
- 方便监控,使用Spring Boot Actuator组件提供了应用的系统监控,可以查看应用配置的详细信息
单体架构与微服务架构
微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通.
什么是单体架构
所谓单体应用架构(all in one)是指我们将一个应用的中的所有服务封装在一个应用中.无论是ERP、CRM或是其他什么系统,都把数据库访问、WEB访问,等等各个功能放到一个war包内.
单体架构优缺点
优点:易于开发和测试;十分方便部署;当需要扩展时,只需要将war复制多酚,然后放到多个服务器上,再做个负载均衡就可以了 缺点:项目过于臃肿;资源无法隔离;无法灵活扩展
什么是微服务架构
所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来.把独立出来的功能元素的动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素.所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制
微服务架构优点
节省了调用资源.每个功能元素的服务都是一个可以替换的、可独立升级的软件代码.
下图可以更好的来分辨单体架构和微服务架构 区别图:
左侧是单体架构,将所有的功能都放到一个容器里面;右侧是微服务架构将功能单独出来进行动态组合.
如何构建微服务
一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http或者RPC相互请求调用.但这种庞大但系统架构部署和运维带来很大的难度,于是Spring为我们带来了构建大型分布式微服务的全套、全程产品:
- 构建一个个功能独立的微服务应用单元,可以使用Springboot 可以帮我们快速构建一个应用;
- 大型分布式网络服务的调用,这部分由Spring cloud来完成,实现分布式.
- 在分布式中间,进行流式数据计算、批处理,采用spring cloud data flow.
快速入门SpringBoot
Maven配置
在下载的maven包中,找到/conf/setting.xml 进行配置localRepository:本地资源路径可以使用默认的也可以自己配置路径,然后配置jdk版本.
然后在IDE中进行配置<localRepository>/xx/path</localRepository>
<profile>
<id>JDK-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</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>
</profile>
创建Spring Boot项目
创建Springboot的两种方式:
Spring 官网下载 https://start.spring.io/
- IDEA 实现 springboot
这里通过IDEA来创建Spring Boot项目,其实IDEA创建Springboot项目就是使用Spring Initializr
之后选择,要集成的框架即可
Spring Boot结构说明
项目结构如下:Application类为Spring Boot项目的启动类.resources/static 静态资源文件 resources/templates html模版 application.properties或者application.yml 项目的配置文件.target目录会生成class文件和jar/war包
pom文件说明
- 项目元数据信息:创建时候输入的Project Metadata部分,也就是Maven项目的基本元素,包括:groupId、artifactId、version、name、description等
- parent:集成spring-boot-starter-parent的依赖管理,控制版本与打包依赖等功能
- dependencies:项目具体依赖
build:构建配置部分.默认使用了spring-boot-maven-plugin,配合spring-boot-starter-parent就可以把Spring Boot应用打成JAR来直接运行 ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0“ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0 <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository -->
com.example.springboot.hello springboot-hello 0.0.1-SNAPSHOT springboot-hello Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.boot spring-boot-maven-plugin
点击右侧的Maven,显示如下:点击package即可进行打包<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/375694/1588922045743-0b0ff26b-a96f-4ac0-9a88-9abacf0bde6a.png#align=left&display=inline&height=273&margin=%5Bobject%20Object%5D&name=image.png&originHeight=546&originWidth=364&size=39581&status=done&style=none&width=182)<br />使用Springboot plugin打包 java -jar xxxxx.jar 直接运行Springboot的jar包即可访问
<a name="eTx0c"></a>
### Spring Boot 启动原理分析
如下代码,是Spring Boot的启动类,关键地方在@SpringBootApplication注解,如果去掉这个注解就无法启动项目
```java
@SpringBootApplication //Spring boot 启动类注解
//如果去掉注解 则无法启动
public class SpringbootHelloApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootHelloApplication.class, args);
}
}
在这个注解上,还有着其他注解分别是:@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@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的配置类 -》 @Configuration :标明这是一个配置类 @EnableAutoConfiguration:开启自动配置功能 -> @AutoConfigurationPackage:自动配置包:在当前类的约定的包下进行扫描 如果不是约定的基础包那么无法加载Spring容器中 @Import(AutoConfigurationPackages.Registrar.class):包启动类所在的包进行默认扫描,该包下的所有的类都会被扫描到Spring容器中进行管理 @Import({AutoConfigurationImportSelector.class}):加载指定的类到Spring容器中去 AutoConfigurationImportSelector:自动配置导入选择器 根据项目来判断你的项目需要哪些配置信息,然后把默认的配置内容导入Spring容器进行管理 @ComponentScan:组件扫描和自动装配,用来指定扫描容器的范围
如下图所示: 目前先了解大体的流程即可,知道Springboot启动的时候做了什么,后续会进行详细的讲解,不要一下深入源码无法自拔了
Spring Boot 配置说明
Springboot 配置文件
Springboot为什么还需要配置文件
- 方便修改默认配置
- 其他信息保存在配置文件中
Springboot配置文件有哪些
- properties配置文件
- yml配置文件
- 如果同时存在properties和yml同时存在,优先properties生效 yml不生效
Springboot配置文件
- 文件放在src/main/resources/目录或者类路径/config目录下(不推荐)
- Springboot默认读取application开头的配置文件
如下默认的application.properties的配置文件,修改默认的端口号
#如果同时存在properties和yml同时存在,优先properties生效 yml不生效
# 优先级 properties > yml
#修改默认端口号 8080
server.port=8088
yml 配置文件
yml的全称为YAML(YAML Ain’t Markup Language) 它是一种标记语言,它是一种直观的被电脑识别的数据序列化格式,并且容易被人类阅读,这种标记语言与其他标记语言不同的地方是,它是以数据为中心,比json、xml等更适合做配置文件.
如下书写格式: 新建application.yml
server:
port: 8089 #yml 修改端口号
person:
name: zhangsan
age: 19
sex: nan
isMerried: false
# friend:
# name: lisi
# sex: nv
friend: {name: lisi,sex: nv}
# pets:
# - 小狗
# - 小猫
# - 小驴
pets: [小猫,小狗,小驴]
friends: [{name: lisi,sex: nv},{name: wangwu,sex: nan}]
yml文件的语法说明:
- yml的基本语法
- key: value的格式(value前面的空格不能少,可以有多个,不能用tab替代);
- 大小写敏感
- 字符串默认不需要使用引号,单引号和双引号的区别在于是否能用转义字符;
- 注释方式:#
- yml支持的三种数据类型
- 字面量:直接量,单个不能被拆分的值(数字、字符串、布尔)
- 对象: 键值对形式存在
- 数组:字面量/对象的集合
读取yml文件的配置信息
如下核心代码,这里省去了setter/getter 和toString 这些重复的代码,加载配置文件主要时配置@ConfigurationProperties 注解,perfix是配置文件的前缀名
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private String sex;
private boolean isMerried;
private Friend friend;
private String[] pets;
private List<Friend> friends;
}
测试:
@SpringBootTest
class SpringbootHelloApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
输出如下:
Person{name=’zhangsan’, age=19, sex=’nan’, isMerried=false, friend=Friend{name=’lisi’, sex=’nv’}, pets=[小猫, 小狗, 小驴], friends=[Friend{name=’lisi’, sex=’nv’}, Friend{name=’万物’, sex=’nan’}]}
读取properties文件配置信息,如下properties要比yml复杂的多
person1.name=zhangsan
person1.age=19
person1.sex=nan
person1.isMerried:false
person1.pets[0]=小猫
person1.pets[1]=小狗
person1.pets[2]=小驴
person1.friends[0].name=lisi
person1.friends[0].sex=nv
person1.friends[1].name=万物
person1.friends[1].sex=nan
person1.friend.name=lisi
person1.friend.sex=nv
只需要将Person类的注解ConfigurationProperties进行修改即可
@ConfigurationProperties(prefix = "person1")
输出结果:
Person{name=’zhangsan’, age=19, sex=’nan’, isMerried=false, friend=Friend{name=’lisi’, sex=’nv’}, pets=[小猫, 小狗, 小驴], friends=[Friend{name=’lisi’, sex=’nv’}, Friend{name=’万物’, sex=’nan’}]}
如果遇到中文没有显示出来多问题修改:
如果我们想只读取某一个属性如何呢? 通过@Value可以更加灵活多获取配置信息
只读取配置文件某些属性
实现如下,这时候就不需要使用@ConfigurationProperties注解了,在类中哪个属性需要通过@Value灵活的获取配置信息
@Component
//@ConfigurationProperties(prefix = "person1")
public class Person {
@Value("${person.name}")
private String name;
@Value("${person.age}")
private Integer age;
@Value("#{11*2}")
private String sex;
private boolean isMerried;
private Friend friend;
private String[] pets;
private List<Friend> friends;
}
输出结果如下:
Person{name=’zhangsan’, age=19, sex=’22’, isMerried=false, friend=null, pets=null, friends=null}
无论是@Value还是@ConfigurationProperties可以根据编码的实际情况进行使用.
如何读取自定义的properties文件配置信息呢?
首先在resources目录下创建person2.properties文件
person2.name=zhangsan
person2.age=19
person2.sex=nan
person2.isMerried:false
person2.pets[0]=小猫
person2.pets[1]=小狗
person2.pets[2]=小驴
person1.friends[0].name=lisi
person1.friends[0].sex=nv
person1.friends[1].name=万物
person1.friends[1].sex=nan
person1.friend.name=lisi
person1.friend.sex=nv
使用@PropertySource注解指定自定义的properties文件
@Component
@ConfigurationProperties(prefix = "person2")
@PropertySource("classpath:person2.properties")
public class Person {
private String name;
private Integer age;
private String sex;
private boolean isMerried;
private Friend friend;
private String[] pets;
private List<Friend> friends;
结果如下,成功读取到了自定义的配置文件
Person{name=’zhangsan’, age=19, sex=’nan’, isMerried=false, friend=Friend{name=’lisi’, sex=’nv’}, pets=[小猫, 小狗, 小驴], friends=[Friend{name=’lisi’, sex=’nv’}, Friend{name=’万物’, sex=’nan’}]}
Spring Boot 进行Web开发
RESTful
使用JPA
Spring DATA REST
http://localhost:8080/ 请求项目就会返回如下信息
请求 : http://localhost:8080/users 会返回如下的信息,用户的所有信息
自动实现的分页请求
同时可以去请求分页:http://localhost:8080/users?page=1&size=2 会自动帮我们进行分页
还可以对分页的数据进行排序:http://localhost:8080/users?page=1&size=3&sort=id,desc
根据条件进行查询
包括查询某一条的用户信息: http://localhost:8080/users/1 默认支持ID的查找
如果要通过username进行查找需要进行配置:
@RepositoryRestResource(path = "users")
public interface UserRepository extends JpaRepository<User, Integer> {
User findByUsername(@Param("username") String username);
}
http://localhost:8080/users/search 可以查询你自己定义的请求,如下就可以进行使用,它会告诉你如何进行请求
http://localhost:8080/users/search/findByUsername?username=张三
{
"username": "张三",
"password": "aaaaa",
"name": "zzsaan",
"_links": {
"self": {
"href": "http://localhost:8080/users/1"
},
"user": {
"href": "http://localhost:8080/users/1"
}
}
}
POST请求
当我们发送post请求:http://localhost:8080/users?username=张三&password=111111&name=zhangsan 去向数据库添加一条记录
会报400的错误这是为什么呢?
{
"cause": {
"cause": null,
"message": "No content to map due to end-of-input\n at [Source: (org.apache.catalina.connector.CoyoteInputStream); line: 1, column: 0]"
},
"message": "JSON parse error: No content to map due to end-of-input; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input\n at [Source: (org.apache.catalina.connector.CoyoteInputStream); line: 1, column: 0]"
}
header 需要设置:Content-Type:application/json;charset=UTF-8
发送body:
{"username":"张三","password":"aaaaa","name":"zzsaan"}
这样就请求成功了
{
"username": "张三",
"password": "aaaaa",
"name": "zzsaan",
"_links": {
"self": {
"href": "http://localhost:8080/users/0"
},
"user": {
"href": "http://localhost:8080/users/0"
}
}
}
添加ID 进行修改数据
{"id":8,"username":"长瘤","password":"bbbbbb","name":"zhangliu"}
PUT请求
put请求:http://localhost:8080/users/8 后面必须要加上主键ID
{"username":"长瘤1","password":"bbbbbb1"}
如下,如果我们只想要修改username和password,但是put进行了全局的修改包括post
PATCH请求
patch请求:http://localhost:8080/users/8 同样还是只修改用户名和密码,在数据库中加上name
{"username":"长瘤1","password":"bbbbbb1"}
运行结果如下: 可见patch请求可以实现对小范围的修改
{
"username": "长瘤1",
"password": "bbbbbb1",
"name": "sjdsj",
"_links": {
"self": {
"href": "http://localhost:8080/users/8"
},
"user": {
"href": "http://localhost:8080/users/8"
}
}
}
:::tips post和put都会进行全局修改而patch可以进行指定的字段修改 :::