深入浅出Spring Boot 2.x

杨开振

前言

  • “微服务”将一个大的系统拆分为多个子系统,然后通过REST风格的请求将它们集成起来,进一步简化了分布式系统的开发。

本书使用的Spring Boot版本

  • Spring Boot 2.x和Spring Boot 1.x在使用上有很多地方存在很多不同,并且只能支持JDK 8或者以上版本

1.1 Spring的历史

  • 而Spring的面向切面的编程(AOP)通过动态代理技术,允许我们按照约定进行配置编程,进而增强了Bean的功能,它擦除了大量重复的代码,如数据库编程所需大量的try...catch...finally...语句以及数据库事务控制代码逻辑,使得开发人员能够更加集中精力于业务开发,而非资源功能性的开发

1.2 注解还是XML

  • 对于业务类使用注解,例如,对于MVC开发,控制器使用@Controller,业务层使用@Service,持久层使用@Repository;而对于一些公用的Bean,例如,对于数据库(如Redis)、第三方资源等则使用XML进行配置
  • Pivotal团队在原有Spring的基础上主要通过注解的方式继续简化了Spring框架的开发,它们基于Spring框架开发了Spring Boot,所以Spring Boot并非是代替Spring框架,而是让Spring框架更加容易得到快速的使用。
  • 随着近年来微服务的流行,越来越多的企业需要快速的开发,而Spring Boot除了以注解为主的开发,还有其他的绑定

1.3 Spring Boot的优点

  • •创建独立的Spring应用程序; •嵌入的Tomcat、Jetty或者Undertow,无须部署WAR文件; •允许通过Maven来根据需要获取starter; •尽可能地自动配置Spring; •提供生产就绪型功能,如指标、健康检查和外部配置; •绝对没有代码生成,对XML没有要求配置。
  • 约定优于配置,这是Spring Boot的主导思想。

2.2 Spring Boot的依赖和自动配置

  • 其中加框的类DispatcherServletAutoConfiguration就是一个对DispatcherServlet进行自动配置的类

2.3 使用自定义配置

  • •命令行参数;•来自java:comp/env的JNDI属性;•Java系统属性(System.getProperties());•操作系统环境变量;•RandomValuePropertySource配置的random.*属性值;•jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件;•jar包内部的application-{profile}.properties或application.ym(带spring.profile)配置文件;•jar包外部的application.properties或application.yml(不带spring.profile)配置文件;•jar包内部的application.properties或application.ym(不带spring.profile)配置文件;•@Configuration注解类上的@PropertySource;•通过SpringApplication.setDefaultProperties指定的默认属性。

2.4 开发自己的Spring Boot项目

  • Spring MVC的视图解析器的作用主要是定位视图,也就是当控制器只是返回一个逻辑名称的时候,是没有办法直接对应找到视图的,这就需要视图解析器进行解析了
  • spring.mvc.view.prefix和spring.mvc.view.suffix是Spring Boot与我们约定的视图前缀和后缀配置
  • @SpringBootApplication标志着这是一个Spring Boot入门文件

第3章 全注解下的Spring IoC

  • Spring最成功的是其提出的理念,而不是技术本身。它所依赖的两个核心理念,一个是控制反转(Inversion of Control,IoC),另一个是面向切面编程(Aspect Oriented Programming,AOP)
  • IoC是一种通过描述来生成或者获取对象的技术
  • Spring还提供了依赖注入的功能,使得我们能够通过描述来管理各个对象之间的关系。
  • IoC容器需要具备两个基本的功能:•通过描述管理Bean,包括发布和获取Bean;•通过描述完成Bean之间的依赖关系。

3.1 IoC容器简介

  • 所有的IoC容器都需要实现接口BeanFactory,它是一个顶级容器接口
  • 在Spring IoC容器中,允许我们按类型或者名称获取Bean
  • 在Spring IoC容器中,默认的情况下,Bean都是以单例存在的,也就是使用getBean方法返回的都是同一个对象。
  • 在现实中我们使用的大部分Spring IoC容器是ApplicationContext接口的实现类
  • 扩展了消息国际化接口(MessageSource)、环境可配置接口(EnvironmentCapable)、应用事件发布接口(ApplicationEventPublisher)和资源模式解析接口(ResourcePatternResolver),所以它的功能会更为强大。
  • 而主要介绍一个基于注解的IoC容器,它就是AnnotationConfigApplicationContext,从名称就可以看出它是一个基于注解的IoC容器。
  • Java简单对象(Plain Ordinary Java Object,POJO)
  • ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
  • 代码中将Java配置文件AppConfig传递给AnnotationConfigApplicationContext的构造方法,这样它就能够读取配置了。

