Spring SpringMVC SpringBoot SpringCloud框架(Spring全家桶)

Spring 全家桶

一、Spring

一、Spring框架简介

  1. Spring是一款诞生于2003年的开源Java开发框架。Spring在诞生之初就致力于全面简化Java的企业级开发(JAVAEE) , 不是单纯的针对于WEB应用开发中的某一个层面, Spring框架会贯穿于WEB应用开发的各个层面。

  2. Spring的核心支持:
    在这里插入图片描述

  3. Spring框架可以整合Struts2、Mybatis、Hibernate等一些其他框架。

  4. Spring框架引入了众多的设计模式: 工厂设计模式(专注于对象的创建)、原型设计模式、 策略设计模式、适配器设计模式、模板设计模式等。

二、工厂设计模式的践行

  1. 工厂设计模式专注于简化对象的获取方式, 通过工厂类提供对象。

  2. 通用工厂类的编写:

2.1 工厂配置文件 : 负责指定工厂未来可以生产的对象

2.2 工厂类 : 根据调用者的需要,提供对象

  1. 工厂模式的好处: 解耦和, 提高了项目的可维护性。

三、使用Spring开发第一个程序

  1. 搭建开发环境

1.1 引入jar包

在这里插入图片描述

1.2 引入配置文件 : 引入Spring工厂配置文件

PS: 工厂配置文件放置位置没有强制要求,名字也没有强制要求。 建议: 放在src根目录下,名字叫做applicationContext.xml
在这里插入图片描述

  1. 编码

2.1 编写类

2.2 编写工厂配置文件
在这里插入图片描述

2.3 通过Spring工厂获取对象

-Spring开发的核心API

① Java环境初始化工厂对象: ClassPathXmlApplicationContext 【重点】

② WEB环境初始化工厂对象: WebXmlApplicationContext 【了解】
在这里插入图片描述

四、注入(injection) 【重点】

  1. 什么是注入: Spring工厂在创建对象的同时,可以给对象的属性赋值。

  2. Spring注入的实现方式:

2.1 set****注入 【重点】

2.2 构造注入

2.3 自动注入

五、set注入 【重点】

  1. 给八种基本数据类型和String类型注入值

在这里插入图片描述

  1. List集合类型

在这里插入图片描述

  1. Set集合类型

在这里插入图片描述

  1. Map集合类型
    在这里插入图片描述

  2. Properties 类型
    在这里插入图片描述

  3. 自定义对象类型相关注入

6.1 属性为简单的自定义对象类型

在这里插入图片描述

6.2 list集合元素是自定义对象类型
在这里插入图片描述

6.3 set集合元素是自定义对象类型
在这里插入图片描述

6.4 map集合元素的value是自定义对象类型
在这里插入图片描述

PS: set注入的基本实现原理, Spring是通过调用实体属性对应的set方法实现给属性注入值的。

六、构造注入**【**了解】

  1. 构造注入是指Spring工厂通过调用对应的有参构造方法初始化对象,同时给成员变量赋值。

  2. 根据参数的下标注入值: 将构造方法的参数看成一个数组, 下标从0开始。

在这里插入图片描述

  1. 根据参数的名字注入值
    在这里插入图片描述

  2. 根据参数的类型注入值

在这里插入图片描述

七、自动注入(autowire) 【了解】

  1. 自动注入的实现:

1.1 根据工厂中对象的类型注入

在这里插入图片描述

1.2 根据工厂中对象的bean id 与类的属性名匹配注入

在这里插入图片描述

  1. 注意事项: 由于自动注入,是通过在工厂中寻找对应的对象属性值, 所以仅限于自定义对象类型的注入。

八、IOC和DI 【重点 理解并能讲述】

  1. IOC(Inverse Of Control): 控制反转

控制反转是指将创建对象的权利反转给容器负责。在使用Spring框架的开发中, 我们将创建对象的权利交给了Spring工厂容器, 所以这种场景我们成为控制反转。

  1. DI(Dependency Injection): 依赖注入

依赖注入是指Spring工厂在创建对象的同时,可以给对象所依赖的属性注入值。

  1. IOC和DI编程的好处:

3.1 解耦和 (弱耦合)

3.2 提高了项目的可维护性, 降低了企业维护项目的成本。

九、Spring工厂控制Java对象创建的次数 【重点】
在这里插入图片描述

  1. 单例模式创建的对象

XxxService XxxDao

  1. 多例模式创建的对象

Struts2的action实现类

作业:

  1. 使用JDBC技术完成对商品表的开发:

