String Boot 入门
String Boot 简介
Spring Boot 主要优点:
- 为所有Spring开发者更快的入门
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化web项目
- 没有冗余代码生成和XML配置的要求
微服务
什么是微服务
微服务是一种机构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http等的方式进行互通。
单体应用架构
所谓单体应用架构(all in one)是指,我们将一个应用的中的所有应用服务都封装在一个应用中。
无论是ERP、CRM或是其他什么系统,你都把数据库访问,web访问,等等各个功能放到一个war包内。
- 这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
- 单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。
微服务结构
all in one的架构方式,我们把所有的功能单元放在一个应用里面。然后我们把整个应用部署到服务器上。如果负载能力不行,我们将整个应用进行水平复制,进行扩展,然后在负载均衡。
所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来。把独立出来的功能元素的动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
这样的好处是:
1、节省了调用资源。
2、每个功能元素的服务都是 独立、可替换的、可以进行独立的升级软件代码。
原文地址:https://martinfowler.com/articles/microservices.html
翻译:https://www.cnblogs.com/liuning8023/p/4493156.html
微服务架构
微服务架构类似一个神经网络。微服务越大,这个神经网络越复杂。每一个功能都是一个单独的神经元,他们独自工作,通过http进行相互调用。把一个项目的每一个功能都独立成一个功能服务,它们一起构建一个庞大的项目。如果要对其中一个功能进行修改升级,只需更新对应的功能模块即可。
但是这种庞大的系统架构给部署和运维带来很大的难度。于是,spring为我们带来了构建大型分布式微服务的全套、产品
- 构建一个个功能独立的微服务应用单元,可以使用springboot,可以帮我们快速构建一个应用;
- 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
- 在分布式中间,进行流式数据计算、批处理,我们有spring cloud data flow.
- spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案。
第一个SpringBoot程序:helloworld
搭建环境:
- jdk1.8
- maven 3.6.1
- SpringBoot:最新版
- IDEA
方法一:使用Spring官网搭建SpringBoot(不推荐)
官网地址:https://spring.io/
进入官网点击Projects ,然后选择SpringBoot
反到最下方点击Spring Initializr
然后进行下载
将其解压出来
一直下一步即可。
方法二:IDEA 创建(推荐)
然后一直下一步即可。
Spring Boot 项目结构
依赖解释
<?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">
<modelVersion>4.0.0</modelVersion>
<!--有一个父类项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zjb</groupId>
<artifactId>helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helloworld</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--web依赖:Tomcat、dispatcherServlet、xml-->
<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>
<build>
<!--打jar包插件-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot 运行方式
运行后在浏览器地址栏输入http://localhost:8080/ 进行测试。因为我们没有进行任何修改,会近入自带的error页面,如下图。
SpringBoot 测试helloworld
创建controller、dao、pojo、service。
注意:要在HelloworldApplication同级目录下创建
在controller创建HellController控制类
@Controller和@RestController区别
参考文章https://www.cnblogs.com/shuaifing/p/8119664.html
package com.zjb.helloworld.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
//接口:http://localhost:8080/hello
//用处:调用业务,接收前段的参数
@RequestMapping("/hello")
public String hello(){
return "hello World";
}
}
启动后在浏览器输入地址测试:http://localhost:8080/hello
结果如图
打包插件
双击下图的package进行打包,打包会比较慢。
在target下我们会得到一个jar包
这个jar包是可运行的,我们打开测试一下
我们依然可以看见hello world
程序的内部是默认内嵌了Tomcat服务器。
更改端口号
更改端口号为8081,可以自行启动测试!
更改SpringBoot 启动时的logo(玩一玩,休息一下)
生成文图网站:https://www.bootschool.net/ascii;bsid=CB140F4F4A7FC8ECB42364FC41179D55
首先在网站,粘贴一个自己喜欢的图案。例如下图
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
在resource下创建banner.txt文件,把文图粘贴到文件里。
注意:banner文件的角标有图案证明被扫描了,如果没有证明你创建的文件有问题!
运行测试一下吧。(有好的图案记得分享一下哦)
看看底层,了解原理
自动装配:
pom.xml
- spring-boot-dependencies :核心依赖在父工程中!
- 我们在写或者引入一些Springboot依赖的时候,不需要指定版本,就因为有这些版本仓库
查看源码的方法
我们来看看父项目都什么?
spring-boot-starter-parent 中进行了资源及其插件管理。
spring-boot-dependencies 中存放了全部依赖的版本号进行了管理。在我们不想使用默认版本的时候可以设置需要的版本号。
启动器
- Springboot中有很多启动器,启动器说白了就是Springboot的启动场景;
- Springboot会把所有的功能场景,都变成一个个-的启动器
- 例如我们上面用到的spring-boot-starter-web,它就会帮助我们自动导入web环境所有的依赖!
- 我们要使用什么功能,就只需要找到对应的启动器即可starter
看看spring官网的starters
主程序
主程序的表面意思
//@SpringBootApplication:标注这个类是一个springboot的应用
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(HelloworldApplication.class, args);
}
}
底层内容太多了 整理好了单发一篇文章
yml语法
yml介绍
官方文档:https://docs.spring.io/spring-boot/docs/2.4.3/reference/htmlsingle/#common-application-properties
配置文件
SpringBoot 的配置文件名是固定的叫application,唯一的全局配置文件
yml与properties区别
语法结构区别
- application.properties
- 语法结构:key=value
server.post=8080
- application.yml
- 语法结构:key: 空格 value
server:
port: 8080
存取方式区别
properties 只能保存键值对key-value
name=zhao
yml 不仅可以保存 普通的键值对key-value 还可以保存对象 和 数组。
#普通的键值对key-value
name:zhao
#对象
student:
name: zhao
age: 23
#行内写法
student: {name: zhao,age: 23}
#数组
pets:
- cat
- dog
- pig
#行内写法
pet: [cat,dog,pig]
注意:yml对空格的要求非常严格
例1:student 对象下有nameage两个属性
student:
name: zhao
age: 23
例2:student 对象下有name name下age属性
student:
name: zhao
age: 23
例3:student 、name 、age三个对象
student:
name: zhao
age: 23
yml可以直接给实体类赋值
以前是使用注解进行赋值
package com.zjb.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Dog {
@Value("旺财")
private String name;
@Value("3")
private Integer age;
public Dog() {
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类
package com.zjb;
import com.zjb.pojo.Dog;
import com.zjb.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Dog dog;
@Test
void contextLoads() {
System.out.println(dog);
}
}
结果
现在我们使用yml进行赋值
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉springBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = "person”:将配置文件中的person下面的所有属性一一对应
只有这个组件是容器中的组件,才能使用容器提供的ConfigurationProperties功能
package com.zjb.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
public Person() {
}
public Person(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
this.name = name;
this.age = age;
this.happy = happy;
this.birth = birth;
this.maps = maps;
this.lists = lists;
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", happy=" + happy +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", dog=" + dog +
'}';
}
}
这个是让你导入一个相关依赖,可以可无不重要
<!--@ConfigurationProperties 报红提示 功能就是使用时有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
application.yml文件
person:
name: zhao
age: 23
happy: true
birth: 1999/9/20
maps: {k1: k1,K2: k2}
lists:
- cat
- dag
dog:
name: "旺财"
age: 3
测试类
package com.zjb;
import com.zjb.pojo.Dog;
import com.zjb.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Dog dog;
@Autowired
private Person person;
@Test
void contextLoads() {
// System.out.println(person);
System.out.println(dog);
}
}
结果
拓展占位符
$ {random.value}、$ {random.int}、$ {randam .long,$ {random .int(10)}等等
例:name: zhao${random.uuid}
结果:name=‘zhao3accd456-dcd9-4cbd-b0d9-dfa85301e58c’
例:name: ${person.hello:hello}_旺财
person.hello 数值进行替换 没值使用默认hello 结果:name=‘hello_旺财’
person:
name: zhao${random.uuid}
age: 23
happy: true
birth: 1999/9/20
maps: {k1: k1,K2: k2}
lists:
- cat
- dag
dog:
name: ${person.hello:hello}_旺财
age: 23
@ConfigurationProperties与@Value区别
- @ConfigurationProperties只需要写一次,@value需要每个字段都添加。
- 松散绑定:这个什么意思呢?比如我的yml中写的last-name,这个和lastName是一样的,-后面的字母默认是大写的。这就是松散绑定。
- JSR303数据校验,这个就是我们可以在字段是增加一层过滤器验证,可以保证数据的合法性
- 复杂类型封装,yml中可以封装对象,使用@value就不支持
结论
配置yml和配置properties都可以获取到值,强烈推荐yml
- 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value
- 如果说,我们专门编写了一个JavaBean来和配置文件进行映射,就直接使用configurationProperties,不要犹豫!
JSR303校验
介绍
JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
说白了就是 校验是否满足要求
举个栗子
我们导入依赖,不导入依赖也可以使用因为SpringBoot在内部集成了hibernate-validation,可以直接使用。注意二者之间存在差异,功能一样!
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
编写application.yml
dog:
name: 旺财
age: 23
编写实体
package com.zjb.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Email;
@Component
@ConfigurationProperties(prefix = "dog")
@Validated //JSR303校验
public class Dog {
@Email //是否为邮箱格式 可以自定义报错原因@Email(message="不是邮箱")
private String name;
private Integer age;
public Dog() {
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
结果
常用的校验
导入依赖的
@NotNul1(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private string email;
空检查
@Nul1
验证对象是否为null
@NotNul1
验证对象是否不为null,无法查检长度为0的字符串
@NotBlank检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.@NotEmpty检查约束元素是否为NULL或者是EMPTY.
Booelan检查
@AssertTrue
验证Boolean 对象是否为true
@AssertFalse
验证 Boolean 对象是否为false
长度检查
@Size(min=, max=)验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=,max=) Validates that the annotated string is between min and max included.
日期检查
Past
验证 Date 和l calendar对象是否在当前时间之前
@Future
验证 Date和 calendar 对象是否在当前时间之后
@Pattern
验证String对象是否符合正则表达式的规则 重点
.......等等
除此以外,我们还可以自定义一些数据校验规则
springBoot集成hibernate-validation的
配置文件位置
配置文件的位置可以更改,下面是官方的说明
我们测试一下这四个位置,以及他们执行的优先级
这里直接给出测试结果
1、 file:./ config/
2、file:./
3、classpath: / config/
4、classpath:/
官方默认位置的最慢的
多环境配置
properties文件下的多环境切换
默认环境
server.post:8080
开发环境
server.post:8081
测试环境
server.post:8082
测试结果走的是 默认环境
如何切换配置环境
使用
spring.profiles.active=
这里写你文件名-后面的即可
例如:application-dev.properties 就写spring.profiles.active=dev
springboot的多环境配置:可以选择激活那一个配置文件
spring.profiles.active=dev
yml文件的多环境切换(推荐)
编写yml
server:
port: 8080
# springboot的多环境配置:可以选择激活那一个配置文件
profiles:
active: test
---
server:
port: 8081
spring:
profiles:
activate: dev
---
server:
port: 8082
spring:
profiles:
activate: test
运行测试