3.2 装配你的Bean

  • 在Spring中允许我们通过XML或者Java配置文件装配Bean
  • 对于扫描装配而言使用的注解是@Component和@ComponentScan。@Component是标明哪个类被扫描进入Spring IoC容器,而@ComponentScan则是标明采用何种策略去扫描装配Bean。
  • 当然你也可以不配置这个字符串,那么IoC容器就会把类名第一个字母作为小写,其他不变作为Bean名称放入到IoC容器中
  • 这里加入了@ComponentScan,意味着它会进行扫描,但是它只会扫描类AppConfig所在的当前包和其子包
  • @ComponentScan还允许我们自定义扫描的包
  • 首先可以通过配置项basePackages定义扫描的包名,在没有定义的情况下,它只会扫描当前包和其子包下的路径
  • @Service(该标准注入了@Component,所以在默认的情况下它会被Spring扫描装配到IoC容器中)
  • 这样,由于加入了excludeFilters的配置,使标注了@Service的类将不被IoC容器扫描注入,这样就可以把UserService类排除到Spring IoC容器中了
  • 它提供的exclude和excludeName两个方法是对于其内部的自动配置类才会生效的
  • 并且很有可能希望把第三方包的类对象也放入到Spring IoC容器中,这时@Bean注解就可以发挥作用了。

3.3 依赖注入

  • 依赖注入(Dependency Injection,DI)
  • @Autowired,这也是我们在Spring中最常用的注解之一,十分重要,它会根据属性的类型(by type)找到对应的Bean进行注入
  • @Autowired提供这样的规则,首先它会根据类型找到对应的Bean,如果对应类型的Bean不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配。如果匹配得上,就会使用该Bean;如果还无法匹配,就会抛出异常。
  • @Quelifier可以满足你的这个愿望。它的配置项value需要一个字符串去定义,它将与@Autowired组合在一起,通过类型和名称一起找到Bean。
  • 使用@Autowired注解对构造方法的参数进行注入

3.4 生命周期

  • IoC容器如何装配和销毁Bean的过程
  • Bean的生命周期的过程,它大致分为Bean定义、Bean的初始化、Bean的生存期和Bean的销毁4个部分
  • ComponentScan中还有一个配置项lazyInit,只可以配置Boolean值,且默认值为false,也就是默认不进行延迟初始化
  • BeanPostProcessor是针对所有Bean而言的
  • Spring Bean的生命周期
  • 有时候Bean的定义可能使用的是第三方的类,此时可以使用注解@Bean来配置自定义初始化和销毁方法,如下所示:

3.5 使用属性文件

  • 有了依赖,就可以直接使用application.properties文件为你工作了
  • @Value注解,使用${......}这样的占位符读取配置在属性文件的内容。
  • 有时候我们也可以使用注解@ConfigurationProperties,通过它使得配置上有所减少
  • @PropertySource去定义对应的属性文件,把它加载到Spring的上下文中
  • value可以配置多个配置文件。使用classpath前缀,意味着去类文件路径下找到属性文件;ignoreResourceNotFound则是是否忽略配置文件找不到的问题。

3.6 条件装配Bean

  • Spring提供了@Conditional注解帮助我们,而它需要配合另外一个接口Condition(org.springframework.context.annotation.Condition)
  • 加入了@Conditional注解,并且配置了类DatabaseConditional,那么这个类就必须实现Condition接口

3.7 Bean的作用域

  • 在一般的容器中,Bean都会存在单例(Singleton)和原型(Prototype)两种作用域

3.8 使用@Profile

  • Spring还提供了Profile机制,使我们可以很方便地实现各个环境之间的切换。
  • 在Spring中存在两个参数可以提供给我们配置,以修改启动Profile机制,一个是spring.profiles.active,另一个是spring.profiles.default。在这两个属性都没有配置的情况下,Spring将不会启动Profile机制,这就意味着被@Profile标注的Bean将不会被Spring装配到IoC容器中。Spring是先判定是否存在spring.profiles.active配置后,再去查找spring.profiles.default配置的,所以spring.profiles.active的优先级要大于spring.profiles.default