Create table product( Id number(9) primary key, Name varchar2(50), Price number(9,2), Orgin varchar2(50)// 产地 );

1.1 完成service和dao的编写, 功能:

-查询所有产品

-根据价格区间查询产品

-根据名字模糊查询产品

-根据ID查询产品

-添加产品

-修改产品信息

-删除产品

要求: 使用依赖注入在service中注入dao对象, service对象交给Spring工厂创建

一、复杂对象的创建 【重点】

  1. 复杂对象是指无法通过手动new出来的对象。

在这里插入图片描述

  1. 使用FactoryBean<?>接口实现复杂对象的创建

2.1 定义类实现FactoryBean接口, 通过接口的泛型指定创建的复杂对象类型

在这里插入图片描述

2.2 将FactoryBean接口实现类交给Spring工厂管理
在这里插入图片描述

2.3 通过工厂获取对象

在这里插入图片描述

练习: 使用FactoryBean技术创建SqlSessionFactory

**二、**配置文件的参数化 【重点】

  1. 将Spring工厂配置文件中数据库相关配置,提取到小配置文件 xxx.properties 保存
    在这里插入图片描述

  2. 在Spring工厂配置文件需要引入外部的小配置文件
    在这里插入图片描述

  3. 配置文件参数化的好处: 利于项目的维护 。

三、Spring工厂创建对象的几个细节

  1. Spring工厂创建对象的生命周期

1.1 创建:

  • 在Spring工厂初始化的时候会创建所有的单例对象

  • 对于多例模式的对象, 每一次调用的时候创建

1.2 销毁:

  • Spring工厂关闭的时候销毁
  1. Spring工厂支持我们自定义对象的初始化方法和销毁方法

在这里插入图片描述

四、AOP 【重点】

  1. AOP引言

1.1 OOP ( Object Oriented Programming ) : 面向对象编程, 强调的是以对象为单位,进行编程操作,解决问题。
1.2 AOP ( Aspect Oriented Programming) : 面向切面编程 ,以切面为单位,进行编程操作,去解决问题。

在这里插入图片描述

1.3 在现有的项目当中, 存在着一些散落在系统中 “方面”的功能(额外功能)代码 , AOP所要解决的问题就是将这些散落在系统中的代码, 提取到一个位置进行定义 , 通过织入的方式在添加到相关的位置,实现功能。

  1. 静态代理 【了解】

在这里插入图片描述

2.1 实现静态代理

① 定义一个接口

② 书写接口的原始实现

③ 书写代理的实现类

2.2 静态代理的优缺点:

① 优点 : 通过引入代理类使得额外功能与 核心的业务功能实现,降低了耦合, 程序的灵活性得到了提升。

② 缺点 :

  • 一个代理类只能针对代理一个原始类, 对着业务操作类的增加, 会产生大量的代理类。

  • 静态代理实现的代理类,额外功能大量的冗余。

2.3 代理的思想和最终目的 : 通过代理类给原始类增加额外功能, 使额外功能与核心的业务操作之间降低耦合。

  1. Spring的AOP开发 : 本质是基于动态代理实现的 。【重点】

3.1 动态代理的最终目的也是通过代理类给原始类增加额外功能。 但是区分于静态代理的是:

  • 静态代理中的代理类,是由程序员手工编写的。

  • 动态代理中的代理类, 是程序在运行过程中产生创建的 。

3.2 Spring动态代理的开发流程

① 编写原始类

在这里插入图片描述

② 编写额外功能类(通知 advice)

PS: 引入AOP 支持jar包

在这里插入图片描述

  • 前置通知 : 是指在原始方法执行之前添加额外功能。

在这里插入图片描述

  • 后置通知(返回通知) : 是指在原始方法执行成功后加入额外功能。

  • 环绕通知: 是指在原始方法的执行前后加入额外功能。

  • 异常通知: 当原始方法抛出异常是加入额外功能。

③ 定义切点: 定义额外功能加入的位置。 比如: 在哪个包中的 哪个类中 哪个方法上增加额外功能。

  • 编写切入点表达式

在这里插入图片描述

execution(* .*(…)) :代表给所有的包中所有的类中的所有的方法都织入额外功能 。

第一个* : 匹配方法的返回值

第二个*: 匹配包名

第三个*: 匹配类名

第四个*: 匹配方法名

(…) : 匹配方法的参数列表

例:

  • 给com.baizhi.service包下的所有类中所有方法加额外功能:

execution(* com.baizhi.service..(…)) | 包结构后面一个点, 不包含子包

execution(* com.baizhi.service….(…)) | 包结构后面两个点, 包含子包

  • 给类名是OrderServiceImpl中的所有方法加入额外功能

execution(* …OrderServiceImpl.(…))

  • 给所有方法名为save的加入额外功能

execution(* .save(…))

  • 给所有方法参数第一个是String类型的加入额外功能

execution(* .*(String,…))

④ 编织 : 根据切入点定义的位置 将额外功能加入到原始类。

在这里插入图片描述

⑤ 测试

在这里插入图片描述

作业:

  1. 在商品的业务操作上增加额外功能:

在控制台输出访问方法的名字 以及访问方法的时间

  1. 课堂案例重点练习

一、AOP续

  1. 编写原始类

  2. 编写通知(额外功能)

2.1 前置通知 : MethodBeforeAdvice

2.2 返回通知 : AfterReturningAdvice

在这里插入图片描述

2.3 环绕通知 : MethodInterceptor 【重点】

在这里插入图片描述

环绕通知使用的思考:

在这里插入图片描述

2.4 异常通知 :ThrowsAdvice

在这里插入图片描述

在这里插入图片描述
3. 定义切点 : 通过切入点表达式指定额外功能加入的位置

3.1 execution切入点函数 : 可以匹配返回值、包结构、类名、方法名以及参数列表 【重点】

  • 基本语法规则: execution(* .*(…))

匹配com.baizhi.service包下所有类(包含子包)

execution(* com.baizhi.service….(…))

匹配类名是UserServiceImpl中的所有方法

execution(* …UserServiceImpl.(…))

一个标准的切入点表达式:

execution(* com.baizhi.service….(…))

3.2 within切入点函数: 可以匹配包结构和类

  • 语法规则: within() | 第一个匹配包结构 第二个匹配类

  • 例:

匹配com.baizhi.service包下所有类(包含子包) : within(com.baizhi.service…*)

匹配类名是UserServiceImpl中的所有方法: within(*…UserServiceImpl)

3.3 args切入点函数: 只匹配参数列表

  • 语法规则: args(…) | 两个点代表匹配所有的参数列表(包含没有参数的)

  • 例:

只匹配有一个Integer类型参数的 : args(Integer)

匹配两个String参数类型的: args(String,String)

匹配最后一个参数时String 类型的: args(…,String)

3.4 @annotation切入点函数 : 用于匹配注解

  • 语法规则: @annotation(指定注解的类型)

  • 例:

匹配方法上使用com.baizhi.anno.Log类型注解的:

@annotation(com.baizhi.anno.Log)

3.5 切入点函数之间进行逻辑运算: and| 并且 or| 或者

  • 例:

匹配参数列表最后一个是String类型,并且使用了Log注解的:

agrs(…,String) and @annotation(com.baizhi.anno.Log )

  1. 编织

在这里插入图片描述

  1. 测试 : 使用了Spring的AOP开发之后, 从工厂获取到的是一个代理对象

  2. AOP总结:【重点】

6.1 什么是Spring 的AOP : AOP称为面向切面编程, Spring的AOP本质是基于动态代理实现的, 通过程序运行过程中产生代理对象, 给原始对象增加额外功能。

6.2 基于AOP编程的好处: 可以将程序中的一些额外功能与核心的业务操作之间降低耦合;AOP编程也从另一个维度提高了代码的复用性。(我们将额外功能提取到一处定义,未来根据切入点的定义位置, 再应用到我们的业务操作中)。

在这里插入图片描述

二、Spring AOP实现的原理 : 基于动态代理实现的。【了解】

  1. JDK原生的动态代理 :
    在这里插入图片描述

在这里插入图片描述

  1. Cglib的动态代理: Cglib技术生成代理对象的规则是, 让代理类去继承原始类。

  2. Spring在这里才用了策略设计模式, 根据原始类的实际情况选择使用JDK的方式或Cglib的方式生成代理对象。 如果原始类实现了接口,则采用JDK的方式。 如果原始类没有实现接口, 那么采用Cglib的方式。

三、SM整合 (Spring+ Mybatis) 【重点】

  1. Spring与Mybatis框架整合的思路: Spring框架会接管mybatis-config.xml配置文件。

在这里插入图片描述

  1. 数据源讲解(连接池)

2.1 连接池的好处 : 减少频繁的创建和销毁连接对象, 提高了连接资源的复用性, 也会提升系统的执行效率。

在这里插入图片描述

2.2 主流的连接池技术 :

  • alibaba 提供的druid数据源

  • c3p0 数据源

  • dbcp数据源

2.3 druid数据源基本使用

在这里插入图片描述

  1. 整合流程

在这里插入图片描述

3.1 搭建开发环境

  • 引入整合的所有jar包

  • 引入mapper文件

  • 引入spring的配置文件

  • 引入数据库配置的小配置文件

3.2 开发

  • 建表

  • 封装实体类

  • 定义DAO接口

  • 编写mapper文件

  • 编写spring工厂配置文件

  • 测试

作业: 使用Spring+mybatis整合完成学生互动系统的dao开发

要求: 必须完成测试
在这里插入图片描述

DAO需要完成:

UserDao

User selectByUsernameAndPassword(String username,String password);

void insertUser(User user);

StudentDao

List selectAll(); // 关系查询

List selectLike(String cname); // 根据班级名模糊查询

List selectLike(String sname); // 根据学生姓名模糊查询

void updateStudent(Student stu);

void deleteById(Integer id);

ClazzDao

List selectAll(); // 查询所有的班级

TeacherDao

List selectAll(); // 关系查询

一、事务管理

  1. 什么是事务:

1.1一个事务是由一到多条SQL命令组成, 组成事务的一组SQL命令是不可分割的整体,要么一起成功要么一起失败。 为了保证数据的完整性和一致性需要做事务的控制。

1.2 站在用户的角度, 一个事务就是用户的一个业务操作, 事务也是用户操作数据库的基本单元。

  1. JDBC中的事务管理机制:JDBC中默认事务是自动提交的,由connection对象管理。

  2. mybatis中事务管理机制: 默认事务是自动回滚的。

  3. Spring框架的事务管理

4.1 Spring框架管理事务的对象: DataSourceTransactionManager

4.2 Spring框架管理事务的机制: Spring采用的是声明式事务管理 。 开发人员需要在Spring的配置文件中, 声明自己对于不同业务操作的管理事务态度, Spring框架会根据程序员的声明, 进行具体的事务管理。 比如: 写操作一般是必须有事务控制的, 而读操作可以有事务也可以没有。

4.3 Spring事务管理的开发流程:Spring的事务管理开发,是基于Spring的AOP展开。

① 编写原始类 - 业务操作领域

在这里插入图片描述

② 创建事务管理对象 - DataSourceTransactionManager(依赖于数据源对象)
在这里插入图片描述

③ 编写额外功能 – 对于事务管理的声明配置

在这里插入图片描述

④ 定义切点

⑤ 编织
在这里插入图片描述

⑥ 测试
在这里插入图片描述

  1. 事务属性

5.1 事务的传播性 【重点】

① 事务的传播性是指, 当一个业务操作调用另一个业务操作时, 两个事务之间是如何配合的。

  • PROPAGATION_REQUIRED(propagation_required)【默认】 : 事务是必须的。外层有事务, 内层加入外层的事务中。外层没有事务,内层自己创建一个新的事务。

  • PROPAGATION_SUPPORTS(propagation_supports): 支持事务。外层有事务,内层加入外层的事务。外层没有事务,不会主动创建事务。

  • PROPAGATION_REQUIRES_NEW(propagation_requires_new): 无论什么情况,都会创建新的事务。外层有事务,先挂起外层的事务,自己创建一个新的事务,执行完毕,再去执行外层的事务。外层没有事务,自己主动创建一个新的事务。

  • PROPAGATION_NEVER(propagation_never): 从来都不能运行在有事务的环境,如果有事务则抛出异常。

  • PROPAGATION_MANDATORY(propagation_mandatory):必须运行在事务环境, 没有事务则会抛出异常。

5.2 事务的隔离性 【重点 要会表述隔离级别的特点】

① 事务的隔离性是指,在多个事务运行的环境下,一个事务跟另一个事务之间的隔离级别。

② 名词解释:

  • 脏读 :一个事务读取到了另一个事务没有提交的数据。

  • 不可重复读 :在同一个事务中进行了两次的读取(同一条数据),但是两次的结果不一致。

  • 幻影读 :在同一个事务中,对于一张表进行了两次统计, 但是两次的统计结果不一致。

③ 事务的隔离级别 :

  • 读未提交(read uncommitted): 一个事务读取到了另一个事务没有提交的数据。

  • 存在问题:脏读 不可重复读 幻影读

  • 安全性:极差

  • 效率: 极高

  • 读提交(read committed):一个事务只能读取到另一个事务提交的数据。

  • 存在问题:不可重复读 幻影读

  • 安全性: 一般

  • 效率: 一般

  • 可重复读(read repeatable):一个事务中,对于同一条数据的两次读取结果一致。

  • 存在问题:幻影读

  • 安全性:很好

  • 效率:较差

PS:当一个事务操作某条数据的时候,对当前的数据进行加锁的操作,当事务结束时,再释放锁。

  • 序列化读 (serializable): 一个事务中,对于同一张表进行的两次统计结果一致。

  • 安全性: 极高

  • 效率: 极差

PS: 当一个事务对一张表进行统计的时候, 对整张表进行加锁的操作, 事务结束释放锁。

④ Oracle数据库的默认隔离级别: 读提交

⑤ Mysql数据默认隔离级别: 可重复读

5.3 事务的回滚性

① 回滚性是指,当程序出现异常时,Spring对事务的处理方式。

② 默认情况:

  • 当抛出运行时异常事务做回滚处理。

  • 当抛出非运行时异常, 事务自动提交。

③ 手动自定义回滚性:

在这里插入图片描述

在这里插入图片描述

PS: 异常的回滚, 默认使用Spring的方式就可以。

5.4 事务的超时性
在这里插入图片描述

5.5 事务的只读性

当一个事务被设置成只读之后, 那么当前事务内只允许进行读的操作, 不允许进行写操作。
在这里插入图片描述

二、使用Spring管理事务整合mybatis开发

  1. 搭建开发环境

1.1 引入jar包

1.2 引入配置文件

  • spring_core.xml

  • mapper.xml

  • jdbc_oracle.properties

  • log4j.properties |必须放在src根目录下

  1. 编码

2.1 创建表

2.2 封装实体类

2.3 定义DAO接口

2.4 编写mapper.xml

2.5 定义service接口 == 》 编写service的实现类

2.6 编写 spring_core.xml

  • 引入外部小配置文件

  • 配置数据源

  • 配置SqlSessionFactory

  • 配置DAO实现类对象的创建

  • 配置创建service

  • 配置创建DataSourceTransactionManager

  • 声明事务管理的配置

  • 定义切入点

  • 编织

三、SSM整合(Spring + Struts2+ mybatis)

  1. 整合的思路

在这里插入图片描述

  1. Spring + Struts2整合

2.1 搭建开发环境

  • 引入整合jar包

  • 引配置文件

  • spring_core.xml

  • struts.xml

  • 初始化配置 : 编写web.xml

① 配置Struts2的核心过滤器

在这里插入图片描述

② 初始化Spring工厂的配置

在这里插入图片描述

2.2 编写一个Struts2的控制器

在这里插入图片描述

  1. SSM整合

3.1 搭建开发环境

  • 引jar包

  • 引配置文件

  • 初始化配置

3.2 编码

  • 建表

  • 封装实体

  • 编写DAO

  • 编写Service

  • 编写action

  • 编写spring_core.xml

一、事务管理补充

  1. 事务传播属性失效的场景: 当一个Service中的方法直接调用了本类中的另一个方法时, 工厂中的传播属性配置会失效。 原因是,此时直接调用没有通过工厂获取对象, 那么工厂的事务声明配置也就没有任何意义。

  2. 解决事务传播属性失效的方案:
    在这里插入图片描述

  3. Spring的声明式事务管理机制的好处: 通过在配置文件中声明事务管理的方式, 开发人员在编写业务操作的时候, 不必去关注事务的操作了, 更多的精力投入到业务开发中。

二、使用注解的方式管理事务

  1. 使用注解方式管理事务后, 会替换掉原有配置文件的管理事务配置。

  2. 注解管理事务 对配置文件的替换

在这里插入图片描述

  1. 使用注解管理事务的流程

3.1 在工厂配置文件中开启注解管理事务

在这里插入图片描述

3.2 在需要进行事务管理的业务操作上书写注解 : @Transactional .

在这里插入图片描述

① @Transactional注解用于方法上: 只针对当前的方法做事务属性的控制。

② @Transactional注解用于类上:针对当前类中所有的方法进行事务属性控制。

在这里插入图片描述

PS: 当类上与方法上同时指定了事务传播属性的配置时, 以方法上的为标准。

三、Spring的注解开发

  1. 注解开发的目的: 通过注解形式的开发,简化我们的配置文件 。

  2. Spring注解开发的流程:

2.1 开启注解的扫描

在这里插入图片描述

PS: base-package 属性的值:

  • 扫描多个包结构: 多个包结构之间可以使用逗号分隔 | 为了提高可读性,建议不要使用通配符同时也支持通配符的方式扫描

在这里插入图片描述

2.2 在指定的类上书写注解

在这里插入图片描述

PS: @Component注解创建类的对象, 默认的beanid是 当前类名的首字母小写

比如:

@Component // 此时通过工厂获取Person对象的beanid为: person

public class Person{}

2.3 从工厂中获取对象

在这里插入图片描述

2.4 注解替换配置文件的基本对应关系

在这里插入图片描述

PS: 当注解与配置文件有冲突的时候, 配置文件会覆盖掉注解的使用。

  1. Spring开发常用的注解:

3.1 用于创建DAO: @Repository

3.2 用于创建Service: @Service

3.3 用于创建控制器:@Controller

3.4 自动注入: @Autowired (Spring框架提供的) | @Resource (是JDK原生提供)

在这里插入图片描述

3.5 指定创建对象的模式: @Scope | @Scope(“prototype”) 多例模式创建对象

3.6 事务控制注解: @Transactional

在这里插入图片描述

四、注解开发的整体流程

  1. 搭建开发环境

1.1 引入jar包

1.2 引入配置文件

  • spring_core.xml

  • jdbc_oracle.properties

  • struts.xml

  • mapper.xml

  • log4j.properties

1.3 初始化配置 : 编写web.xml

  1. 编码开发

2.1 创建表

2.2 封装实体类

2.3 编写DAO

2.4 编写Service

PS:需要在service的实现类上使用@Service注解, 还要使用@Autowired自动注入DAO对象

使用@Transactional进行事务控制

2.5 编写Controller | 如果是Struts2的控制器类, 需要指定 @Scope(“prototype”)

PS: 需要在控制器类上使用@Controller注解, 并且需要使用@Autowired自动注入Service对象

2.6 编写配置文件 : spring_core.xml

  • 引入外部小配置文件

  • 开启注解扫描

  • 配置数据源

  • 配置sqlSessionFactory

  • 配置创建DAO实现类的对象

  • 创建事务管理对象: DataSourceTransactionManager

  • 开启事务注解驱动

五、Spring整合Junit测试

  1. 引入spring整合 测试的jar包

  2. 测试编码
    在这里插入图片描述

二、SpringMVC

一、概述

  1. MVC编程思想

1.1 M(odel) : Mybatis |JDBC

1.2 V(iew) : JSP| HTML

1.3 C(ontroller) : Servlet | Struts2 | SpringMVC

  1. 什么是SpringMVC

2.1 SpringMVC框架是Spring家族的一款子产品, 主要用于解决控制器层的问题。

2.2 使用SpringMVC框架可以与Spring框架进行更加完美的整合。

  1. 控制器层需要解决的问题

3.1 接收客户端请求参数并进行相关的数据类型转换

3.2 使用作用域管理数据

3.3 流程跳转

  1. SpringMVC框架与Struts2框架的对比

在这里插入图片描述

二、 使用SpringMVC框架开发一个控制器

  1. 搭建开发环境

1.1 引入jar包: springMVC的jar包就是基于原有spring的jar包基础上, 额外引入springmvc的jar包

在这里插入图片描述

1.2 引入配置文件: 就是spring的配置文件, 额外引入springmvc框架的文件头(xsd)
在这里插入图片描述

1.3 初始化配置 : 编写web.xml, 配置springmvc的核心入口Servlet

在这里插入图片描述

  1. 编写控制器

在这里插入图片描述

PS:

@RequestMapping注解:

  1. 使用在类上,相当于namespace, 便于对控制器进行分类管理

  2. 使用在方法上,相当于actionName

在这里插入图片描述

  1. 编写配置文件

在这里插入图片描述

三、 获取原生ServletAPI对象

在这里插入图片描述

四、SpringMVC中的跳转

  1. controller --> JSP

1.1 请求转发:

在这里插入图片描述

1.2 请求重定向:

在这里插入图片描述

  1. controller --> controller

在这里插入图片描述

五、 Spring+ SpringMVC+ mybatis整合

  1. 引入jar包

  2. 引入配置文件

  • spring_core.xml

编写数据源 以及事务控制操作等

  • spring_mvc.xml

编写SpringMVC框架的配置

  1. 初始化配置

  2. 编码开发

六、 Spring的收参机制

  1. 收集请求参数: 通过控制器类方法的入参来接收。

  2. 接收八种基本数据类型和String类型:

在控制器类的方法参数列表中声明参数:

类型: 是您想要的类型

名字: 与请求参数的key对应

在这里插入图片描述

  1. 接收自定义对象类型

在这里插入图片描述

  1. 接收日期类型

在这里插入图片描述

4.1 自定义接收日期类型的格式

在这里插入图片描述

七、 SpringMVC中的数据管理

  1. model机制: 通过在控制类方法的入参声明Model, 由SpringMVC自动传入model对象的值, 使用model对象操作作用域。

在这里插入图片描述

作业:

使用spring springmvc mybatis 完成ems2.0

一、Spring接收请求参数

  1. @RequestParam

在这里插入图片描述
在这里插入图片描述

  1. 接收list集合类型请求参数

在这里插入图片描述

在这里插入图片描述

  1. 接收日期类型

在这里插入图片描述

PS: 默认请求参数的格式必须是 yyyy/MM/dd

在这里插入图片描述

二、 处理POST请求的中文乱码

在这里插入图片描述

PS: GET 请求中文乱码处理: tomcat/conf/server.xml

在这里插入图片描述

三、SpringMVC数据管理机制

  1. 操作request作用域 : request.setAttribute(String name,Object value);

1.1 Model

在这里插入图片描述

1.2 ModelMap

在这里插入图片描述

1.3 ModelAndView : 可以同时管理作用域的数据 以及 跳转的视图

要求: 控制器类方法的返回值类型必须是ModelAndView

① 管理作用域的数据

② 设置跳转的视图
在这里插入图片描述

PS:

在这里插入图片描述

  1. 操作session作用 :
  • 存数据: session.setAttribute(String name,Object value);

  • 销毁:session: session.invalidate();

在这里插入图片描述

在这里插入图片描述

开发建议: 操作session作用域, 使用原生的HttpSession

四、 ajax技术与SpringMVC控制器交互
在这里插入图片描述

  1. 使用Sprinvmvc控制处理异步请求

1.1 引入springmvc天生支持的json转换工具包 – jackson

在这里插入图片描述

1.2 编写一个处理异步请求的springmvc 控制器

在这里插入图片描述

1.3 发送ajax请求
在这里插入图片描述

  1. 使用异步请求发送json字符串–> 控制自动将json字符串转成java 对象

在这里插入图片描述

PS: 请求方式必须是POST , 指定contentType=’application/json’

在这里插入图片描述

在这里插入图片描述

五、验证码的实现

  1. 为什么需要验证码?

1.1 判断是不是一个真正的人在操作。

PS: 实现验证码图片的思路:

-先生成验证码随机数

-将验证码随机数绘制到图片上

  1. SpringMVC 控制器实现验证码

在这里插入图片描述

六、文件上传和下载

先引入工具包:
在这里插入图片描述
在这里插入图片描述

  1. 文件上传

1.1 客户端表单处理:

  • 必须是POST请求方式

  • enctype=multipart/form-data : 目的是将文件的实际内容进行二进制编码处理后,再进行发送

在这里插入图片描述

1.2 编写控制器

在这里插入图片描述

1.3 编写配置文件 : 指定一个上传文件的解析工具类

在这里插入图片描述

  1. 文件下载

在这里插入图片描述

七、拦截器

  1. 拦截器主要作用: 将多个控制器类当中的共性代码,提取到拦截器中定义, 在请求到达目标控制器之前,先执行拦截器, 提高了代码的复用性。

  2. SpringMVC中拦截器的实现

2.1 实现一个接口 : HandlerIntercepter

在这里插入图片描述

2.2 编写配置文件

在这里插入图片描述

  1. 拦截器配置的细节

3.1 拦截指定的请求

在这里插入图片描述

3.2 排除不拦截的请求

在这里插入图片描述

  1. 拦截器中的重定向处理
    在这里插入图片描述

PS : 拦截器执行的顺序, 根据配置的先后顺序执行的。

八、全局异常处理机制

  1. 自定义异常实现的方式

1.1 实现运行时异常: 继承RuntimeException

1.2 实现非运行时异常: 继承Exception

  1. 异常处理方式

2.1 积极处理: try{}catch(捕捉异常的类型){}

2.2 消极处理: throws 异常类型 | 向上抛出

  1. SpringMVC的全局异常处理

在这里插入图片描述

在这里插入图片描述

九、 SpringMVC入口Servlet第二种配置方式
在这里插入图片描述

在这里插入图片描述

十、SpringMVC 控制器的特点

  1. 所有的控制器类对象是单例的。 不建议定义一些保存数据的成员变量。

  2. Struts2控制器是多例的,每一次请求都会创建一个新的控制器对象。

三、Springboot

  1. springboot概念

​ Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

  1. springboot优点

  2. 创建独立的Spring应用程序

  3. 嵌入的Tomcat,无需部署WAR文件

  4. 简化Maven配置

  5. 自动配置Spring

  6. springboot和spring.springMVC的区别

Spring 是一个“引擎”;

Spring MVC 是基于Spring的一个 MVC 框架 ;

Spring Boot 是基于Spring4的条件注册的一套快速开发整合包。

  1. springboot约束

maven的项目结构

src/main/java

​ com.baizhi 主包

​ entity 子包

​ dao

​ service

​ controller

​ util

​ conf

​ Application.java 入口类必须和子包同级

​ webapp

​ WEB-INF

​ web.xml

src/main/resource

​ com.baizhi.mapper

​ application.yml 名称必须为application,里面的每一个空格都是必须的

​ application.yaml

​ application.properties

src/test/java

​ com.baizhi.test

src/test/resource

第一种方式,用maven创建

  1. 用maven创建一个web项目

  2. 导入springboot的jar包

    <!-- 父类依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
    </parent>
    <!-- web -->
    <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>
        <!-- 只在test测试里面运行 -->
        <scope>test</scope>
    </dependency>
    
  3. 创建入口类Application.java

    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class,args);
        }
    }
    
  4. 配置文件application.yml

    server:
      port: 9999
      context-path: /springboot
    
  5. 运行启动类

