该阶段的学习可以分配两部分:SpringBoot阶段的学习以及微服务部分的学习。SpringBoot部分主要是几个点,会进行项目的配置、编写SpringBoot程序、整合Mybatis、整合数据源、整合安全框架、整合Swagger。微服务阶段的学习主要是明白微服务的思想,以及会用Dubbo和ZooKeeper进行整合。我们后面还会学习SpringCloud,这是两套不同的方式,所以这个阶段的学习,不仅要会用,个人觉得一定要多看文档资料,因为里面涉及到的东西,不是简单的几行代码就能够说明的。愿你学习完这一部分知识,对整个java阶段的学习认识又上一个新的台阶!!!
文章目录
-
- 1、微服务概述
- 2、创建SpringBoot程序
-
- 2.1、创建SpringBoot程序
- 2.2、项目的要点
- 2.3、自动装配原理
- 3、SpringBoot配置
-
- 3.1、yaml配置
- 3.2、使用yaml进行属性注入
- 3.3、使用properties进行属性注入
- 3.4、@ConfigurationProperties与@Value的对比
- 3.5、核心配置文件的优先级
- 3.6、配置环境的切换
- 4、SpringBoot Web开发
-
- 4.1、静态资源的导入问题
- 4.2、首页的定制
- 4.3、Thymeleaf模板引擎
- 4.4、装配SpringMVC
- 5、整合JDBC
- 6、整合Druid数据源
-
- 6.1、配置数据源对应的信息
- 6.2、编写数据源的后台监控
- 6.3、配置Druid Web监控的filter过滤器
- 7、整合Mybatis
- 8、SpringSecurity
- 9、Shiro
- 10、Swagger
- 11、任务
-
- 11.1、异步任务
- 11.2、定时任务
- 11.3、邮件任务
- 12、分布式Dubbo + ZooKeeper + SpringBoot
-
- 12.1、分布式理论
- 12.2、RPC
- 12.3、Dubbo
- 12.4、ZooKeeper
- 12.5、安装环境
- 12.6、集中整合
- 13、思维导图
1、微服务概述
这个阶段注意几个问题就行了
- 微服务的概念是什么?
- SpringBoot是干嘛的?
- SpringBoot有哪些特点?
- 为什么会有SpringBoot的出现?
2、创建SpringBoot程序
2.1、创建SpringBoot程序
创建方式主要有两种:
- 在官网选择一个SpringBoot项目,然后下载到本地,再用编译器打开
- 使用IDEA集成的SpringBoot(帮我们封装了第一种方式)
2.2、项目的要点
1、我们新建的包名,应该和项目的启动类保持一个等级。
2、pom.xml文件中是目前我们项目的各种信息
- pom.xml:部分插件,可以显式的定义对应的依赖(及对应的启动器)
- pom.xml的父项目为:spring-boot-starter-parent(配置了资源过滤器,及插件)
- pom.xml的父项目的父项目:spring-boot-dependencies(配置了很多的版本信息和启动器。当我们在pom.xml中配置依赖时,可以不用指定对应的版本信息,因为这些版本都可以在这里中找到)
3、SpringBoot是内嵌了Tomcat服务器的,并且默认使用的是Tomcat,内嵌的还有Jetty和UnderTow服务器。
4、我们可以直接使用maven打包的工具将项目打包成jar包存放在本地,在使用java -jar运行项目
5、我们可以在配置文件中修改项目的相关信息,比如最基础的端口号
6、修改SpringBoot项目启动的图标,在核心配置文件的同级目录下新建一个banner.txt文件,放入指定的样式即可
2.3、自动装配原理
目前自己还看不懂,等把SpringBoot玩转了,再来慢慢学习原理
启动器的概念:
在我们的pom.xml文件中,包含了一个启动器。它类似于我们SpringBoot的启动场景,比如:spring-boot-starter-web,系统就会帮我们自动导入web环境相关的所有的依赖。此时SpringBoot会将所有的功能场景都变成一个个启动器,我们要做的就是找到对应的启动器就可以了。
主程序的概念:
我们会发现主程序中有@SpringBootApplication注解,它白哦是我们这是一个SpringBoot应用程序。观察主方法的方法体我们可以得出,SpringApplication.run()是一个静态方法,并且传入的其中一个参数是主程序的反射模板类。
SpringApplication类主要做了以下四件事情
- 推断应用的类型是普通的项目还是Web项目
- 查找并加载所有可用初始化器 , 设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
3、SpringBoot配置
3.1、yaml配置
"YAML Ain’t a Markup Language"也可以简写成yml
你可以将yaml理解成properties、xml同级的一种语法,用于配置程序的信息。不过SpringBoot更推荐我们使用yaml,我想yaml一定是有它独特的优势,不然官方也不会这么推荐了。
基本格式:把properties的 . 变成 :外加换行后的两个空格(切记格式规范)
server:
port: 8081
3.2、使用yaml进行属性注入
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Data
@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;
}
person:
name: 默辨
age: 23
happy: true
birth: 2020/03/16
maps: {key1: value1,key2: value2}
lists:
- eat
- sleep
- play
dog:
name: 小黄
age: 11
yaml的高级用法补充:
person:
name: 默辨${random.uuid} # 随机uuid
age: ${random.int} # 随机int
happy: true
birth: 2020/03/16
maps: {key1: value1,key2: value2}
lists:
- eat
- sleep
- play
dog:
name: ${person.hello:other}_小黄 #如果有值就输出,没有就使用默认值,再拼接_阿黄
age: 11
3.3、使用properties进行属性注入
注意修改properties文件的字符编码,不然会出现乱码
与使用yaml属性注入的方式不同,我们使用properties时,在实体类上使用注解注解,引入对应的配置信息即可
@AllArgsConstructor
@NoArgsConstructor
@Data
@ToString
//该注解,可以用来绑定我们自定义的配置文件(配置文件中包含我们设置好的属性)
@PropertySource(value = "classpath:cat.properties")
@Component
public class Cat {
@Value("${cat.name}") //可以从配置文件中取值
private String name;
@Value("#{2*3}") // #{SPEL} Spring表达式
private int age;
}
3.4、@ConfigurationProperties与@Value的对比
我们在使用的properties配置文件进行属性的注入时,可以使用两种方式:
- @ConfigurationProperties(pre = “对象名”)
- @PropertySource(value = “classpath:配置文件名”) + @Value("${对象.属性}")
我们可以发现这是将属性配置文件与我们的pojo类绑定的两种不同方式。第一种直接绑定对象名,即可完成自动的属性注入。后者为指向配置文件名字,然后使用@Value进行输入的单个绑定,绑定的方式是使用SpEL表达式(Spring的EL表达式)。
依据个人喜好进行选择。
不过我推荐使用第一种方式。第一种方式支持松散绑定(数据库的字段与pojo属性之间的转换形式),支持复杂数据类型的封装,还支持JSR3030校验(@Validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理)。看起来代码比较清爽,个人感觉!!!
配置类和核心配置文件是互相匹配的,
自动装配的原理的核心要领:
- SpringBoot启动会加载大量的自动配置类
- 我们首先看我们需要的功能有没有在Spring Boot默认写好的自动配置类当中;
- 我们再看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
- 给容器中自动配置类添加组件的时候,会从配置类中获取某些属性。我们只需要在核心配置文件中指定这些属性的值即可;
xxxxAutoConfigurartion:自动配置类,给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
补充JSR303校验的异常参数:
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为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=) string is between min and max included.
日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则
.......等等
除此以外,我们还可以自定义一些数据校验规则
3.5、核心配置文件的优先级
目前我们知道的核心配置文件只有一个那就是application.propertiest或者application.yaml,我们后面还会学习到一种bootstarp.properties或bootstarp.yaml
我们通常创建的核心配置文件位置一般都在resources文件下。
其实他可以创建在四个不同的位置,逐级覆盖,位置分别时:
- 在项目下新建一个config文件夹,里面建立核心配置文件
- 直接在项目下新建核心配置文件
- 在resources资源路径下新建一个config文件夹,里面建立核心配置文件
- 在resources资源路径下,建立核心配置文件
我们总结一下这个访问顺序就是:从项目最开始的位置开始,在项目名路径下遇到config文件夹,就去里面看,如果没有就在项目名路径下寻找配置文件。如果也没有找到那就去resources目录下,重复刚才的过程。
3.6、配置环境的切换
由于我们在自己本地编写代码的环境和后期的上线环境是有些许差异的,所以我们需要能够灵活的切换,当然我们这里是在本地进行切换,未来有可能是在远程的git上进行环境的切换。
server:
port: 8081
#选择要激活那个环境块
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: prod #配置环境的名称
4、SpringBoot Web开发
4.1、静态资源的导入问题
静态资源即css、img、js文件
两种方式引入:
- 使用webjars方式,引入对应的依赖
- 在resources目录下新建文件夹
即静态资源可以存放的位置为:
- 新建的public文件夹下
- 自带的static文件夹下
- 新建的resources文件夹下
- 根目录下的/**
外部访问的优先级:resources > static(默认) > public
4.2、首页的定制
新建一个首页,文件命名为index.html,可以根据适当的需求,自行放在public、static、templates等目录的其中一个下
4.3、Thymeleaf模板引擎
理解Thymeleaf可以对比JSP,JSP也是一种模板引擎,它将后端传过来的数据,以相应的形式渲染到前端,继而达到前端显示后端的数据。那我们这里的Thymeleaf也就是同样的功能,SpringBoot推荐我们使用Thymeleaf,只是我们目前还不知道它的具体语法,所以我们感觉比较陌生。
使用步骤:
- 引入对应的命名空间,xmlns:th=“http://www.thymeleaf.org” 防止报异常看着碍眼
- 引入对应的依赖(2个)
- 编写controller控制器类
- 编写对应的前端界面
- 测试
基本语法:
- th:each:遍历
- th:utext:不文本形式显示
- th:text:以文本的形式显示
<!--如果msg信息中含有html标签,我们就将它进行转译-->
<div th:utext="${msg}"></div>
<!--将msg以文本的形式进行打印输出-->
<div th:text="${msg}"></div>
<!--循环遍历users,将遍历出来的每一个元素命名为user,然后再把user以文本的形式进行打印输出-->
<div th:each="user:${users}" th:text="${user}"></div>
4.4、装配SpringMVC
按理说,我们不装配已经能够达到测试效果了,那这个配置又是出来干嘛的呢?
我们回想一下之前的SpringMVC阶段的学习,我们除了编写对应的视图跳转以外,还会编写一些视图解析器(SpringMVC的视图解析器我们可以自定义)、拦截器、格式化显示…
我们现在就可以通过装配SpringMVC来实现这一切配置的自定义,具体能够重写的方法,我们只需要实现
WebMvcConfigurer
接口即可查看。如果我们不去自定义,那么我们就会使用SpringBoot默认的方法体。
5、整合JDBC
SpringBoot默认的Jdbc模板使用的数据源是HikariDataSource
整合JDBC步骤:
- 勾选对应的依赖(MySQL驱动、JDBC API、Web启动器)
- 使用IDEA连接对应的数据库
- 在配置文件中配置对应的数据库信息
- 编写对应的控制器类进行测试
- 我们也可以编写对应的Test类打印查看数据源相应的信息
6、整合Druid数据源
6.1、配置数据源对应的信息
Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控
按照我们之前的说法,很多东西SpringBoot都是帮我们自动配置好的,有一个默认的选项,比如数据源默认就是HikariDataSource,但是我们觉得它功能不够强大,我们就像引入自己自定义的数据源,比如阿里巴巴帮我们定义好的Druid数据源。那么我们就又需要编写一个配置类,用来配置数据源
使用步骤:
- 引入对应的maven依赖
- 编写一个配置类(在config包下,并使用@Configuration注解)
- 如果我们想要按照自己的需求自定义数据源信息,那么我们也可以在核心配置文件中对数据源进行相应的配置(使用@ConfigurationProperties()注解进行信息绑定)
- 在测试类中进行测试,观察数据源信息
6.2、编写数据源的后台监控
添加对应的配置即可完成监控界面,至于为什么这么配置,我也说不上来。那就理解成规范就是这样配置吧,先记住!!!
访问路径:http://localhost:8080/druid
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
// 这些参数可以在 com.alibaba.druid.support.http.StatViewServlet
// 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin"); //后台管理界面的登录账号
initParams.put("loginPassword", "123456"); //后台管理界面的登录密码
//后台允许谁可以访问
//initParams.put("allow", "localhost"):表示只有本机可以访问
//initParams.put("allow", ""):为空或者为null时,表示允许所有访问
initParams.put("allow", "");
//deny:Druid 后台拒绝谁访问
//initParams.put("kuangshen", "192.168.1.20");表示禁止此ip访问
//设置初始化参数
bean.setInitParameters(initParams);
return bean;
}
然后在后台就可以查看相应的操作对应的SQL语句了。
6.3、配置Druid Web监控的filter过滤器
过滤器可以理解成一张网,你可以选择在哪些位置将网的孔弄小一点,哪些位置孔大一些,方便我们抓鱼,这里就是统计信息。
//配置 Druid 监控 之 web 监控的 filter
//WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
bean.setInitParameters(initParams);
//"/*" 表示过滤所有请求
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
7、整合Mybatis
我们前面说过整合JDBC,这里又是整合Mybtis,我们是否可以联想到我们之使用Mybatis代替了原生的JDBC?
整合Mybatis的主要步骤:
- 在JDBC依赖的基础上,添加Mybatis的依赖
- 使用IDEA连接数据库
- 在JDBC数据库配置的基础上,添加Mybatis的别名配置以及mapper文件位置的配置
- 编写对应的实体类
- 编写对应的SQL语句的接口类
- 编写对应接口类的mapper.xml文件
- 编写对应的控制器类
- 测试
我们不难发现,其实步骤大体上与Mybatis编写查询语句差不多(4、5、6、7、8),我们这里的整合只是将之前的mybatis-config.xml中的信息转移到了application.yaml文件中,并添加对应的依赖
8、SpringSecurity
看到名字我们就应该明白,Spring安全,这是Spring为我们提供的安全模板,我们只需要添加对应的启动器,然后在核心配置文件中进行配置,最后再进行配置即可使用。虽然是这样几个步骤,但是我不会,哈哈,所以这里就不说了!!!
Spring Security的两个主要目标是“认证”和“授权”(控制访问)
我先记住这两个概念吧,这在很多的安全框架中都是有这两个概念的:
- 认证:Authentication
- 授权:Authorization
9、Shiro
与前面的SpringSecurity一样,这个也是一个安全框架。
由于我对这两个安全框架的理解都没有太深,甚至没有理解,不敢妄写总结,不过有几个点我们应该明确:
- 既然是新东西,那么我们也需要拿出一部分时间去学习Shiro框架本身
- Shiro这个安全框架与SpringSecurity都是安全框架,不过Shiro是一个外来的
- 对于自家的框架,SpringBoot总归是帮我们做了一些整合优化
- Shiro既然是外来的,那么我们就应该和很多东西都需要整合,比如Mybatis、Thymeleaf,当然还有最重要的SpringBoot
- 安全在网络中是一个比较重要的点,个人觉得应该尽可能的深入学习,而不是入门就完了
- 保证安全的具体安全形式,我们需要自己编写对应的代码
10、Swagger
让代码和程序一体化。
这是一个用于监控前后端接口的一门技术。现在大部分都是前后端分离,如果前端或后端有了相应的改变,却没有及时沟通,就有可能产生许多不必要的麻烦。Swagger就是用来让前后端及时通信的。前后端分别将自己的代码部署在Swagger上面,以此让两者能够及时看见变化。
与SpringBoot整合步骤:
- 创建一个含有web依赖的SpringBoot项目
- 导入相关的依赖(2个)
- 编写对应的配置类(内含我们每个人的信息。方便前端及时查看)
- 编写对应的类
- 运行Swagger后台,查看对应的类信息
11、任务
11.1、异步任务
我们可以根据对应的配置,指定对应的异步任务。最终的效果为,前端与后台服务之间不是同步显示的,前端先显示,后端再出现相应的形式。
11.2、定时任务
这里引入一个新的知识点:cron表达式
我们的程序会根据cron表达式设置的时间,进行对应时间的执行。就像我们的闹钟一样
11.3、邮件任务
我们可以进行相应的配置,实现邮件的发送
12、分布式Dubbo + ZooKeeper + SpringBoot
终于到了最后一个知识点了
12.1、分布式理论
我们学习一个技术不能是仅仅学会用,更要学会背后的思想的转变,所以个人觉得分布式的学习,需要辅助一些文档资料才能对其核心理念有更加深入的了解
分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据
12.2、RPC
RPC(Remote Procedure Call)指远程过程调用,是一种进程间的通信方式,它不是一种技术思想,而是一种规范。它允许程序掉用另一个地址空间(通常是共享网络的另一台机器上)的过程函数。
举个简单的例子,我们本地编写一个方法需要使用一个Student的实体类,如果是以前,我们可能就在pojo包下新建了实体类了。但是现在变成了远程协同开发,我要的那个实体类是存在的,只不过不在我的这个项目里面,那我们怎么才能拿到别人那里的Student实体类呢?我们就可以根据RPC的规范,使用它去拿。当然具体实现细节还有很多,比如序列化和反序列化、Call ID、网络传输…
所以要多看相关的文档资料,我们这里更多的是侧重于学习怎么使用。
12.3、Dubbo
RPC是一种通信方式,是一种规范,Dubbo就是它的具体落地
还是带上官网的图把,毕竟看起来挺好看的。
Dubbo是一个RPC框架,我们将编写的程序注册到RPC的注册中心里面,然后再通过注册中心实现我们的远程调用。
名词解释:
- 服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者(Consumer):调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需要的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用
- 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
- 监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
12.4、ZooKeeper
我们刚才在谈论Dubbo的时候有说到,我们将编写好的程序注册到注册中心里面,然后就可以进行相应的调用了。那么问题又来了
注册进来的那么多的服务,我们怎么去管理它呢?
Dubbo推荐使用ZooKeeper来进行注册中心的管理。Dubbo是RPC通信方式的一个落地实现,它更多的是给出一个框架形式,具体的实现可以使用相应的功能。Dubbo将注册中心进行抽象,使得它可以外接不同的存储媒介给注册中心提供服务。
引入了Zookeeper作为存储媒介,也就把Zookeeper的特性引进来了。ZooKeeper的特性包括载均衡、资源同步、命名服务。反正一句话就是,ZooKeeper很好,很适合Dubbo,所以Dubbo推荐它。
12.5、安装环境
1、安装测试ZooKeeper
2、安装Dubbo
3、安装Dubbo-admin(使用客户端进行观测)
12.6、集中整合
整合前提是,我们Dubbo、ZooKeeper环境已经搭建完成
整合步骤:
- 新建两个不同的项目(配置不同的端口号,用来表示不同的程序)
- 导入对应的依赖
- 将其中一个类设置为Provider,一个设置为Consumer
- 配置对应的程序端口号以及dubbo的信息
- 编写不同项目的相应的方法体
- 执行项目,观测后台信息(要配置Dubbo-admin)