3.9 引入XML配置Bean

  • 我们也可以在Spring Boot中使用XML对Bean进行配置。这里需要使用的是注解@ImportResource,通过它可以引入对应的XML文件,用以加载Bean。
  • @ImportResource(value = {"classpath:spring-other.xml"})

3.10 使用Spring EL

  • 通过Spring EL可以拥有更为强大的运算规则来更好地装配Bean。
  • @Value中的${......}代表占位符,它会读取上下文的属性值装配到属性中
  • 采用#{......}代表启用Spring表达式,它将具有运算的功能;T(.....)代表的是引入类
  • 等值比较如果是数字型的可以使用==比较符,如果是字符串型的可以使用eq比较符

4.1 约定编程

  • proceed方法,它会以反射的形式去调用原有的方法。
  • 约定是本节的核心,也是Spring AOP的本质
  • 要求参数target对象存在接口
  • 如果拦截器的useAround方法返回true,则执行拦截器的around方法,而不调用target对象对应的方法,但around方法的参数invocation对象存在一个proceed方法,它可以调用target对象对应的方法;如果useAround方法返回false,则直接调用target对象的事件方法。

4.2 AOP的概念

  • Spring AOP是一种基于方法的AOP,它只能应用于方法上。

4.3 AOP开发详解

  • 当以@Aspect作为注解时,Spring就会知道这是一个切面
  • Spring定义了切点(Pointcut)的概念,切点的作用就是向Spring描述哪些类的哪些方法需要启用AOP编程。
  • 使用了注解@Pointcut来定义切点,它标注在方法pointCut上,则在后面的通知注解中就可以使用方法名称来定义了
  • execution表示在执行的时候,拦截里面的正则匹配的方法
  • @ResponseBody,所以最后Spring MVC会将其转换为JSON响应请求
  • 环绕通知是一个取代原有目标对象方法的通知,当然它也提供了回调原有目标对象方法的能力
  • 是能够得到期待的结果的,但用注解测试的时候总是在顺序上出现这样的出入,估计是Spring版本之间的差异留下的问题,这是在使用时需要注意的。所以在没有必要的时候,应尽量不要使用环绕通知,正如前面说过的,它很强大,但是也很危险
  • @DeclareParents,它的作用是引入新的类来增强服务,它有两个必须配置的属性value和defaultImpl。
  • Spring会把UserService和UserValidator两个接口传递进去,让代理对象下挂到这两个接口下,这样这个代理对象就能够相互转换并且使用它们的方法了
  • 可以看到在JDK动态代理中下挂的两个接口,于是我们可以将这个代理对象通过这两个接口相互转换,然后调度其对应的方法,这就是引入的原理
  • 对于非环绕通知还可以使用一个连接点(JoinPoint)类型的参数,通过它也可以获取参数。
  • 织入是一个生成动态代理对象并且将切面和目标对象方法编织成为约定流程的过程。
  • Spring采用了JDK和CGLIB,对于JDK而言,它是要求被代理的目标对象必须拥有接口,而对于CGLIB则不做要求。因此在默认的情况下,Spring会按照这样的一条规则处理,即当你需要使用AOP的类拥有接口时,它会以JDK动态代理运行,否则以CGLIB运行。

4.4 多个切面

  • Spring提供了一个注解@Order和一个接口Ordered,我们可以使用它们的任意一个指定切面的顺序。
  • 对于前置通知(before)都是从小到大运行的,而对于后置通知和返回通知都是从大到小运行的,这就是一个典型的责任链模式的顺序。

第5章 访问数据库

  • MyBatis是一个不屏蔽SQL且提供动态SQL、接口式编程和简易SQL绑定POJO的半自动化框架

5.1 配置数据源

  • 实现了接口ApplicationContextAware 的方法setApplicationContext(),依照Spring Bean 生命周期的规则,在其初始化的时候该方法就会被调用,从而获取Spring IoC容器的上下文(applicationContext),这时通过getBean方法就可以获取数据库连接池,

5.2 使用JdbcTemplate操作数据库

  • 在配置数据源后,Spring Boot通过其自动配置机制配置好了JdbcTemplate,JdbcTemplate模板是Spring框架提供的
  • 对JdbcTemplate的映射关系是需要开发者自己实现RowMapper的接口的,这样就可以完成数据库数据到POJO(Plain Ordinary Java Object)对象的映射了
  • JdbcTemplate是每调用一次便会生成一个数据库连接
  • 有时候我们希望在一个连接里面执行多条SQL,对此我们也可以使用StatementCallback或者ConnectionCallback接口实现回调