@SpringBootApplication注解是一个组合注解
	@Configuration   //声明当前类是一个配置类
	@EnableAutoConfiguration   //开启自动配置
	@ComponentScan    //扫描组件

第二种创建方式 快速构建

创建module的时候选择spring initializr

注意:更改parent的版本到1.5.6,不要使用默认的2.1.3

与第三方技术的集成

集成mybatis
  1. 导入jar包
<!--整合mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.19</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
</dependency>
  1. 配置application.yml

    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/test
        username: root
        password: root
    mybatis:
      mapper-locations: classpath:/com/baizhi/mapper/*Mapper.xml
      type-aliases-package: com.baizhi.entity
    
  2. 在启动类application.java上书写注解@mapperscan。用来扫描dao

    @SpringBootApplication
    @MapperScan(value = "com.baizhi.dao")
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class,args);
        }
    }
    
集成jsp
  1. 导入jar包

    <!--与jsp集成-->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>
    
  2. 引入jsp插件

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    
    
  3. 配置视图解析

    spring:
      mvc:
        view:
          prefix: /
          suffix: .jsp
    
    
  4. 配置jsp热部署

    server:
      jsp-servlet:
        init-parameters:
          development: true
    
    
集成lombok

介绍:在项目中使用Lombok可以减少很多重复代码的书写。比如说getter/setter/toString等方法的编写。

集成

  1. 安装插件

  2. 导入jar包

    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.4</version>
        <scope>provided</scope>
    </dependency>
    
    

    3.常用注解

    @Data 注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
    @Setter :注解在属性上;为属性提供 setting 方法
    @Getter :注解在属性上;为属性提供 getting 方法
    @NoArgsConstructor :注解在类上;为类提供一个无参的构造方法
    @AllArgsConstructor :注解在类上;为类提供一个全参的构造方法
    @NonNull : 如果给参数加个这个注解 参数为null会抛出空指针异常
    @Value : 注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。
    
    
集成logback
  1. 日志分类

    根日志:项目级别的日志

    子日志:类级别的日志 dao、service

  2. 日志级别

    OFF、FATAL、(ERROR、WARN、INFO、DEBUG)、TRACE、 ALL。

  3. 导入logback.xml文件放到resources目录下

集成MBG(mybatis-generator)

根据库表帮助你自动生成实体,dao,mapper.xml

​ 使用

  1. 导入jar包

    <!--MBG集成jar包-->
    <dependency>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-core</artifactId>
        <version>1.3.2</version>
    </dependency>
    
    
  2. 导入插件

    <!--MBG插件-->
    <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.2</version>
        <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.38</version>
            </dependency>
        </dependencies>
        <configuration>
        <!--配置文件的路径 --> 	<configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
            <overwrite>true</overwrite>
        </configuration>
    </plugin>
    
    
  3. 导入配置文件 mybatis-generator.xml

  4. 运行插件

集成通用mapper
  1. 使用通用mapper

    1. 导jar包

      <!--通用mapper的启动器   注意这是mybatis和mybatis启动器的封装-->
              <dependency>
                  <groupId>tk.mybatis</groupId>
                  <artifactId>mapper-spring-boot-starter</artifactId>
                  <version>2.1.1</version>
              </dependency>
      
      
    2. dao集成mapper<实体类>

    3. @mapperscan 注意:一定要用tk的包,不用原生的了

    4. 注解

      @Table  //表名
      @Id    //声明主键
      @Column //声明字段的名称
      @transient //忽略表中没有的字段对应的属性
      
      

      总结

      lombok优雅的编码,省略getset方法,有参无参构造等等
      logbackspringboot的官方日志
      MBGmybatis-generator 逆向工程,根据库表生成dao,实体,mapper.xml
      通用mapper根据实体类生成对应的增删改查

四、springcloud 框架的集合

1.单体应用架构存在的问题

一个归档包(例如war)包含所有功能的应用程序,通常称为单体应用。
在这里插入图片描述

  • 复杂性高:定时炸弹
  • 技术债务:no broken don’t fix
  • 可靠性差:单个bug,导致整个系统瘫痪
  • 阻碍技术创新

2.架构的演变

在这里插入图片描述

3.什么是微服务

the microservice architectural style [1] is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.

  • 每个服务可独立运行在自己的进程里
  • 一系列独立运行的微服务共同构建起整个系统
  • 每个服务为独立的业务开发,一个微服务只关注某个特定的功能,例如订单管理,用户管理
  • 微服务之间通过一些轻量的通信机制进行通信,例如Restful API进行调用
  • 可以使用不同的语言与数据存储局势

官网链接:https://www.martinfowler.com/articles/microservices.html

4.微服务的解决方案

在这里插入图片描述

5.什么是springcloud

​ Spring Cloud是一个含概多个子项目的开发工具集,集合了众多的开源框架,他利用了Spring Boot开发的便利性实现了很多功能,如服务注册,服务注册发现,负载均衡等.Spring Cloud在整合过程中主要是针对Netflix(耐非)开源组件的封装.

​ NetFlix 是美国的一个在线视频网站,微服务业的翘楚,他是公认的大规模生产级微服务的杰出实践者,NetFlix的开源组件已经在他大规模分布式微服务环境中经过多年的生产实战验证,因此spring cloud中很多组件都是基于NetFlix组件的封装

​ Spring Cloud的出现真正的简化了分布式架构的开发

6.springcloud的特点

  • 服务注册和发现

  • 路由

  • service - to - service调用

  • 负载均衡

  • 断路器

7.Spring Cloud 的服务架构图

在这里插入图片描述

8.Eureka组件

Eureka是Netfilx开源的服务发现组件,本身是一个基于rest的服务,它包含client和server两部分。

Spirng Cloud将它集成在子项目Spirng Cloud Netfilx中,从而实现服务的注册和发现

1.eureka中的server和client的介绍及特点
  • Eureka Server:提供服务发现的能力,各个微服务启动时,会向Eureka Server注册自己的信息例如(IP,端口号,服务名称等),Eureka会存储这些信息
  • Eureka Client:是一个java的客户端用来简化Eureka Server的交互
  • 微服务启动后会周期性的(默认30秒)向Eureka Server发送心跳,如果Eureka在规定的时间没有收到心跳,则会注销该实例(默认90秒)
  • Eureka Client会缓存服务注册表中的信息。这种方式有一定的优势首先可以降低Eureka Server的压力,其次当所有的Eureka Server宕机服务调用方依然可以完成调用
2.服务注册与服务发现
  • 服务注册:当微服务client启动时,向Eureka Server发起注册,并上报该节点的相关信息
  • 服务发现:client从Eureka Server获取注册信息,然后发起调用
3.Eureka Server开发
1.引入springcloud的相关依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.baizhi</groupId>
    <artifactId>springcloud_regist</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>springcloud_regist</name>
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <!--引入springboot的父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>
    <dependencies>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <!-- spring boot test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>
2.入口类的开发
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer.class,args);
    }
}

3.配置文件
//设置eureka server 的交互地址,之后的服务获取和服务注册都需要依赖于这个地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
//表示是否将自己注册到eureka上
eureka.client.register-with-eureka=false
//表示是否从eureka server上获取注册信息
eureka.client.fetch-registry=false
spring.application.name=eureka
server.port=8761
4.Eureka Client的开发
1.jar包和Server相同
 将spring-cloud-starter-eureka-server改为spring-cloud-starter-eureka
      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
2.入口类
@EnableDiscoveryClient
@SpringBootApplication
public class HiApplication {

    public static void main(String[] args) {
        SpringApplication.run(HiApplication.class, args);
    }
}

3.配置文件

server.port=8989
eureka.client.service-url.default-zone=http://localhost:8761/eureka
spring.application.name=hi
eureka.instance.prefer-ip-address=true
5.Eureka client之间的相互调用
1.导入相关的jar
和eureka server 一致
2.java配置RestTemplate
    @Bean
    @LoadBalanced
    RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

3.调用
   @Autowired
   RestTemplate restTemplate;

    @RequestMapping("/hi")
    public String hi(String name) {
        String restTemplateForObject = restTemplate.getForObject("http://服务名/test/test?name=" + name, String.class);
        return restTemplateForObject;
    }

6.Eureka的自我保护机制

Eureka进入自我保护机制的最直接体现,是Eureka首页输出警告如图:

默认情况下,如果Eureka Server在一定时间内没有接受到服务实例的心跳,Eureka将会注销该实例(默认90秒).但是当网络分区发生故障时,微服务和Eureka Server 无法正常通信.以上行为可能变得特别危险了-因为微服务本身是健康的,此时不能注销该服务实例.

Eureka通过自我保护机制来解决这个问题,当Eureka Server在短时间丢失过多的服务实例(可能发生了网络分区的故障,那么这个节点进入自我保护模式,一旦进入此模式,Eureka Server将会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不再注销任何的服务实例),当网络故障恢复后,Eureka会自动退出自我保护模式。

综上,自我保护模式是一种应对网络故障的安全保护措施,它的架构哲学是宁可同时保留所有的微服务,也不盲目注销任何健康的微服务,使用自我保护模式可以让Eureka,更加健壮,稳定。

在springcloud中可以通过

#关闭自我保护机制  默认开启
eureka.server.enable-self-preservation=false

如果想及时剔除eureka的服务除了关闭自我保护机制外,可以调低eureka的心跳值

eureka-server服务端
配置文件中我们添加如下配置

#关闭保护机制,以确保注册中心将不可用的实例正确剔除
eureka.server.enable-self-preservation=false
#(代表是5秒,单位是毫秒,清理失效服务的间隔 )
eureka.server.eviction-interval-timer-in-ms=5000


客户端
配置文件中我们添加如下配置

# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
# 配置说明
#  lease-renewal-interval-in-seconds 每间隔10s,向服务端发送一次心跳,证明自己依然”存活“
#  lease-expiration-duration-in-seconds  告诉服务端,如果我20s之内没有给你发心跳,就代表我“死”了,将我踢出掉。
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.instance.lease-expiration-duration-in-seconds=20

7.client的高可用
保证端口号不一致(测试环境)
保证实例名一致

配置如下

eureka.client.service-url.defaultZone=http://peer:8761/eureka
spring.application.name=eureka-producter
server.port=8764        

eureka.client.service-url.defaultZone=http://peer:8761/eureka
spring.application.name=eureka-producter
server.port=8763        

8.Eureka Server的高可用

单节点的Eureka Server 不适合线上的生产环境,Eureka Client会定时连接Eureka Server,获取服务注册表中的信息并缓存在本地,微服务消费远程API总是使用本地缓存的数据,因此一般来说既是Eureka Server发生宕机,也不会影响到服务的调用,但是如果Eureka Server宕机时某些微服务也出现了不可用的情况,Eurek Client中的缓存若不被更新,可能会影响到服务的调用,甚至影响到整个系统的高可用性,因此在生产环境会部署一个高可用的Eureka Server集群。

Eureka可以通过运行多个实例并互相注册实现高可用部署,Eureka Server实例会彼此同步信息。

server.port=8761
eureka.client.service-url.defaultZone=http://peer2:8762/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=peer1

server.port=8762
eureka.client.service-url.defaultZone=http://peer1:8761/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=peer2

注意:在client注册eureka server时 需要填写所有eureka的地址

eureka.client.service-url.defaultZone=http://peer:8761/eureka,http://peer1:8765/eureka

9.Eureka的健康监测

人会生病,就像人一样服务有时候也会出现异常情况,我们也需要知道某个服务的健康状况。我们可以通过添加如下依赖,开启某个服务的健康检查。

      <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>

我们来访问一下这个接口http://localhost:9001/health,看到了一个很简短的健康报告:

{"description":"Spring Cloud Eureka Discovery Client","status":"UP"}

类似的还有

  • info 显示任意的应用信息
  • metrics 展示当前应用的指标信息 true
  • mappings 显示所有@RequestMapping路径的整理列表
  • trace 显示trace信息(默认为最新的一些HTTP请求)
  • health 展示应用的健康信息
  • beans 显示一个应用中所有Spring Beans的完整列表

这其中有一些是敏感信息,出于安全考虑,一般用户无法访问,如果内网情况下可以

eureka.client.healthcheck.enabled=true
#关掉认证(公网下的生产环境不建议,内网部署可以)
management.security.enabled=false

9.http VS rpc

应用间通信方式主要是HTTP和RPC,在微服务架构中两大配方的主角分别是:

  • Dubbo RPC框架

基于dubbo开发的应用还是要依赖周边的平台生态, 相比其它的RPC框架, dubbo在服务治理与服务集成上可谓是非常完善, 不仅提供了服务注册,发现还提供了负载均衡,集群容错等基础能力同时,还提供了面向开发测试节点的Mock和泛化调用等机制。 在spring cloud 出现之前dubbo在国内应用十分广泛,但dubbo定位始终是一个RPC框架。

  • SpringCloud 微服务框架(HTTP通信)

Spring Cloud 的目标是微服务架构下的一栈式解决方案,自dubbo复活后dubbo官方表示要积极适配到spring cloud的生态方式,比如作为springcloud的二进制通信方案来发挥dubbo的性能优势,或者通过dubbo的模块化以及对http的支持适配到Spring Cloud,但是到目前为止dubbo与spring cloud 还是不怎么兼容,spring cloud 微服务架构下微服务之间使用http的RestFul方式进行通信,Http RestFul 本身轻量易用适用性强,可以很容易跨语言,跨平台,或者与已有的系统集成。10.使用Ribbon完成负载均衡

1.Ribbon简介

ribbin是Netflix发布的负载均衡器,有助于控制http和tcp客户端的行为,为ribbon配置服务提供者列表后,ribbon就可以基于某种负载均衡算法,自动的帮助服务消费者去请求。ribbon提供了很多的负载均衡算法例如

  • RoundRobinRule(轮询算法)

  • RandomRule(随机算法)

  • AvailabilityFilteringRule():会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问

  • WeightedResponseTimeRule():根据平均响应的时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够会切换到WeightedResponseTimeRule

  • RetryRule():先按照RoundRobinRule的策略获取服务,如果获取失败则在制定时间内进行重试,获取可用的服务。

  • BestAviableRule():会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

在springCloud中,当ribbon和Eureka配和使用时ribbon可以自动获取服务注册列表,并基于负载均衡算法,请求其中的一个服务提供实例
在这里插入图片描述

2.为服务消费者整合ribbon
1.ribbon和springcloud的启动器

**注意:**如果已经引入了spring-cloud-starter-eureka-server该依赖已经包含了spring-cloud-starter-ribbon,所以不需要再次引入

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

2.ribbon整合RestTemplate
   @Bean
   @LoadBalanced
    RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

3.使用
    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("/hi")
    public String hi(String name) {
        String restTemplateForObject = restTemplate.getForObject("http://HI-SERVICE/test/test?name=" + name, String.class);
        return restTemplateForObject;
    }

4.验证负载均衡
  @RequestMapping("/test")
    public void test() {
        ServiceInstance serviceInstance = loadBalancerClient.choose("HI-SERVICE");
        int port = serviceInstance.getPort();
        String host = serviceInstance.getHost();
        String serviceId = serviceInstance.getServiceId();
    }

3.自定义ribbon配置
HI-SERVICE.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

11.使用feign实现声明式的调用

使用RestTemplate+ribbon已经可以完成对端的调用,为什么还要使用feign?

   @RequestMapping("/hi")
    public String hi(String name) {
        String restTemplateForObject = restTemplate.getForObject("http://HI-SERVICE/test/test?name=" + name, String.class);
        return restTemplateForObject;
    }

上述代码采用url拼接参数的形式发送请求,如果要发送多个请求参数那么代码就会变得很低效并且难以维护。例如

http://localhost:8989/hi/hi?name=zhangsan&password=123456&age=18

如果使用字符串拼接的方式,那么代码可以编排为:

  @RequestMapping("/hi")
    public String hi(String name, String password, Integer age) {
        Map<Object, Object> map = new HashMap<>();
        map.put("name", name);
        map.put("password", password);
        map.put("age", age);
String restTemplateForObject = restTemplate.getForObject("http://HI-SERVICE/test/test?name={name}&password={password}&age={age}", String.class, map);
        return restTemplateForObject;
    }

在这里url仅仅包含三个参数,如果url为10个参数那么代码会变的更加难以维护。

1.feign简介

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果并且springcloud为feign添加了springmvc注解的支持。

2.为服务消费者整合feign
1.引入feign的相关依赖
	   <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>

2.入口类开启feign支持
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class HiApplication {

    public static void main(String[] args) {

        SpringApplication.run(HiApplication.class, args);
    }

}

3.创建feign接口
@FeignClient(serviceId = "HI-SERVICE")
public interface feignTest {
    @RequestMapping("/test/test")
    public String sayHi(@RequestParam("name") String name);
}

4.测试
@RequestMapping("/hi")
    public String hi(@RequestParam("name") String name) {
        final String s = feignTest.sayHi(name);
        System.out.println(s);
        return s;
    }

3.feign日志

很多的场景下,需要了解feign处理请求的具体细节,如何满足这种需求呢?

feign对日志的处理非常灵活可为每个feign客户端指定日志记录策略,每个客户端都会创建一个logger默认情况下logger的名称是feign的全限定名需要注意的是,feign日志的打印只会DEBUG级别做出响应。

我们可以为feign客户端配置各自的logger.lever对象,告诉feign记录那些日志logger.lever有以下的几种值

  • NONE 不记录任何日志
  • BASIC 仅仅记录请求方法,url,响应状态代码及执行时间
  • HEAdERS 记录Basic级别的基础上,记录请求和响应的header
  • FULL 记录请求和响应的header,body和元数据
1.java配置核心日志类
@Configuration
public class feignConf {
    @Bean
    public Logger.Level feignConfiguration() {
        return Logger.Level.FULL;
    }
}

2.配置feign客户端的日志级别
logging.level.com.baizhi.feign.feignTest=debug

4.feign构造多参数请求
1.错误方式
feign的注意事项
1.多参数传输的时候 必须要在feign接口上进行参数的绑定 
    public String testFeign(@RequestParam("name") String name, @RequestParam("password") String password, @RequestParam("age") Integer age);
2.以对象格式为参数进行数据传输时 必须设置feign的请求形式为post
3.在服务方接收对象参数时需在形参上加入@RequestBody的注解
public interface feignPost {
    @RequestMapping(value = "/test/test1", method = RequestMethod.GET)
    public User sayHi(User user);
}


错误日志信息

feign.FeignException: status 405 reading feignPost#sayHi(User); content:
{"timestamp":1546852876890,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/test/test1"}

由异常信息可知,尽管指定了get的方法,feign依然会使用post发送请求(对象传输时)。正确的方式如下:

2.get
    @RequestMapping("/test/test",method = RequestMethod.GET)
    public String sayHi(@RequestParam("name") String name,@RequestParam("password")String password);


3.post

feign配置

@FeignClient(serviceId = "HI-SERVICE")
public interface feignPost {
    @RequestMapping(value = "/test/test1", method = RequestMethod.POST)
    public User sayHi(User user);
}

服务提供方

  @RequestMapping("/test1")
    public User test1(@RequestBody User user) {
        return user;
    }

12.使用Hystrix实现微服务的容错处理

1.实现容错的手段

如果服务提供者响应的速度特别慢,那么消费者对提供者的请求就会强制等待,直到提供者响应或者超时。在高负载的情况下,如果不做任何处理,此类问题可能会导致服务消费者的资源耗尽甚至整个系统的崩溃。例如曾经发生的一个案例,某个电子商务网站在某个星期五发生过载,过多的并法请求,导致用户支付请求延迟很久没有响应,在等待很长时间后最终失败,支付失败又导致用户重新刷新页面再次尝试支付,进一步增加了服务器的负载,最终整个系统崩溃了。

1.1雪崩效应

我们常把基础服务故障导致级联服务故障的现象称为雪崩效应。雪崩效应描述的是提供方不可用导致消费方不可用并将不可用逐渐放大的过程。

1.2.如何容错

想要避免雪崩效应,必须有强大的容错机制,该容错机制需要实现以下两点

  • 为网络请求设置超时

  • 使用断路器模式

    正常情况下断路器关闭可正常请求服务,当一定时间内请求达到了一定的阈(yu)值(错误率达到百分之50或者100次/分钟),断路器就会打开此时不会再去请求依赖服务,断路器打开一段时间之后,会自动进入半开的状态。此时断路器允许一个请求请求服务实例,如果该服务可以调用成功,则关闭断路器,否则继续保持打开状态。

在这里插入图片描述

2.使用hystrix实现容错

hystrix是Netfilx开源的延迟和容错库,用于隔离访问远程系统,服务或者第三方库,防止级联失败,从而提升系统的可用性和容错性

3.通用方式整合Hystrix
1.为项目添加依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>


2.在消费者的入口类上添加注解
@EnableHystrix
@EnableDiscoveryClient
@SpringBootApplication
public class HiApplication {

    public static void main(String[] args) {

        SpringApplication.run(HiApplication.class, args);
    }


3.让当前方法具备容错的能力
    @Autowired
    LoadBalancerClient loadBalancerClient;
    @HystrixCommand(fallbackMethod = "testFallback")
    @RequestMapping("/hi")
    public User hi(String name) {
        User restTemplateForObject = restTemplate.getForObject("http://HI-SERVICE/test/test?name=" + name, User.class);
        return restTemplateForObject;
    }

 public User testFallback(String name){
        User user=new User();
        user.setName(name);
        user.setAge(-1);
        return user;
    }

4.测试
1.启动eureka服务
2.启动生产者
3.启动消费者
4.访问消费者
结果
{"name":"xiaohei","password":null,"age":null}
5.关闭生产者
6.访问消费者
结果
{"name":"xiaohei","password":null,"age":-1}

我们知道,当请求失败,被拒绝超时或者短路器打开时都会进入到回退方法,但是进入回退方法并不是意味着断路器被打开,那怎样才算断路器打开呢?

5.实验 进行健康监测实时查看断路器是否打开
1.启动eureka服务
2.启动生产者
3.启动消费者
4.访问消费者
结果
{"name":"xiaohei","password":null,"age":null}
5.访问 http://ip:port/health
{
    status:"up",
    hystrix:{
        status:"up"
    }
}
6.关闭生产者
7.访问消费者
结果
{"name":"xiaohei","password":null,"age":-1}
8.访问 http://ip:port/health
{
    status:"up",
    hystrix:{
        status:"up"
    }
}
通过这里我们可以发现,尽管执行了fallback方法,但此时hystrix状态依然是up,这是因为咱们的失败率还没有达到阀值(默认520次失败),这里再次强调,执行回退的逻辑并不代表断路器已经打开,请求超时,失败,被拒绝以及断路器打开都会执行回退逻辑
9.5秒请求20{
    status:"up",
    hystrix:{
        status:"CIRCUIT_OPEN"(断路器打开的标识)
    }
}

4.feign整合Hystrix

很显然@HystrixCommand是添加到方法上的,那么对于feign来说一定不适用,如何让Hystrix整合feign

1.feign方法上添加相关注解
@FeignClient(serviceId = "HI-SERVICE",fallback = FeignClientFallBack.class)
public interface feignPost {
    @RequestMapping(value = "/test/test1", method = RequestMethod.POST)
    public User sayHi(User user);
}

2.实现Feign接口
@Component
public class FeignClientFallBack implements feignPost {
    @Override
    public User sayHi(User user) {
        System.out.println("Hystrix method is invoke");
        return null;
    }
}

3.添加feign的配置文件
为feign开启断路器
feign.hystrix.enabled=true

14.统一配置中心

为什么需要统一配置中心?

统一配置中心顾名思义,就是将配置统一管理,配置统一管理的好处是在日后大规模集群部署服务应用时相同的服务配置一致,日后再修改配置只需要统一修改全部同步,不需要一个一个服务手动维护

统一配置中心的架构图:

在这里插入图片描述

1.配置中心服务器的开发
1.添加依赖
      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>


2.添加注解支持
@EnableEurekaClient
@EnableConfigServer
@SpringBootApplication
public class EurekaApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaApplication.class, args);
	}
}

3.在远程的仓库创建配置文件(yml,properties,yaml)
4.配置相关的配置文件
#注册到注册中心
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
#默认端口号 8888
server.port=8888
# 实例名
spring.application.name=config
#配置git的远程仓库   https 暂时不支持ssh
spring.cloud.config.server.git.uri=https://gitee.com/my_os_do_you_know/springcloud-config.git

5.启动配置中心服务

http://localhost:8888/order-a.yml

http://localhost:8888/order-a.yaml

http://localhost:8888/order-a.properties

http://localhost:8888/order-a.json

以上四种访问方式都可以

在这里插入图片描述

6.服务的配置的访问规则

{name}-{profiles}.yml

{name}/{profiles:.[^-].}

{name}-{profiles}.json

{label}/{name}-{profiles}.yml

{name}/{profiles}/{label:.*}

{label}/{name}-{profiles}.properties

{label}/{name}-{profiles}.json

{name}/{profile}/{label}/**

{name}/{profile}/{label}/**

说明:

label: 分支名称 默认是master分支

name:文件的服务的名称(自定义的名称)

profiles:不同环境

2.创建配置中心客户端
1.导入相关依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>
2.添加配置
#开启配置中心
spring.cloud.config.enabled=true
#找到配置中心实例
spring.cloud.config.discovery.service-id=CONFIG
#指定名字
spring.cloud.config.name=product
#指定环境
spring.cloud.config.profile=1
#指定分支
spring.cloud.config.label=master
#指定配置中心的uri
spring.cloud.config.uri=http://localhost:9999
3.注意将配置文件名修改为 bootstrap.yml

在这里插入图片描述

15.路由网关(zuul)

在微服务架构中,需要多个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能
路由、配置管理等,由这个基础组件相互协作,共同组建了一个简单的微服务系统。一个简单的微服务系统如下

在这里插入图片描述

注意:A服务和B服务是可以相互调用的,并且配置服务也是注册到服务注册中心的。
总结:在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求先先经过负载均衡(Ngnix),再到达服务网关(zuul集群),然后再到具体的服务。服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理,配置服务的配置文件仓库,方便开发人员随时改配置。

1.Zuul 简介

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服
务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能

1.搭建Zull
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
 </dependency>
2.编写Zuul的入口类
 @EnableZuulProxy
 @EnableEurekaClient
 @SpringBootApplication
 public class ServiceZuulApplication {

 public static void main(String[] args) {
 SpringApplication.run(ServiceZuulApplication.class, args);
 }
}
3.编写application.yml
eureka:
	client:
		serviceUrl:
 			defaultZone: http://localhost:8080/eureka/
server:
	port: 8769
spring:
	application:
		name: service-zuul
zuul:
 	routes:
 		api-a:
 			path: /api-a/**
 			serviceId: service-ribbon
 		api-b:
 			path: /api-b/**
			serviceId: service-feign
#关闭安全认证		
management.security.enabled=false
#设置断路时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000			
  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值