视图解析器:主要作用就是定位视图,也就是当控制器只是返回一个逻辑名称的时候,是没有办法直接找到视图的,这就需要视图解析器进行解析了。
在SpringBoot中使用JSP,SpringBoot默认使用thymeleaf
引入依赖
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>9.0.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
配置application.yml
spring:
mvc:
view:
prefix: /WEB-INF/JSP/
suffix: .jsp
控制器
@org.springframework.stereotype.Controller
public class Controller {
@GetMapping("/index")
public String Index(){
return "index";
}
}
IOC容器需要具备两个基本功能
1、通过描述管理Bean,包括发布和获取Bean。
2、通过描述完成Bean直接的依赖。
Bean的获取方式有按照类型获取的,也有按照名称获取的
@Component:只能扫描一个组件
@ComponentScan:扫描当前包或者包下的,或者指定其他的包。includeFilters满足条件的,excludeFilters不满足条件的
@Primary :当出现多个相同的类型,可以为其中一个类型加上这个注解作为优先
@Autowired:除了注入变量,也可以用在构造器的参数中,形成有参构造器。
Bean的生命周期
Bean的定义:Spring通过配置解析,完成资源定位,保存Bean的定义,最后把定义发布给Spring容器
在ComponentScan中有个属性lazyInit,用于延迟初始化,只有使用时才初始化
Bean初始化
Bean的生存周期
Bean的销毁
@Bean:可以定义initMethod 初始化方法,destroyMethod销毁方法
属性文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
使用application中的值引用到变量上
@Value("$(database.driverName)")
@PropertySource为了不使application中的属性太多,可以使用这个注解添加properties配置到IOC容器中
@PropertySource(value = {"classpath:jdbc.properties"}, ignoreResourceNotFound = true)
@Conditional(xxx.class)xxx必须实现@Condtional接口中的mathes,用于指定必须配置的属性
使用
@Scope指定作用域默认单例
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)//多例
//
@Scope(WebApplicationContext.SCOPE_REQUEST)//请求
//
@Scope(WebApplicationContext.SCOPE_SESSION)//会话
//
@Scope(WebApplicationContext.SCOPE_APPLICATION)//应用
@Profile("dev")用于指定不同的环境
需要在配置文件中配置启动
spring:
profiles:
active: dev
文件名 application-dev.properties
@ImportResource引入XML配置文件
#{...}配置Spring EL,作用 赋值字符串,科学计数法,浮点数,使用Bean的属性
使用Bean的属性
AOP流程
代码实现InvocationHandler接口中的invoke()
AOP编程 的本质是约定
连接点(join point):对应的是被拦截的对象,因为Spring只支持方法,所以被拦截的对象都是一个方法。
切点(point cut):切面不是一个方法,多个类的不同方法,可以通过表达式去定义连接点,这就是切点的概念
通知(advice):按照约定的流程方法,分为前置通知(before advice),后置通知 (after advice),环绕通知(around advice),事后返回通知(afterReturning advice),异常通知(afterThrowing advice)
目标对象(target):是指被代理的对象
引入(introducting):是指引入新的类和方法,增强现有Bean
织入(weaving):只是通过动态代理技术,为原生的对象生成动态代理,按照约定织入连接点的增强方法
切面(aspect):是一个可以定义切点,各类通知和引入内容,AOP通过他的功能来进行增强
after方法一定会执行,无论抛不抛出异常
例子
引入功能,是指在无法改变一个类的基础上,增加方法对他进行代理
//
@Order确定执行切面的顺序
访问数据库
mybatis
mybatis配置
@Transactional用在类上是代表所有共有非静态都将启用这个功能
事务管理器
隔离级别。因为在互联网中时刻出现高并发环境,时刻都是多线程共享数据,这样就会在多线程环境中扣除商品。这就容易出现丢失更新。
@PostContruct:作用在这个类初始化后,调用这个方法
Atomic(原子性):事务中包含一个整体单元,要么整体失败,要么成功。
Consistency(隔离性):事务完成时,所有数据必须保持一致,完整
Isolation(隔离性):为了压制隔离更新。数据库定义了隔离级别的概念,通过他的选择可以在不同程度上压制隔离更新。
Durability(持久性):事务结束后,所有数据会固话到某一个地方
四类隔离级别:
未提交读:允许一个事务读取另一个事务没有提交的数据,容易导致脏读
读写提交:一个事务只能读取另一个事务已经提交的事务数据,出现问题一个数据会对事务是个可变数据,比如之前可以提交但在提交这个事务之前,就有另一个事务提交了,不可重复读错误
可重复读:一个事务必须等待另一个事务的完成,容易出现幻读,查询和结果不一致
串行化:是所有数据库最高的级别,他会要求所有的SQL都按照顺序执行,这样就能保证数据的一致性和完整性
Oracle:支持读写提交和串行化,默认读写提交
MySql:支持四种,默认可重复读
传播行为是方法之间调用事务采取的策略问题
Spring事务机制对数据库存在7种传播行为
需要事务:他是默认传播行为,如果当前存在事务,就沿用当前事务,否则新建一个事务运行子方法,REQURED
支持事务:如果当前存在事务,就沿用当前事务,如果不存在就继续采用无事务的方式运行子方法,SUPPORTS
必须使用事务:必须使用事务,如果当前没有事务,则会抛出异常,如果当前存在事务就会沿用当前事务,MANDATORY
REQUIRES_NEW:无论当前是否存在,都回创建新事务的运行方法,这样新事务就具有了新的锁和隔离级别的特性,与当前事务相互独立
NO_SUPPORTED:不支持事务,如果当前方法存在事务,就将事务挂起,运行方法
NEVER:不支持事务,如果当前方法存在就抛出异常,否则继续使用无事务机制运行
NESTED:当前方法调用子方法,如果子方法发生异常,只回滚子方法执行的SQL,而不会滚当前方法的事务
自调用会导致事务失效,原因事务的实现是AOP动态代理的,而在自调用的过程中是类自身的调用,而不是代理对象的调用,这样就不会产生AOP,这样就不能按照约定吧你的代码织入到约定的流程中
可以使用这种方式
第七章Redis——性能利器
NOSQL在互联网中起到加速的作用,有两种最为广泛Redis和MongoDB
SpringBoot默认使用Lettuce的客户端驱动。而在一般的项目中我们会使用Jedis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
Spring支持其中数据类型的操作
常用SessionCallback,RedisCallback接口接近底层
在SpringBoot中使用Redis
使用Jedis可以获取RedisTemple的所有Redis命令
对于集合Redis中是不允许出现重复的,对于两个集合,Redis还提供了交集,并集和差集的运算
Redis支持事务
Redis在默认情况下是使用一条条命令发送给Redis客户端的,对于Redis中可以使用流水线技术,注意在使用事物或者流水线技术的时候,命令也只是进入了队列而没有执行
消息发布订阅模式
使用Lua脚本
Redis运行Lua有两种方法
1、直接把Lua发送给Redis
2、先把Lua发送给Redis,Redis会对Lua脚本进行缓存,然后再返回一个SHA1的32位编码回来,之后只需要将发送的32位SHA1编码和相关参数发送给Redis就行了,这个方法是为了解决网络的瓶颈,从而提高Redis 的性能
MongoDB对于需要提供统计,按条件查询和分析的数据,它提供了支持
依赖
@Document说明作为MongoDB文档的存在
@id作为主键存在
@Field将变量作为列表值
@DBRef只会保存引用信息而不是角色信息
MongoTemple操作Mongo文档对象
Spring MVC
使用@RequestMapping
返回JSON数据
在Spring MVC3.1支持不通过web.xml配置运行环境了,而是通过WebMvcConfigurer这是基于java8的接口,但很多都是空方法需要开发者实现这个类,他有一个静态的内部类WebMvcConfigurationAdapter,通过它Spring Boot就配置了Spring MVC的初始化
HandlerMapping主要任务就是请求定位到具体的处理器上
@RequestParam解决前后端数据参数映射不一致的问题
@PathVariable通过URL传递参数
@DateTimeFormat针对日期进行格式化
@NumberFormat针对数字进行格式化
HttpMessageConverter作用将将请求体中的信息进行转换成java对象
处理器转换参数是通过WebDataBinder,主要作用就是解析HTTP上下问,然后在控制器调用之前转换参数和验证,为待用控制器做准备。
Converter(一个普通的转换器,如将字符串转化为Integer),Formatter(一种格式化转换器,将字符串按照约定格式转化为日期),和GernericConverter(就是将HTTP参数转化为数组)这三种接口的实现类都采用注册机的机制。
对于数据类型转换。SpringMVC提供了一个服务机制去管理,他就是ConversionSerivce接口,默认情况下会使用DefaultFormattingConversionSerivce来管理这些转换类
使用Converter
Spring Boot中还提供了特殊的机制来管理这些转换器,WebMvcAutoConfiguration还定义了一个内部类WebAutoConfigurationAdapter
数据验证
JSR-303验证
@InitBinder这个注解的作用是允许在进入控制器的方法修改WebDataBinder机制
在ModelAndView中存在ModelMap类型属性,ModelMap继承LinkedHashMap类。在Spring MVC中,如果控制器方法参数是ModelAndView、Model或者ModelMap作为参数,Springl MVC会自动创建模型对象。
视图有两种,逻辑视图是需要试图解析器的定位的,才能将数据模型进行数据渲染,而对于非逻辑视图不需要,他只需要将数据模型直接渲染出来就行了
各种控制器都有不同的导出逻辑,为了适应不同的控制器的自定义导出,可以先定义导出接口
文件上传
可以使用MultiHttpServletRequest(由HttpServeltRequest强转),MultipartFile对象,也可以使用Servlet的API Part类来实现write写入文件
拦截器,基于java的反射机制
所有的拦截器都需要实现HandlerInterceptor接口
实现了HandlerInterceptor接口注册到Web中
国际资源化
对于国际化。Spring Boot提供了国际化消息机制,那就是MessageSource接口体系,它的作用是装载国际化消息
在绝大部分的情况下是使用JDK的ResourceBundle处理国际化信息的,这里主要是ResourceBundleMessageSource
message.properties是默认的国际化文件
对于国际化还需要用户确定是那个国际区域,SpringBoot也提供了LocalResolver的接口来确定用户的国际化接口
实现类有
AcceptHeaderLocalResolver:使用浏览器的请求信息去实现国际化区域,这是SpringBoot默认的国际化解析器,因为这个符合大部分计算机用户的选择
FixedLocalResolver:固定的国际化解析器,只能选择一种变化不大
CookieLocalResolver:将国际化区域设置在Cookie中,这样可以使得系统可以从浏览器中读取国际化信息来确定用户的国际化区域,如果用户禁止使用Cookie,则会使用默认的国际化信息解析器
SessionLocalResolver:类似于CookieLocalResolver,将国际化信息存在Session中,这样就能读取Session中的信息确定国际化的区域,也是最常用的让用户选择国际化的手段。
使用SessionLocalResolver 国际化
在SpringMVC中需要使用一个拦截器LocalChangeInterceptor,可以在处理器前处理相关信息
@ResponseBody转换JSON的方式,处理器会记录下这个方法的响应类型为JSON数据集,当控制器处理完后就会使用结果解析器来解析这个结果,她回去轮询注册给Spring MVC的HttpMessageConverter接口的实现类,因为MappingJackson2HttpMessageConverter实现类被Spring MVC注册了,再加上控制器的结果类型为JSON,所以就匹配上了,于是就在处理器内部把结果替换上。
重定向就是通过各种方法将各种网络请求重新定个方向转到其他位置。
RedirectAttribute扩展了addFlashAttribute,这个方法可以保存重定向需要的数据
操作会话对象,@SessionAttribute(应用于参数,他的作用是将HttpSession中的属性读出来,赋予控制器的参数)和@SessionAttributes(只能作用于类的注解,他会将相关的数据模型保存到Session中)
给控制器增加通知
@ControllerAdvice:定义一个控制器的通知类,允许定义一些关于增强控制器的各类通知和限定增强哪些控制器功能等。
@InitBinder:定义控制器参数绑定规则,格式化等,他会在参数转换之前进行。
@ExceptionHandler:定义控制器发生异常后的操作。
@ModelAttribute:可以在控制器方法执行之前,对数据模型进行操作。
@RequestHeader获取请求头的参数
在HTTP协议在发展中提出了很多的规则。但这些规则有些繁琐,于是又提出一种风格约定,他就是REST(Representational State Transfer)风格。严格的意义上来讲他不是一种标准,而是一种风格。
资源:它可以是系统权限用户、角色和菜单等、也可以是一些媒体类型,总之他是一个具体存在的对象。每个资源都应该有独一无二的URL,在REST中,URI也被称为端点(End Point)
表现层:有了资源还需要确定如何表现这个资源。
状态转换:现实中的资源不是一层不变的,他是一个变化的过程,一个资源可以经历创建,访问,修改和删除。
特点:
服务器上存在一系列资源,每个资源都是通过唯一的URL进行标识的
客户端和服务端之间可以相互传递资源,而资源会以某种表现层得以展示
客户端通过HTTP协议所定义的动作对资源进行操作,以实现资源的转换
REST风格是对应HTTP的行为去操作资源的
GET(VISIT):访问服务器资源
POST(CREATE):提交服务器资源,用于创建新的资源
PUT(UPDATE):修改服务器已经存在的资源
PATCH(UPDATE):不常使用这个,只需要修改部分的资源属性
DELETE(DELETE):从服务器删除资源
HEAD:获取资源的元数据
OPTIONS:提供资源可供客户端修改属性信息
误区
在URL中不应该出现动词
在URL不因该出现版本,如果需要版本也应该在HTTP请求头中
处理HTTP状态码,异常和响应头
ResponseEntity可以有效的封装错误和消息码
@ResponseStatus可以配置指定的响应吗给客户端
RestTemple:在当今的微服务中,会将大系统被拆分成很多微服务,每个微服务系统都会暴露REST风格的URL请求给别的微服务系统所调用,为了方便系统之间的调用,Spring给予了模板RestTemple,底层是基于HttpURLConnection实现的。在实际中服务器只会调用JSON给我们。不过RestTemple会转换为java对象。
Spring Security
基本原理:一旦启用了Spring Security ,Spring IOC容器就会为你创建一个名称为SpringSecurityFilterChain的Spring Bean。他的类型为FilterChainProxy,事实上他也实现了Filter接口,是个特殊的拦截器。在Spring Security的操作中她会提供Servlet过滤器DelegatingProxy,这个过滤器会去获得Spring Security创建的FilterChainProxy,这个FilterChainProxy上有个列表,就有是否拦截那些请求的功能。
application.properties配置
这个方法是用来配置用户信息的
自定义用户签名服务包含内存签名服务、数据库签名服务和自定义签名服务。
关于限定请求权限是通过下列方法实现的
内存签名使用用户
JdbcUserDetailsManagerConfigurer是一个Spring Security对数据库配置支持,并且他也默认是SQL
Spring Security提供了一个UserDetailsService接口,通过它可以获取用户的信息
限制权限
在WebSecurityConfigurerAdapter中configure(HttpSecurity)通过它就能对不同角色赋予不同权限了
强制使用HTTPS加密
跨站点请求伪造(Cross-Site Request Forgery)
开启SCRF过滤器验证,每次提交HTTP表单时都要求存在CSRF参数
Http Basic认证:是一个浏览器自动弹出简单的模拟对话框的功能
登出可以使用POST请求/logout
JMS(Java Message Service)两种规范
点对点就是将一个系统的消息发布到指定的另一个系统,这样另一个系统就能收到消息
发布订阅模式是一个系统约定将消息发布到一个主题中,然后各种系统就能够通过订阅这个主题,根据发送过来的消息处理对应的业务。
JMS服务的规范有很多,常用传统的就是ActiveMQ和分布式的Kafka。为了安全可靠,还存在AMQP(Advanced Message Queuing Protocol),实现它比较常用的有RabbitMQ
ActiveMQ
配置
消息的发送和接受可以通过@JmsListener作用的JmsTemple(JmsTemple会提供一个SimpleMessageConverter去提供转换规则。它实现MessageConverter,如果要使用其他转换接口,如SerializerMessageConverter或者Jackson2JsonMessageConverter的情况下,只需要使用setMessageConverter方法)模板去处理
在配置自定义发送的信息对象需要保证ActiveMQ信任我们创建的信息类比如User类,需要配置文件中添加
使用AMQP-RabbitMQ
配置信息
实现类可以回调方法查看消费者是否成功收到消息
通过监听器监听发送消息
定时任务
在配置文件中加入@EnableScheduling,然后再通过@Scheduled进行配置
WebSocket协议
基于TCP的一种新的网络协议,它实现了浏览器和服务器全双工通信——允许服务器主动发消息给客户端,从而实现从客户端直接发消息给服务器,而服务器又可以转发消息给客户端
@ServerEndpoint("/xxx"):表示让Spring创建WebSocket的服务端点,其中请求地址是“/xxx”
@OnOpen:标注客户端打开WebSocket服务端点的调用方法
@OnClose:标注客户端关闭WebSocket端点的调用方法
@OnMessage:标注客户端发送消息,WebSocket服务端点调用的方法
@OnError:标注客户端请求服务器发生异常的调用方法
使用STOMP
需要在配置类加入@EnableWebSocketMessageBroker这个注解会启动WebSocket下的子协议STOMP,配置这个协议可以实现Spring的WebSocketMessageBrokerConfigurer。为了方便开发者操作还是用了AbstractWebScoketMessageBrokerConfigurer
WebFlux
对于游戏,视频和新闻广告,他们一般不会涉及财产安全,也就是不需要很高的一致性,但对于并发性和响应数据却十分在意,而传统的开发模式会引入一致性的机制,这是造成他们瓶颈的原因之一,为此一些软件设计者提出了响应式编程概念。
对于响应式框架,是基于响应式宣言的理念所产生的编程方式,分为四大理念
灵敏的:就是可以快速响应的,只要有任何可能,系统就应该能够尽可能的做出响应。
可恢复的:系统在运行中出现问题,但是能够有很强大的容错机制和修复机制性保持响应性。
可伸缩性:在任何负载下,响应式编程就可以根据自身压力变化。请求减少时,通过减少资源,释放服务器的压力。负载大时能够通过扩展算法和软硬件的方式扩展服务功能,以经济实惠的方式实现可伸缩性。
消息驱动:响应式编程存在异步消息机制,事件之间的协作是通过消息进行连接的。
基于这样的概念满足要求的有Reactor和RxJava,默认使用Reactor
传统的
现在的
Selector只是一个轮询的线程,所以可以对请求做实时响应,速度很快。而客户端必须先要注册感兴趣的事件,这时并不会触发,只有客户端发生了一些注册事件时才会触发。selector就会为这个请求找到对应的请求处理器,然后分配一个线程处理这个请求。所以selector就属于路由,不过这就存在一个问题就是需要如何区别事件类型。以及将数据流发送到客户端上,对数据流的一些细节处理问题,这就涉及到了背压(Back Pressure)。
对于响应式编程分为三层
Router Functions:是一个路由转发层,也就是他会根据请求的事件,决定采用什么类的什么方式处理客户端发送过来的事件请求。所以他就是selector的作用
Spring-webflux:是一种控制层,类似于Spring MVC的层级封装,他主要处理业务的逻辑前进的封装和控制数据流的返回格式等。
HTTP/Reactive Streams:是将结果转换为数据流的过程。
在Spring WebFux中存在两种开发方式,一种是类似于Spring MVC的模式,另一种则是函数功能性的编程,建议使用Spring MVC 的模式。
Reactor提供Flux和Mono了他们都是封装数据流的类。Flux是存放0N个数据流序列,响应式会一个接一个把他们发送到客户端,而Mono是存放01一个数据量序列,他们之间可以相互转换。这里还有一个背压(Backpressure)的概念,这个概念只对Flux有意义。
如果在短时间内将大量数据传输给客户端,那么客户端就有可能被拉垮,为了处理这个问题一般就会使用拉取式,也就是将服务端的数据划分为多个序列,一次仅发送一个数据流给客户端,当客户端处理完了这个序列化后,再向服务端发送消息,这样获取第二个序列化进行处理,直至数据流完全处理。
DispatcherHandler是关注的核心
WebHandlerDecorator则是一个装饰类,采用装饰方式作用于WebHandler
ResourceWebHandler则是系统资源管理器
Spring WebFlux只能支持Spring Data Reactive这是一种非阻塞的数据响应方式。而数据库开发往往都是阻塞的,所以Spring Data Reactive 是不适用数据库的,支持NOSQL也就是Redis和MongoDB开发
依赖
这个开发模式可Spring MVC相似
只不过使用的是非关系型数据库所以需要排除掉@EnableAutoConfiguration初始化
为了使微服务之间方便调用,Spring WebFlux 还提供了WebClient类给予开发者使用,他是一个比RestTemple更为强大的类,方便请求后端的服务
类型转换器(客户端发送给服务端的数据进行类型转换再处理)
实现接口WebFluxConfigurer,addFormatters(FormatterRegister register)将定义的Converter注册到register中,或者将转换器定义个Bean,让容器扫描注入
关于日期格式化,WebFlux允许我们通过application.properties进行配置
验证器——Validator
注意验证器只能有一个,而不是多个,且这个验证器具有全局性。将他配置到配置类中
也可以使用局部验证器
并且要在控制器的方法上启用验证器
访问静态资源时可以在WebFluxConfigurer的addResourceHandlers方法中设置静态资源通过Url访问或者,在Spring的上下文机制中设置访问路径
为了将静态资源和动态资源分开可以在application.properties中设置
客户端
客户端错误处理机制,通过判断响应头中是否是4xx或者5xx来判断服务器错误,然后进行处理
当服务器发送给客户端的对象,并不是客户端需要的对象时可以使用转换机制,直接将接受的数据转换成需要的对象
通过请求头中获得数据
客户但需要设置
服务端直接通过请求头获得数据
使用路由函数方式开发WebFlux
开发路由函数方式,首先需要开发一个处理器(Handler)用来处理各种场景,这个处理器就类似于service
上面开发了用户处理器,然而将请求映射到处理器还需要一个路由器的功能
java中::的使用:this::fuction不可以用静态方法,Object::fuction是使用静态方法的
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class Test {
public static void printValur(String str) {
System.out.println("print value : " + str);
}
public static void main(String[] args) {
List<String> al = Arrays.asList("a", "b", "c", "d");
al.forEach(Test::printValur);
// 下面的方法和上面等价的
Consumer<String> methodParam = Test::printValur; // 方法参数
al.forEach(x -> methodParam.accept(x));// 方法执行accept
}
}
过滤器,是用过滤器验证身份,以免被网站攻击。验证身份后才能处理逻辑业务,例如在请求头上存放用户名和密码服务。
为了解决超并发,现代企业提出了悲观锁,乐观锁和使用Redis等多种方案。
超并发的出现问题在于共享数据被多个线程调用,无法保证其执行顺序。
使用这种方式表示会在事务的执行中锁定查询出来的数据,其他事务不能对其进行读写,这就避免了数据的不一致性。只有单个事务完成之后,才会释放这个锁。但这种方式会严重影响性能。
乐观锁是一种不使用数据库和不阻塞线程并发的一种方案。他会先查询数据库保存一个旧值,然后当要执行一定的业务逻辑时,会对比保存出来的旧值和查询出来的新值是否一致,如果一致就执行,如果不一直就说明数据不值得被信赖。
然后他也会出现这种问题
解决方式使用版本号
在使用乐观锁时,性能不会丢失,也不会发生超发。因为没有独占资源和阻塞任何线程的并发,所以乐观锁也称为非独占锁或者无阻塞锁,但是因为加入了版本号的原因,所以请求失败的概率就很高。
为了解决这个问题,乐观锁还引入了重置机制。原理就是一旦发现版本号被更新,不是结束请求,而是重新做一次乐观锁的流程,直到成功为止。但这种方式就会给数据库带来很大的压力,为了克制这个问题一般都会设置重置次数。
重置时间戳
一旦大于100ms就终止,这个的问题就是,系统会因为自身的忙碌而大大减少重入的次数
使用次数作为结束
部署,测试和监控
为了解决在测试时占用应用的端口号,所以在测试@SpringTest的配置项webEnvironment为随机端口启动。
Mock测试是指在测试过程中,对某些不容易构建或者不易获取的对象,用一种虚拟的对象来创建以便测试的测试方法。
Actuator监控点
Spring Cloud
基础技术:服务治理和服务发现,客户端负载均衡,声明调用(接口式的声明服务调用编程),断路器(如果服务消费者大量调用网络延迟或者故障的服务提供者,那么很快消费者会因为大量的等待,和积压导致自身服务出现瘫痪,可以使用Netflix的开源框架Hystrix来处理这些问题),API网关(1、将请求映射为真实的服务器地址,起到路由转发的功能,降低单个节点的负载。2、过滤服务,将恶意请求或者无效请求排除在服务网站之外)
配置服务治理节点,使用NetFlix的Eureka,他是最核心也是最基础的两个模块
启动Eureka需要在启动文件上加上注解@EnableEurekaServer,然后配置就行了
服务发现
让微服务相互交互起来,Spring Cloud 提供了两个组件进行支持,他就是Ribbon和Feign
微服务的调用
为了方便从不同的微服务中调用服务,使用基于REST风格提供一个URI请求,这样产品微服务就可以通过REST来请求获取用户服务了。
Ribbon负载均衡,具体会使用那个节点Spring Cloud已经屏蔽了一些底层细节,它只需要提供一个简单的@LoadBalance注解就可以提供负载均衡算法了。在默认的情况下他会提供轮询的负载均衡算法
Feign声明式调用
为了克服参数的组装和结果的返回等操作
为了启动Feign就需要在Spring Boot的启动文件中加入@EnableFeignClients
与Ribbon相比,Feign屏蔽掉了RestTemple的使用,采用接口式声明调用,使得程序可读性更高
断路器——Hystrix
降级服务
还需要再Spring Boot启动文件中加入@EnableCircuitBreaker
Hystrix默认的2000ms就会超时,但是希望能把这个数字进行自定义,可以使用@HystrixCommand中设置相关属性。
启用Hystrix仪表盘
对于Hystrix,Spring Cloud还提供了一个仪表盘(Dashboard)进行监控短路的情况,从而让开发者监控可能出现的新问题。
在Spring Boot启动文件中加入@EnableHystrixDashboard
默认支持三种监控,前两种是基于Turbine的,一种是默认集群,另一种是指定集群,第三种是单点监控。
使用单点监控需要引入actuator,添加配置属性
路由网关——zuul
他可以将请求转发为真实地址,进而保护真实服务器IP地址,其次他也可以作为负载均衡的方式,请求按照一定的算法方式平摊到多个路由节点上,最后他还能提供过滤器,可以判断是否为有效算法。
启用Zuul只需要在Spring Boot的启动文件上加上 @EnableZuulProxy,默认端口80
请求映射的配置文件
上面这种配置有一个问题就是无法将另一个服务节点加入,推荐使用下面这种面向服务的配置,配置产品微服务名称
过滤器
使用@SpringCloudApplication,这是为了解决启动文件的多注解
网友评论