5.3 使用JPA(Hibernate)操作数据

  • JPA(Java Persistence API,Java持久化API),是定义了对象关系映射(ORM)以及实体对象持久化的标准接口
  • 在Spring Boot中JPA是依靠Hibernate才得以实现的
  • @GeneratedValue则是可以配置采用何种策略生成主键
  • @Convert指定了SexConverter作为其转换器
  • 这并不需要提供任何实现类,这些Spring会根据JPA接口规范帮我们完成
  • @EnableJpaRepositories代表启用JPA编程,@EntityScan则是对实体Bean的扫描

5.4 整合MyBatis框架

  • MyBatis的官方定义为:MyBatis是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
  • MyBatis是基于一种SQL到POJO的模型,它需要我们提供SQL、映射关系(XML或者注解,目前以XML为主)和POJO
  • MyBatis的配置文件包括两个大的部分,一是基础配置文件,一个是映射文件。
  • MyBatis是一个基于SqlSessionFactory构建的框架
  • typeHandler的使用集中在枚举类型上
  • 注解@MappedJdbcTypes声明JdbcType为数据库的整型,@MappedTypes声明JavaType为SexEnum,这样MyBatis即可据此对对应的数据类型进行转换了。
  • MapperFactoryBean是针对一个接口配置,而MapperScannerConfigurer则是扫描装配,也就是提供扫描装配MyBatis的接口到Spring IoC容器中
  • MapperScannerConfigurer类来定义扫描了,它可以配置包和注解(或者接口)类型进行装配
  • @MapperScan允许我们通过扫描加载MyBaits的Mapper,如果你的Spring Boot项目中不存在多个SqlSessionFactory(或者SqlSessionTemplate),那么你完全可以不配置sqlSessionFactoryRef(或者sqlSessionTemplateRef)

第6章 聊聊数据库事务处理

  • 在Spring中,数据库事务是通过AOP技术来提供服务的。

6.2 Spring声明式事务的使用

  • 对于声明式事务,是使用@Transactional进行标注的。这个注解可以标注在类或者方法上,当它标注在类上时,代表这个类所有公共(public)非静态的方法都将启用事务功能。
  • 关于注解@Transactional值得注意的是它可以放在接口上,也可以放在实现类上。但是Spring团队推荐放在实现类上,因为放在接口上将使得你的类基于接口的代理时它才生效。
  • 在Spring中,事务管理器的顶层接口为PlatformTransactionManager
  • 这里使用@Alias注解定义了它的别名,这样就可以让MyBatis扫描到其上下文中,

6.3 隔离级别

  • Spring事务机制中最重要的两个配置项,即隔离级别和传播行为。
  • 数据库事务具有以下4个基本特征,也就是著名的ACID。
  • 对于这样一个事务回滚另外一个事务提交而引发的数据不一致的情况,我们称为第一类丢失更新
  • 多个事务都提交引发的丢失更新称为第二类丢失更新
  • 这4类隔离级别是未提交读、读写提交、可重复读和串行化
  • 为了克服脏读的问题,数据库隔离级别还提供了读写提交(read commited)的级别
  • 读写提交(read committed)隔离级别,是指一个事务只能读取另外一个事务已经提交的数据,不能读取未提交的数据。
  • 可重复读的目标是克服读写提交中出现的不可重复读的现象,因为在读写提交的时候,可能出现一些值的变化,影响当前事务的执行
  • 串行化(Serializable)是数据库最高的隔离级别,它会要求所有的SQL都会按照顺序执行
  • 在现实中一般而言,选择隔离级别会以读写提交为主,它能够防止脏读,而不能避免不可重复读和幻读。
  • Oracle只能支持读写提交和串行化,而MySQL则能够支持4种,对于Oracle默认的隔离级别为读写提交,MySQL则是可重复读

6.4 传播行为

  • 传播行为是方法之间调用事务采取的策略问题
  • 在Spring中,当一个方法调用另外一个方法时,可以让事务采取不同的策略工作,如新建事务或者挂起当前事务等,这便是事务的传播行为。
  • NESTED传播行为和REQUIRES_NEW还是有区别的。NESTED传播行为会沿用当前事务的隔离级别和锁等特性,而REQUIRES_NEW则可以拥有自己独立的隔离级别和锁等特性,这是在应用中需要注意的地方。

