Open eziceice opened 5 years ago
@SpringBootApplication
注解包含了@SpringBootConfiguration
,@EnableAutoConfiguration
和@ComponentScan
。@ConfigurationProperties
和@EnableConfiguration
可以将一系列的properties载入应用程序内。@PropertySource
可以自定义不同的配置文件来使用,避免把所有properties放在application.properties中。spring.profiles.active=dev/test/prod
便可以使用对应的配置文件。
1. Annotation in Spring IOC
Life cycle of Spring bean
Spring bean的生命周期大致分为Bean的定义,Bean 的初始化,Bean的生存期和Bean的销毁四个部分。
Bean Definition
Conditional
Bean的作用域
Profile
使用@Profile,并且使用环境命令-Dspring.profiles.active=dev可以随意切换配置环境。
引入XML配置Bean
使用@ImportSource就可以将定义好bean的xml装配到ioc容器中
Spring EL
{.....}代表启用Spring表达式,它将具有运算的功能;T(.....)代表引入类,Java默认的包可以只写包名,其他包必须用全名。beanName是Spring IOC容器的Bean的名称。
2. Spring AOP
How AOP works in Spring
AOP: Aspect oriented programming (面向切面编程)
约定编程
AOP的概念
AOP开发详解
@Aspect开启切面声明。
@Pointcut定义切点。execution(* com.springboot.service.UserSerivceImpl.printUser(..))
@Around是环绕通知,为所有通知中最强大的,可以直接去修改原目标对象的服务逻辑,当然通过调用proceed方法也可以调用原目标对象的服务逻辑。
@DeclareParents可以增强原类连接点的功能。@DeclareParents(value = "com.springboot.service.UserServiceImpl+", defaultImpl = UserValidatorImpl.class)。该功能是将两个类的接口挂在proxy的获取目标的接口的方法中,因此proxy可以在多个接口中互相转换。它有两个必须的属性配置:
通过使用args和Joint point,可以获取目标对象的传入参数。@Before("pointcut() && args(user)") - JoinPoint point - points.getArgs(); 环绕通知则使用ProceedingJoinPoint。
对于使用JDK来说,它是要求被代理的目标对象必须拥有接口,而对于CGLIB则不作要求。因此在默认情况下如果目标对象拥有接口,Spring将使用JDK进行动态代理运行,否则将使用CGLIB。
Spring也可以定义多个切面,通过使用@Order或者实现Ordered接口,可以控制切面的执行顺序。注意:对于前置通知,顺序为从小到大。而对于后置和返回通知,执行顺序为从大到小,这是一个典型的责任链模式的顺序。
3. Spring with Database
How to work with Database in Spring
Spring中主流方式是使用Mybatis和Hibernate,目前来看Hibernate全映射框架在互联网时代高性能的要求下逐渐被淘汰,Mybatis逐渐成为主流,Spring的JDBC Template则并不经常使用。
JDBC Template
Spring JPA (Hibernate)
MyBatis
MyBatis支持定制化SQL,存储过程以及高级映射的优秀持久层框架。
4. Spring with Transaction
Manage Transaction
在高并发的场景下,数据库事务便显得尤其重要,尤其是涉及到金钱的情况下,更是不允许出错的。Springboot通过各种注解来支持数据库事务的操作。在Spring的数据库事务中可以使用编程式事务,也可以使用声明式事务,现在在绝大部分的情况下都是使用声明式事务。
Spring声明式事务的使用
@Transcational配置项
@Transcationnal可以放在接口上也可以放在实现类上,推荐放在实现类上,因为该注解是基于AOP的,如果放在接口上意味着无法使用CGLIB的动态代理。
Isolation(事务的隔离级别)
追求更高的隔离级别,它能更好的保持数据的一致性,但是也要付出锁的代价。有了锁,就意味着性能的丢失,而且隔离级别越高,性能就是直线的下降。通常的隔离级别为read commited。不同的数据库对于隔离级别的支持也不一样,Oracle只支持read committed,而MySQL则支持四种。
数据库的ACID
数据库的四个隔离级别:
Propagation(事务的传播行为)
传播行为是方法之间调用事务采取的策略问题。在绝大部分的情况下,我们会认为数据库事务要么全部成功,要么全部失败。然而在某些情况下,我们不应该因为极少数的交易不能完成而回滚批量任务调用的其他交易。因此,如果一些交易发生异常,我们只是回滚那些出现异常的交易。
在Spring中,当一个方法调用另外一个方法时,可以让事务采取不同的策略工作,如新建事务或者挂起当前事务。 常用的Propagation:
NESTED: 当数据库支持保存点技术时(save point), 就启用保存点技术;如果不能支持,就新建一个事务去运行代码,等价于REQUIRES_NEW。NESTED的传播行为和REQUIRES_NEW还是有区别的。NESTED的传播行为会沿用当前事务的隔离级别和锁等特性,而REQUIRES_NEW则可以拥有自己独立的隔离级别和锁等特性。
@Transcationalt一定不可以使用在自调用,此时会失效(同一个类中的方法直接调用)。因为Spring数据库事务实现的原理是AOP,AOP的原理为动态代理,如果调用过程中是类本身的调用而不是代理对象的调用,则就不会有AOP,则Spring就不能把你的代码织入到约定的流程中。
5. Spring and Redis
Spring and Redis
NoSQL现在已经广泛应用,在互联网中起到加速系统的作用。其中有两种NoSQL使用最为广泛,那就是Redis和MongoDB。
Redis是一种运行在内存中的数据,支持7种数据类型的存储。由于其是基于内存的,因此运行速度很快,大约是关系数据库的几倍到几十倍的速度,所以开发中我们会将常用的数据存储到Redis中。
Spring-Jedis (Spring中Redis的驱动)
Redis Transcation
在高并发的场景中,往往我们需要保证数据的一致性,这时考虑使用Redis事务或者利用Redis执行Lua的原子性来达到数据一致性的目的。
Redis Pipline
在默认的情况下,Redis客户端是一条条命令发送给Redis服务器的,这样显然性能不太高。在关系数据库中我们可以使用批量,也就是只有需要执行SQL时,才一次性发送所有的SQL去执行,这样性能就高了很多。通常网络1传输速度的瓶颈会造成Redis性能不佳,然而使用pipline后就可以大幅度的在需要执行很多命令时提升Redis的性能。
Redis Subscription
发布订阅是message的一种常用的模式。通过多个监听器对渠道进行监听(Queue/Topic),来接受渠道内的消息。
Redis Lua Script
在Redis中使用Lua脚本可以提高Redis的计算能力,而且还具备原子性,所以在需要保证数据一致性的高并发环境中,我们也可以使用Redis的Lua脚本来保证数据的一致性。
在Redis中有两种运行Lua脚本的方法:
如果Lua脚本比较长,那么就需要通过网络传递脚本给Redis执行,而现实的情况是网络的传递速度往往跟不上Redis的执行速度,所以网络就成为了Redis执行的瓶颈。如果只是传递32位编码和参数,那么需要传递的消息就少了许多,这样可以极大的减少网络传输的内容,提升性能。
Redis Spring Annotation
6. Spring and MongoDB
MongoDB
由于Redis的计算能力十分有限,MongoDB此时就派上用场了。对于那些需要统计,按条件查询和分析的数据,它提供了支持,它可以说是一个最接近关系数据库的SQL。
MongoDB的目的是为Web应用提供可扩展的高性能数据存储解决方案。
MongoDB Template
Criteria
定义条件,使用Query
构建数据库语句,然后使用template
执行语句实现结果。MongoDB JPA + Template
7. Spring MVC
Spring MVC
Spring MVC是一个较为松散的组合,展示给用户的视图(View),控制器返回的数据模型(Model),定位试图的解析器(ViewResolver)和处理适配器(HandlerAdapter)等内容都是独立的。
Spring MVC的框架原理
Spring MVC的流程
流程和组件是Spring MVC的核心,Spring MVC的流程是围绕着DispatcherServelt而工作的,这是Spring MVC中最重要的内容。 流程:
Spring MVC处理请求并非一定经过全流程,有时侯比如发送JSON数据给前端则渲染过程不需要存在。
这些组件的初始化都是在spring-webmvc-xxx.jar中的属性文件DispatcherServlet.properties中配置的,定义的对象都是在Spring MVC开始时就初始化,并且放在Spring IOC的容器中。
@Controller和@RequestMapping在Web服务器启动Spring MVC时,被扫描到HandlerMapping的机制中存储,之后在用户发起请求被DIspatcherServlet拦截后,通过URI和其他的条件,通过HandlerMapper机制就能找到对应的Controller的方法进行响应。
通过HandlerMapping返回的是一个HandlerExecutionChain的对象,这个对象包含一个handler,这个是对controller的包装,因为controller中可能存在参数,那么handler就可以读入http和上下文相关参数,然后再传给controller。而在controller执行完成返回后,handler又可以通过配置信息对controller返回的结果进行处理。
有了Handler还需要去运行,但是这里面有普通的http request,有bean request,还有WebSocket request,所以还需要一个Adapter去运行HandlerExecutionChain对象包含的handler,这就是HandlerAdapter接口定义的实现类。
Spring MVC用于处理视图最重要的两个接口是ViewResolver和View。ViewResolver的主要作用是把一个逻辑上的视图名称解析为一个真正的视图,Spring MVC中用于把View对象呈现给客户端的是View对象本身,而ViewResolver只是把逻辑视图名称解析为对象的View对象。View接口的主要作用是用于处理视图,然后返回给客户端。
ViewResolver就是拿到三个参数:request,response,ModelAndView, 生成一个View对象的实例。而后DispatcherServlet就可以调用 View.render()了。
定制Spring MVC Initialization
Spring提供了接口WebMvcConfigurer,只需要implement这个接口便可以进行定制。Springboot是通过配置类WebMvcAutoConfiguration定义的,它有一个内部的类WebMvcAutoConfigurationAdapter,通过它Springboot就自动配置了Spring MVC的初始化。
8. 深入Spring MVC
深入Spring MVC开发
处理器映射
HandlerMapping的主要任务就是将请求定位到具体的Handler上。
获取Controller Parameter
自定义参数转换规则
Validation
Spring MVC支持JSR-303验证规范,在默认情况下SpringBoot会引入关于Hibernate Validator机制来支持JSR-303验证规范。
ModelAndView
Controller是业务逻辑核心内容,而控制器的核心内容之一就是对数据的处理。
ViewResolver和View
View是render数据模型展示给用户的组件,在Spring MVC中又分为logical view和physical view。Logical view需要ViewResolver进行进一步的定位解析。Physical view只需要将数据模型直接渲染出来。
File Upload
首先,DispatcherServlet会使用adapter模式,将HttpServletRequest接口对象转换为MultipartHttpServletRequest对象。MultipartHttpServletRequest接口扩展了HttpServletRequest接口的所有方法。
对于MultipartHttpServletRequest的配置,是通过MutipartResolver接口实现的。该接口有两个实现类,现在最常用的是StandardServletMutipartResolver(默认情况下SpringBoot的选择)。
推荐使用Servlet的Part类进行文件上传。
Interceptor
在HandlerExecutionChain对象中包含handler和Interceptor。其中Interceptor可以增强handler的功能。
Interceptor的流程如下:
多个拦截器的执行顺序是chain pattern的规则,因为request和response都需要拦截,对于handler之前的方法采用先注册先执行,而handler之后的方法则是先注册后执行。
AfterCompletion无论如何都会被执行,除非Exception发生在preHandle。
如果controller中发生exception,那么postHandle将无法被执行。
Spring MVC拾遗
@ResponseBody to JSON
当遇到标注的@ResponseBody后,handler就会记录这个方法的response类型为JSON。当执行完controller返回以后,handler就会启用ResultResolver去解析这个结果,它会去loop注册给Spring MVC的HttpMessageConverter接口的实现类。由于MappingJackson2HttpMessageConverter这个实现类已经被Spring MVC所注册,所以匹配上了,handler就会把结果变为JSON。如果转换成功,后续ModelAndView就返回null,这样ViewResolver和View render就不会被执行了。
Redirect
Spring MVC也支持Redirect的需求,就是通过各种方法将request定位到其他位置。可以通过“Redirect:"开头的字符串,同时也可以通过使用RedirectAttributes传递已有的对象给新的方法。在RedirectAttriubtes中通过使用addFlashAttriubte方法保存参数,在controller执行完成以后,会被保存在session对象中。当执行redirect时,在进入redirect之前首先把session中的参数取出,用来填充重定向的方法的参数和数据模型,之后删除session中的数据,然后调用redirect方法,并且将对象传递给redirect方法。
HttpSession
有两个注解用来操作HttpSession对象:
Controller Advice
可以通过给Spring MVC的controller增加通知,增强controller的功能,可以在controller方法的前后和异常发生时执行不同的处理。
@ControllerAdvice:定义一个controller的advice类,允许定义一些关于增强controller的各类advice和限定增强那些controller的功能等。
@InitBinder:定义Controller的参数绑定规则,如converter和formatter,它会在进入controller(参数转换之前)进行。
@ExceptionHandler:定义controller发生异常后的行为。
@ModelAttribute:可以在controller方法执行之前,对数据模型进行操作。
Parameter in request header
Use @RequestHeader可以获取header的参数。
9. 构建REST风格网站
REST Web Development
在REST风格中,每一个资源都是对应着一个地址,而一个代表资源网址应该是一个名词,而不存在动词,这代表着对一个资源的操作。
REST简述
REST:Representational State Transfer,如果一个architecture符合REST原则,就成它为REST Architecture。
REST Keyword
Resource-Reprensentation-State Transfer
Resource:它可以是系统权限用户,角色和菜单等,也可以是一些MediaType比如Text,Image,MP3等,总之就是一个具体存在的对象。每个资源对应一个独特的URI。在REST中,URI也可以称为end point。
Representation:如何展示这个资源。常用的JSON/XML。
State Transfer:一个资源可以被CRUD。对于HTTP协议,是一个stateless的协议,这就意味着对于Resource的state transfer只发生在Server端。
服务器存在着一系列的资源,每一个资源通过单独唯一的URI标识。
Client和Server之间可以相互传递资源,而资源会以某种表现层得以展示。
Client通过HTTP协议所定义的Action对资源进行操作,以实现资源的状态转换。
HTTP Method
Things to avoid in REST
使用Spring MVC开发REST风格End point
RestTemplate
在当今的microserivces中,会将一个大系统拆分为多个microsevices。按照microservices的建议,每个service系统都会暴露REST URL请求给别的微服务系统所调用。为了方便完成系统之间进行互相调用,Spring还给予了RestTemplate,通过它可以很方便的对REST请求进行系统间的调用,完成系统之间的数据集成。
10. Spring Security
Spring Security
对于构建distributed-miscroservices solution,通常security是一个很大的问题。Spring提供了其安全框架Spring Security来解决安全访问控制的问题。
Spring Security Basic和简单Security Authentication
使用WebSecurityConfigurerAdapter自定义
自定义用户服务信息
In-memory security
authorities("ROLE_USER", "ROLE_ADMIN")
。.roles("USER")
。Jdbc user details security
Restriction on request
configure(HttpSecurity)
的作用。通过它可以实现对于不同用户之间不同的权限的功能。hasAnyRole
方法会自动加入前缀ROLE_
。hasAuthority
则需要手动加入前缀ROLE_
。and
为连接词,代表重新加入新的验证权限。regexMatchers
。Spring EL Expression
access
方法,传入一个表达式,如果返回true就允许访问,否则就不允许。HTTPS
requiresChannel
和requiresSecure
或者requiresInsecure
,可以强制使用HTTPS或者HTTP。Cross-Site Request Forgery - CSRF
Remember me
rememberMe
方法,可以避免用户在一段时间内多次输入密码。并且该方法还可以设置有效时间和key,设置完成后客户端将该key-value保存在cookie中,并且以MD5进行加密,这样能够一定程度上对内容进行保护。Log out
11. Spring中的其他技术
Spring中的其他技术
Spring中还有一些其他的技术比如异步线程池,JMS Message,Scheduler和WebSocket等。
Async Thread Pool
Message Queue
SimpleMessageConverter
去实现转换规则,它实现了MessageConverter
接口。如果要使用其他的序列化器,如SerializerMessageConverter
或者Jackson2JsonMessageConverter
,只需要使用JmsTemplate的setMessageConverter
方法进行设置即可。Rabbit MQ
Schedule Task
Web Socket
WebSocket Protocol是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,允许服务器主动发送信息给客户端,这样就可以实现从客户端发送消息到服务器,而服务器又可以转发消息到客户端,这样就能够实现客户端之间的交互。
STOMP
并不是所有Browser目前都能够支持WebSocket Protocol,为了使得WebSocket的应用能够兼容那些unsupported browser,可以使用STOMP Protocol。
12. WebFlux
In computing, reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change.
Features of reactive programming:
Java的三种IO模型:
BIO(Synchronized Blocking模型) - Tomcat7之前的默认模型::
NIO(Non Blocking Synchronized模型) - Tomcat8之后的默认模型:
WebFlux中的Reactor模型:
WebFlux概述
Spring WebFlux Architecture: SpringMVC vs WebFlux:
WebHandler
WebFlux Client
WebClient
Converter
Database Concurrent Scenario
3 solutions to solve concurrent scenario: Pessimistic Lock, Optimistic Lock and Cache.
Pessimistic Lock
Select * from product where id = #{id} for update
Optimistic Lock
Cache-Redis
13. Deploy/Test and Monitor
Deploy
java -jar XXXX.war --server.port=XXXX
Hot Deploy
Monitor
/actuator/
。