6.5 @Transactional自调用失效问题

  • 这是一个类自身方法之间的调用,我们称之为自调用
  • 我们谈过Spring数据库事务的约定,其实现原理是AOP,而AOP的原理是动态代理,在自调用的过程中,是类自身的调用,而不是代理对象去调用,那么就不会产生AOP,这样Spring就不能把你的代码织入到约定的流程中,于是就产生了现在看到的失败场景

第7章 使用性能利器——Redis

  • Redis是一个开源、使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、键值数据库,并提供多种语言的API。
  • Redis是一种键值数据库,而且是以字符串类型为中心的

7.1 spring-data-redis项目简介

  • 在Java中与Redis连接的驱动存在很多种,目前比较广泛使用的是Jedis
  • RedisTemplate是一个强大的类,首先它会自动从RedisConnectionFactory工厂中获取连接,然后执行对应的Redis命令,在最后还会关闭Redis的连接。
  • Redis是一种基于字符串存储的NoSQL,而Java是基于对象的语言,对象是无法存储到Redis中的,不过Java提供了序列化机制,只要类实现了java.io.Serializable接口,就代表类的对象能够进行序列化,通过将类对象进行序列化就能够得到二进制字符串,这样Redis就可以将这些类对象以字符串进行存储
  • JdkSerializationRedisSerializer是RedisTemplate默认的序列化器
  • SessionCallback提供了良好的封装,对于开发者比较友好,因此在实际的开发中应该优先选择使用它

7.2 在Spring Boot中配置和使用Redis

  • 如果需要多次执行Redis命令,可以选择使用SessionCallback或者RedisCallback接口
  • 为了克服这个问题,这里使用StringRedisTemplate对象保存了一个键为“int”的整数,这样就能够运算了。

7.3 Redis的一些特殊用法

  • 对于Redis也是可以的,这便是流水线(pipline)技术,在很多情况下并不是Redis性能不佳,而是网络传输的速度造成瓶颈,使用流水线后就可以大幅度地在需要执行很多命令时提升Redis的性能
  • 与事务一样,使用流水线的过程中,所有的命令也只是进入队列而没有执行,所以执行的命令返回值也为空,这也是需要注意的地方。

第8章 文档数据库——MongoDB

  • MongoDB 是由C++语言编写的一种NoSQL,是一个基于分布式文件存储的开源数据库系统。

8.3 使用JPA

  • 在Spring中只要定义一个“接口名称+Impl”的类并且提供与接口定义相同的方法,Spring就会自动找到这个类对应的方法作为JPA接口定义的实现

第9章 初识Spring MVC

  • Spring MVC一开始就定位于一个较为松散的组合,展示给用户的视图(View)、控制器返回的数据模型(Model)、定位视图的视图解析器(ViewResolver)和处理适配器(HandlerAdapter)等内容都是独立的。

9.2 Spring MVC流程

  • 流程和组件是Spring MVC的核心,Spring MVC的流程是围绕DispatcherServlet而工作的,所以在Spring MVC中DispatcherServlet就是其最重要的内容

10.2 获取控制器参数

  • 唯一的要求是参数名称和HTTP请求的参数名称保持一致
  • Spring MVC提供了注解@RequestParam来确定前后端参数名称的映射关系
  • 默认的情况下@RequestParam标注的参数是不能为空的,为了让它能够为空,可以配置其属性required为false
  • 可以看到需要传递数组参数时,每个参数的数组元素只需要通过逗号分隔即可
  • 这个方法的参数标注为@RequestBody,意味着它将接收前端提交的JSON请求体
  • 在Spring Boot中,日期参数的格式化也可以不使用@DateTimeFormat,而只在配置文件application.properties中加入如下配置项即可:

10.3 自定义参数转换规则

  • 在Spring MVC中,是通过WebDataBinder机制来获取参数的,它的主要作用是解析HTTP请求的上下文,然后在控制器的调用之前转换参数并且提供验证的功能,为调用控制器方法做准备
  • GenericConverter转换器则将HTTP参数转换为数组

10.4 数据验证

  • 在默认的情况下Spring Boot会引入关于Hibernate Validator机制来支持JSR-303验证规范
  • JSR-303验证主要是通过注解的方式进行的
  • @Valid注解则表示启动验证机制,这样Spring就会启用JSR-303验证机制进行验证。
  • 在WebDataBinder中除了可以注册转换器外,还允许注册验证器(Validator)

10.5 数据模型

  • 数据模型的作用是绑定数据,为后面的视图渲染做准备
  • 如果在控制器方法的参数中使用ModelAndView、Model或者ModelMap作为参数类型,Spring MVC会自动创建数据模型对象

10.6 视图和视图解析器

  • 逻辑视图是需要视图解析器(ViewResolver)进行进一步定位的
  • 对于非逻辑视图,则并不需要进一步地定位视图的位置,它只需要直接将数据模型渲染出来即可
  • 对于视图,除了JSON和JSP视图之外,还有其他类型的视图,如Excel、PDF等

10.8 拦截器

  • 首先所有的拦截器都需要实现HandlerInterceptor接口

10.9 国际化

  • messages.propertiess是默认的国际化文件,如果没有这个文件,则Spring MVC将不再启用国际化的消息机制
  • SessionLocaleResolver:类似于CookieLocaleResolver,只是将国际化信息设置在Session中,这样就能读取Session中的信息去确定用户的国际化区域。这也是最常用的让用户选择国际化的手段。

11.1 REST简述

  • PUT(UPDATE):修改服务器已经存在的资源,使用PUT时需要把资源的所有属性一并提交。
  • 一般不应该在URI中存在动词

11.2 使用Spring MVC开发REST风格端点

  • @RestController让整个控制器都默认转换为JSON数据集
  • Spring MVC在支持REST风格中还存在一个注解@RestController,通过它可以将控制器返回的对象转化为JSON数据集
  • 这里采用了@RestController定义,这样对于getUser 返回的对象就会转变为JSON数据集了。
  • Spring提供了实体封装类ResponseEntity和注解@ResponseStatus。ResponseEntity可以有效封装错误消息和状态码,通过@ResponseStatus可以配置指定的响应码给客户端。

11.3 客户端请求RestTemplate

  • RestTemplate的底层是通过类HttpURLConnection实现的

12.1 概述和简单安全认证

  • 在Java Web工程中,一般使用Servlet过滤器(Filter)对请求进行拦截,然后在Filter中通过自己的验证逻辑来决定是否放行请求
  • 在传统的Spring全注解的方式下,只需要加入@EnableWebSecurity就可以驱动Spring Sercurity了
  • 一旦启用了Spring Security,Spring IoC容器就会为你创建一个名称为springSecurityFilterChain的Spring Bean。它的类型为FilterChainProxy,事实上它也实现了Filter接口,只是它是一个特殊的拦截器

12.2 使用WebSecurityConfigurerAdapter自定义

  • 对于HttpSecurity参数的方法,则是指定用户和角色与对应URL的访问权限,也就是开发者可以通过覆盖这个方法来指定用户或者角色的访问权限

13.1 异步线程池

  • Spring还提供一个注解@EnableAsync,如果Java配置文件标注它,那么Spring就会开启异步可用,这样就可以使用注解@Async驱动Spring使用异步调用

13.2 异步消息

  • 在实际工作中实现JMS服务的规范有很多,其中比较常用的有传统的ActiveMQ和分布式的Kafka。

第14章 Spring 5新框架——WebFlux

  • Spring 5发布了新一代响应式的Web框架,那便是Spring WebFlux。

14.1 基础概念

  • Reactor是一种基于事件的模型,对于服务器线程而言,它也是一种异步的,首先是Selector线程轮询到事件,然后通过路由找到处理器去运行对应的逻辑,处理器最后所返回的结果会转换为数据流。

15.2 高并发开发

  • 为了克服超发的现象,当前企业级的开发提出了乐观锁、悲观锁和使用Redis等多种方案
  • 乐观锁是一种不使用数据库锁和不阻塞线程并发的方案。

16.2 测试

  • Mock测试是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

第17章 分布式开发——Spring Cloud

  • Spring Cloud是一套组件,可以细分为多种组件,如服务发现、配置中心、消息总线、负载均衡、断路器和数据监控等。
  • Spring Cloud为此提供了Ribbon来实现这些功能
  • Spring Cloud提供了接口式的声明服务调用编程,它就是Feign
  • 在Spring Cloud中API网关是Zuul。对于网关而言,存在两个作用:第一个作用是将请求的地址映射为真实服务器的地址
  • Zuul网关的第二个作用是过滤服务,在互联网中,服务器可能面临各种攻击,Zuul提供了过滤器,通过它过滤那些恶意或者无效的请求,把它们排除在服务网站之外,这样就可以降低网站服务的风险。