Spring 全家桶
2022-07-30 21:01:42 0 举报
AI智能生成
spring 技术总结
作者其他创作
大纲/内容
Spring
ServletConfig获取配置信息、ServletContext的应用
ContextLoaderListener 监听器
Spring 应用启动的关键
Spring web启动过程
1.在Servlet容器启动的时候, 会创建一个ServletContext(整个应用上下文)
2. ContextLoaderListener实现了ServletContextListener接口,所以会有两个方法contextInitialized和contextDestroyed。web容器初始化时会调用方法contextInitialized,web容器销毁时会调用方法contextDestroyed。
3.通过 contextInitialized 方法,通过该方法创建一个IOC容器,并将创建的IOC容器存到servletContext中(将WebApplicationContext放入ServletContext)
属性为: servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
Spring基础配置
依赖注入
声明Bean的注解
@Component组件,没有明确的角色
@Service在业务逻辑层(service层)
@Repository在数据访问层(dao层)
@Controller在展现层(MVC→SpringMVC)
注入Bean的注解
@Autowired:Spring提供的注解
@Inject:JSR-330提供的注解
@Resource:JSR-250提供的注解
Java配置
@Configuration声明当前类是一个配置类
@Bean注解在方法上,声明当前方法的返回值为一个Bean
AOP
@Aspect 声明是一个切面
拦截规则@After @Before @Around
PointCut
JoinPoint
Spring常用配置
Bean的Scope
Singleton
Prototype
Request
Session
GlobalSession
SpringEL和资源调用
注入普通字符
注入操作系统属性
注入表达式云算结果
注入其他Bean的属性
注入文件内容
注入网址内容
注入属性文件
Bean的初始化和销毁
Java配置方式
注解方式
Profile
@Profile
通过设定jvm的spring.profiles.active参数
web项目设置在Servlet的context parameter中
事件Application Event
自定义事件,集成ApplicationEvent
定义事件监听器,实现ApplicationListener
使用容器发布事件
spring模块
子主题
Spring的模块
核心容器CoreContainer
Spring-Core
Spring-Beans
Spring-Context
Spring-Context-Support
Spring-Expression
AOP
Spring-AOP
Spring-Aspects
Messaging
Spring-Messaging
WEB
Spring-Web
Spring-Webmvc
Spring-WebSocket
Spring-Webmvc-Portlet
数据访问/集成(DataAccess/Intefration)
Spring-JDBC
Spring-TX
Spring-ORM
Spring-OXM
Spring-JMS
容器
BeanFactory
bean工厂(由`org.springframework. beans.factory.eanFactory`接口定义)是最简单的容器,提供基本的DI支持。
FactoryBean
一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式
以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
https://www.cnblogs.com/tiancai/p/9604040.html
DefaultListableBeanFactory
ApplicationContext
手动启动容器
AnnotationConfigBootstrap 启动类
XmlConfigBootstrap 启动类。
应用上下文
AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文
`AnnotationConfigWebApplicationContext`:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
`ClassPathXmlApplicationContext`:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
`FileSystemXmlapplicationcontext`:从文件系统下的一个或多个XML配置文件中加载上下文定义。
`XmlWebApplicationContext`:从Web应用下的一个或多个XML配置文件中加载上下文定义。
事件监听
图示
Spring 事件发布的核心类 AbstractApplicationContext
事件最终还是由组播(ApplicationEventMulticaster)发布。
事件最终还是由组播(ApplicationEventMulticaster)发布。
容器调用 事件流程
refresh() -> finishRefresh()-> publishEvent(new ContextRefreshedEvent(this));
发送 Spring 事件通过 ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)
Spring 事件的类型 ApplicationEvent
Spring 事件监听器 ApplicationListener
Spring 事件广播器 ApplicationEventMulticaster
实现类:SimpleApplicationEventMulticaster
自定义事件都是PayloadApplicationEvent
事件不一定是单线程执行。
refresh() -> finishRefresh()-> publishEvent(new ContextRefreshedEvent(this));
发送 Spring 事件通过 ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)
Spring 事件的类型 ApplicationEvent
Spring 事件监听器 ApplicationListener
Spring 事件广播器 ApplicationEventMulticaster
实现类:SimpleApplicationEventMulticaster
自定义事件都是PayloadApplicationEvent
事件不一定是单线程执行。
国际化消息接口MessageSource
接口方法
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
方法参数
https://www.jianshu.com/p/a354d3f849ec
bean的生命周期
https://yemengying.com/2016/07/14/spring-bean-life-cycle/
Spring Aware
BeanNameAware
BeanFactoryAware
ApplicationContextAware
MessageSourceAware
ApplicationEventPublisherAware
ResourceLoaderAware
bean 的作用域
1. singleton——唯一 bean 实例
2. prototype——每次请求都会创建一个新的 bean 实例
3. request——每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效
4. session——每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效
5. globalSession
创建Bean的整个过程
父子容器
通过HierarchicalBeanFactory 接口,Spring 的IOC容器可以建立父子关系的容器,子容器可以访问父容器的Bean 但是父容器不能访问子容器的Bean。
在容器内,Bean的id必须 是唯一的,但是子容器可以拥有一个父容器相同的Bean。
SpringMVC中体现
而典型的父子容器就是spring和springmvc同时使用的时候。分别ContextLoaderListener 创建的容器是父容器,DispatcherServlet 创建的容器是子容器。
IOC容器一系列缓存组件组成
IOC
依赖注入(手段)
构造注入
属性注入
接口注入
如何装配对象
基于xml
基于注解
基于javaConfig
控制反转(目的)
好莱坞法则:“不要给我们打电话,我们会给你打电话”
ioc容器控制bean的生命周期
AOP
Spring 原生APO 支持
前置通知:在目标方法执行之前执行,不改变方法的执行流程及执行结果,前置通知的实现类要实现`MethodBeforeAdvice`这个接口。
环绕通知:也叫方法拦截器,可以改变方法的执行流程及执行结果,环绕通知的实现类要实现`MethodInterceptor`这个接口。 (最强大)
后置通知:在目标方法执行之后执行,不改变方法的执行流程及执行结果,后置通知的实现类要实现`AfterReturningAdvice`这个接口。
异常通知: 在方法执行出现异常时候 ,需要实现这个接口`ThrowsAdvice`。
顾问(advisor) 核心接口:`PointcutAdvisor `接口,通知增强版
切入点 ` Pointcut` : 切点的定义会匹配通知所要织入的一个或多个连接点.我们通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。有些AOP框架允许我们创建动态的切
点,可以根据运行时的决策(比如方法的参数值)来决定是否应用通知。
点,可以根据运行时的决策(比如方法的参数值)来决定是否应用通知。
连接点:我们的应用可能也有数以千计的时机应用通知。这些时机被称为连接点。连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
织入:织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。
切面: 切面是通知和切点的结合。通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能。
AspectJ 支持
@EnableAspectJAutoProxy;
@Pointcut语法详解
理解核心思想
如果把传统核心逻辑编程理解为纵向执行,所有逻辑竖线走向,那么AOP则是以一种横切的方式织入到纵向逻辑中
我们可以把切面想象为覆盖在很多组件之上的一个外壳。借助AOP,可以使用各种功能层去包裹核心业务层。
AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
Spring对AOP的支持
AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:
Spring AOP 实现原理
JDK 动态代理
反编译输出到文件
结果
CGLIB 动态代理
持久层
各种 Template 使用
使用模板消除样板式代码
JPA支持
@Entity(name="USER"),@Table
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
@Column(name="USER_NAME")
@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
@OneToMany注解的使用
SpringDataJPA
什么是Spring Data JPA
开启
@EnableJpaRepositories
Repository<T, ID> 接口
CrudRepository<T, ID>
PagingAndSortingRepository<T, ID>
JpaRepository<T, ID>
定义数据访问层
query queryForObject queryForList update
execute
execute
定义查询方法
根据属性名查询
常规查询
限制结果数量
使用JPA的NamedQuery
使用@Query查询
使用参数索引
使用命名参数
更新查询
Specification
排序与分页
定义
使用排序
使用分页
find…By… / read…By… / query…By… / get…By…
count…By…
…OrderBy…[Asc / Desc]
And / Or / IgnoreCase
Top / First / Distinct
分页查询
PagingAndSortingRepository<T, ID>
Pageable / Sort
Slice<T> / Page<T>
自定义Repository的实现
定义自定义Repository接口
定义接口实现
自定义ReposityFactoryBean
开启自定义支持使用@EnableJpaRepositories的repositoryFactoryBeanClass来指定FactoryBean即可
JDBC
Redis
Spring的支持
配置
使用
opsForValue()
opsForList()
opsForSet()
opsForZSet()
opsForHash()
定义Serializer
Spring Boot的支持
安装Redis
非Docker安装
Docker安装
Mybatis(ORM框架)
基本组成
图示
关键类
动态SQL
通过便签的形式,减少了拼接SQL的难度
常用标签 if foreach where等
结果映射
ResultMap
association
collection
输入和输出映射
数据类型转换
插件机制
分页插件
扩展四个接口中的方法
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
核心原理
核心类和接口:
InterceptorChain执行链
Interceptor 执行
Invocation
Plugin 生成代理的类。
InterceptorChain执行链
Interceptor 执行
Invocation
Plugin 生成代理的类。
延迟加载
配置mybatis支持延迟加载
小结
缓存
一级缓存 session级别默认开启。
二级缓存默认是关闭的,Mapper接口级别,也是xml的NameSpace级别,不建议使用 ,用redis第三方等代替。
扩展
MyBatis:#和$的区别
mapper代理的方式
sqlMapConfig.xml
SaveOrUpdate
springboot中配置
mybatis.mapper-locations = classpath*:mapper/**/*.xml
mybatis.type-aliases-package = 类型别名的包名
mybatis.type-handlers-package = TypeHandler扫描包名
mybatis.configuration.map-underscore-to-camel-case = true
Mapper 的定义与扫描
@MapperScan 配置扫描位置
@Mapper 定义接⼝
映射的定义—— XML 与注解
PageHelper
事务抽象
事务处理
事务隔离级别
七大事务传播特性
事务机制
JDBC
DataSourceTransactionManager
JPA
JpaTransactionManger
Hibernate
HibernateTransactionManger
JDO
JdoTransactionManger
分布式事务
JtaTransactionManager
编程式事务
使用TransactionTemplate或者使用PlatformTransactionManager 等 API完成
TransactionTemplate
PlatformTransactionManager
声明式事务
通过xml配置
通过注解@Transaction
子主题
开启事务注解的⽅方式
事务管理器
核心接口 PlatformTransactionManager
org.springframework.jdbc.datasource.DataSourceTransactionManager 用于管理jdbc 和mybatis 数据源
org.springframework.orm.hibernate3.HibernateTransactionManager 用于管理hibernate 数据源
异常回滚
@Transactional(rollbackFor = Exception.class)注解了解吗?
只会回滚 RuntimeException 异常
核心接口
PlatformTransactionManager
TransactionDefinition
JDBC 异常抽象
Spring是怎么认识那些错误码的
Spring Security
Authentication(认证)
Authorization(授权) 发生在 Authentication(认证)之后。
SpringSecurity快速入门
什么是Spring Security
Spring Security的配置
DelegatingFilterProxy
配置
用户认证
内存中的用户
JDBC中的用户
通用的用户
请求授权
定制登录行为
SpringBoot的支持
自动配置了一个内存中的用户
忽略/css/** /js/** /images/** /**/favicon.ico等静态文件的拦截
自动配置的securityFilterChainRegistration的Bean
Spring task定时任务
xml 配置 task:scheduler
注解 @Scheduled
计划任务
cron
https://www.cnblogs.com/yanghj010/p/10875151.html
fixDelay
fixRate
异步任务
多线程
缓存支持 Spring Cache
https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/integration.html#cache
Spring 的缓存抽象
为 Java ⽅方法增加缓存,缓存执⾏行行结果
支持ConcurrentMap、EhCache、Caffeine、JCache(JSR-107)
接口
org.springframework.cache.Cache
org.springframework.cache.CacheManager
基于注解的缓存
Spring5 新特性
响应式编程 webFlux
概念
“在计算机中,响应式编程或反应式编程(英语:Reactive
Programming)是一种面向数据流和变化传播的编程范式。这
意味着可以在编程语言中很⽅便地表达静态或动态的数据流,
⽽而相关的计算模型会自动将变化的值通过数据流进行传播。”
Programming)是一种面向数据流和变化传播的编程范式。这
意味着可以在编程语言中很⽅便地表达静态或动态的数据流,
⽽而相关的计算模型会自动将变化的值通过数据流进行传播。”
Backpressure
Backpressure 指的是在 Buffer 有上限的系统中,Buffer 溢出的现象;它的应对措施只有一个:丢弃新事件。
https://www.jianshu.com/p/4e02c35152a9
Spring中的工具类
StringUitls
字符串操作
WebUtils
处理web的工具
ObjectUtils
BeanUtils
属性复制等
ReflectionUtils
简化反射操作
FileCopyUtils(文件复制),ResourceUtils(读取文件)等
SerializationUtils
序列化工具类
可参看 org.springframework.util包下
分析spring
BeanDefinition描述bean定义相关的信息。描述bean的行为(class,scope,LazyInit,factoryBeanName等信息)
Spring中有逻辑的代码doXXX,getXX,pa r se XXX
Spring:过滤器filter、拦截器interceptor、和AOP的区别与联系
Java 必须掌握的 20+ 种 Spring 常用注解
防止XSS跨站脚本攻击:Java过滤器
Spring:动态刷新JavaWeb应用ApplicationContext配置
Spring @Value:读取Properties配置文件
分布式Session:基于Spring-Session 和 Redis实现
Spring:代理Filter:DelegatingFilterProxy原理和作用
扩展-面试
什么是三级缓存
Spring如何解决循环依赖问题
Spring的后置处理器
Spring MVC
核心流程
核心图示
核心流程
一个请求的大致处理流程
web版
mvc 异步请求
子主题
Model1:在 Model1 模式下,整个 Web 应用几乎全部用 JSP 页面组成,只用少量的 JavaBean 来处理数据库连接、访问等操作。
Model2 :“Java Bean(Model)+ JSP(View,)+Servlet(Controller) 这种开发模式,这就是早期的 JavaWeb MVC 开发模式。Model:系统涉及的数据,也就是 dao 和 bean。View:展示模型中的数据,只是用来展示。Controller:处理用户请求都发送给 ,返回数据给 JSP 并展示给用户。
SpringMVC基础
Spring MVC的常用注解
@Controller
@RequestMapping
path / method 指定映射路径与请求方法
params / headers 限定映射范围
consumes / produces 限定请求与响应格式
@GetMapping / @PostMapping / @PutMapping / @DeleteMapping / @PatchMapping
@ResponseBody
@RequestBody
@PathVariable
@RestController
@ResponseStatus
Spring MVC的基本配置
静态资源映射
拦截器配置
@ControllerAdivce
@ExceptionHandler
@InitBinder
@ModelAttribute
其他配置
ViewController
路径匹配参数配置
WebMvcConfigurerAdapter
WebMvcConfigurer
Spring MVC的高级配置
文件上传配置
自定义HttpMessageConverter
MappingJackson2HttpMessageConverter
StringHttpMessageConverter
服务器端推送技术
SSE
Servlet3.0+异步方法处理
Spring MVC的测试
MockMVC
MockHttpServlerRequest
MockHttpServletResponse
MockHttpSession
基础模块
前端控制器DispatcherServlet
处理器映射器HandlerMapping
处理器适配器HandlerAdapter
处理器Handler
视图解析器View resolver
ViewResolver 与 View 接口
DispatcherServlet 中的视图解析逻辑
视图View
支持的视图
请求参数解析和封装
RequestMappingHandlerAdapter
HandlerMethodArgumentResolver接口
HandlerMethodArgumentResolverComposite类定义了26个默认的解析器;
ServletModelAttributeMethodProcessor 两种情况
1. 使用@ModelAttribute注解的类型参数
2. 自定义的POJO,通过特定的DataBinder将请求参数绑定到实体的属性上
1. 使用@ModelAttribute注解的类型参数
2. 自定义的POJO,通过特定的DataBinder将请求参数绑定到实体的属性上
其他参数的处理如:Map,ServletRequest,ServletResponse,Model 使用内置的转化器
https://docs.spring.io/spring/docs/5.1.5.RELEASE/spring-framework-reference/web.html#mvc-ann-arguments
类型转换
Converter<S,T> 接口
自定义类型转换器,实现convert方法
ConversionService接口
https://www.iteye.com/blog/elim-1860732
自己实现 WebMvcConfigurer
Spring Boot 在 WebMvcAutoConfiguration 中实现了了一个
添加⾃定义的 Converter
添加⾃定义的 Formatter
定义校验
通过 Validator 对绑定结果进行校验
@Valid 注解
BindingResult
方法返回值处理
HandlerMethodReturnValueHandler接口
https://docs.spring.io/spring/docs/5.1.5.RELEASE/spring-framework-reference/web.html#mvc-ann-return-types
拦截器
核心接口
HandlerInteceptor
Spring MVC 的拦截器
针对 @ResponseBody 和 ResponseEntity 的情况
ResponseBodyAdvice
针对异步请求的接口
AsyncHandlerInterceptor
拦截器器的配置⽅式
常规方法
WebMvcConfigurer.addInterceptors()
Spring Boot 中的配置
创建一个带 @Configuration 的 WebMvcConfigurer 配置类
不能带 @EnableWebMvc(想彻底⾃己控制 MVC 配置除外)
文件上传
配置CommonsMultipartResolver 文件上传解析器
通过参数MultipartFile 接收
配置 MultipartResolver
Spring Boot ⾃自动配置 MultipartAutoConfiguration
Spring Boot ⾃自动配置 MultipartAutoConfiguration
⽀持类型 multipart/form-data
全局异常处理
实现HandlerExceptionResolver接口
实现类
SimpleMappingExceptionResolver
DefaultHandlerExceptionResolver
ResponseStatusExceptionResolver
ExceptionHandlerExceptionResolver
@ControllerAdvice 注解
@ExceptionHandler:用于捕获所有控制器里面的异常,并进行处理。(和@ControllerAdveice两者配合使用处理全局异常,该注解在单个Controller中使用只会处理单个Controler的异常)
@InitBinder:用来设置 WebDataBinder,WebDataBinder 用来自动绑定前台请求参数到 Model 中。
@ModelAttribute:@ModelAttribute 本来的作用是绑定键值对到 Model 里,此处是让全局的@RequestMapping 都能获得在此处设置的键值对。
@InitBinder:用来设置 WebDataBinder,WebDataBinder 用来自动绑定前台请求参数到 Model 中。
@ModelAttribute:@ModelAttribute 本来的作用是绑定键值对到 Model 里,此处是让全局的@RequestMapping 都能获得在此处设置的键值对。
异常处理方法
@ExceptionHandler
添加位置
Spring Boot 对 Jackson 的支持
JacksonAutoConfiguration
JacksonHttpMessageConvertersConfiguration
静态资源与缓存
Spring Boot 中的静态资源配置
核心逻辑
WebMvcConfigurer.addResourceHandlers()
常用配置
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/META-INF/
resources/,classpath:/resources/,classpath:/static/,classpath:/public/
resources/,classpath:/resources/,classpath:/static/,classpath:/public/
Spring Boot 中的缓存配置
常用配置(默认时间单位都是秒)
ResourceProperties.Cache
spring.resources.cache.cachecontrol.max-age=时间
spring.resources.cache.cachecontrol.no-cache=true/false
spring.resources.cache.cachecontrol.s-max-age=时间
web容器三大组件(servlet 3.0)
@WebServlet
@WebFilter
@WebListener
SPI机制实现
https://www.jianshu.com/p/3a3edbcd8f24
Spring 在servlet容器实现(servlet3.0)WebApplicationInitializer
https://blog.csdn.net/huxiutao/article/details/86615325
Springboot
自动配置(AutoConfigurer)
为项目添加默认配置
application.properties和application.yml的配置会覆盖默认配置
自动扫描
@Import
导入某个配置类
@SpringBootApplication 入口类上的注解,复合注解,自动化配置,包扫描
从 CLASSPATH下的每个Jar包中搜寻所有 META-INF/spring.factories配置文件
注解模式
enable模式
@EnableWebMvc
@EnableTransactionManagement
@EnableAspectJAutoProxy
@EnableAsync
...
condition模式
@ConditionalOnBean 配置了某个特定bean
@ConditionalOnClass Classpath里有指定的类
@ConditionalOnWebApplication 这是一个Web应用程序
@ConditionalOnMissingClass Classpath里没有指定的类
...
核心注解
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnExpression
@ConditionalOnJava
@ConditionalOnJndi
ConditionalOnMissingBean
ConditionalOnMissingClass
ConditionalOnNotWebApplication
ConditionalOnProperty
ConditionalOnResource
ConditionalOnSingleCandidate
ConditionalOnWebApplication
Import模式
声明一个bean
导入@Configuration注解的配置类
导入ImportSelector的实现类
导入ImportBeanDefinitionRegistrar的实现类
导入@Configuration注解的配置类
导入ImportSelector的实现类
导入ImportBeanDefinitionRegistrar的实现类
@Import用来导入@Configuration注解的配置类、声明@Bean注解的bean方法、导入ImportSelector的实现类或导入ImportBeanDefinitionRegistrar的实现类。
自动装配原理
@EnableAutoConfiguration注解上导入AutoConfigurationImportSelector该类
https://blog.csdn.net/huang__2/article/details/104897957
MultipartAutoConfiguration
@EnableConfigurationProperties(MultipartProperties.class)
SpringApplication
注解编程模型
Spring 注解驱动示例
写法
Spring Boot 引导示例
SpringBoot 事件
事件发布
事件基础
Spring Boot 事件监听示例
步骤
Spring Boot 事件监听器
面试
框架底层的事件是单线程么?业务实现是否可以使用事件去实现?如果使用事件实现会不会是不是会有性能问题?
自动配置、起步依赖、Actuator、命令行界面(CLI) 是Spring Boot最重要的4大核心特性,能够快速构建spring 应用,内嵌web容器,starter 简化maven配置
SpringBoot核心功能
独立运行的Spring项目
内嵌Servlet容器
提供Starter简化Maven配置
自动配置Spring
准生产的应用监控
无代码声称和xml配置
“约定大于配置“的思想
使用约定的配置,不需要大量编写配置文件
SpringBoot基础
基本配置
入口类和@SpringBootApplication
@Configuration
@EnableAutoConfiguration
@ComponentScan
关闭特定的自动配置
定制Banner
修改Banner
关闭Banner
main里修改
fluentAPI
SpringBoot的配置文件
application.properties
application.yml
src/main/resources
starter pom
官方starter pom
spring-boot-starter
spring-boot-starter-actuator
spring-boot-starter-remote-shell
spring-boot-starter-amqp
spring-boot-starter-aop
spring-boot-starter-batch
spring-boot-starter-cache
spring-boot-starter-cloud-connectors
spring-boot-starter-data-elasticsearch
spring-boot-starter-data-gemfire
spring-boot-starter-data-jpa
spring-boot-starter-data-mongodb
spring-boot-starter-data-rest
spring-boot-starter-data-solr
spring-boot-starter-freemarker
spring-boot-starter-groovy-templates
spring-boot-starter-hateoas
spring-boot-starter-hornetq
spring-boot-starter-integration
spring-boot-starter-jdbc
spring-boot-starter-jerscy
spring-boot-starter-jta-atomikos
spring-boot-starter-jta-bitronix
spring-boot-starter-mail
spring-boot-starter-mobile
spring-boot-starter-mustache
spring-boot-starter-redis
spring-boot-starter-security
spring-boot-starter-social-facebook
spring-boot-starter-social-linkedin
spring-boot-starter-social-twitter
spring-boot-starter-test
spring-boot-starter-thymeleaf
spring-boot-starter-velocity
spring-boot-starter-web
spring-boot-starter-Tomcat
spring-boot-starter-Jetty
spring-boot-starter-undertow
spring-boot-starter-logging
spring-boot-starter-log4j
spring-boot-starter-websocket
spring-boot-starter-ws
第三方starter pom
Handlebars
Vaadin
Apache Camel
WRO4J
Spring Batch
HDIV
Jade Templates(jade4J)
Actitivi
使用XML配置
@ImportResource
外部配置
命令行参数配置
常规属性配置
类型安全的配置(基于properties)
日志配置
Profile配置
基于注解的配置
JavaConfig与常见Annotation
@Bean
@Configuration
基于properties配置文件的读取
spring原有的@Value注解
与@PropertySource(该注解指定配置文件的位置)配合使用,读取指定的配置属性
可以直接读取 application.properties文件
缺点, 单个属性的读取,仅支持简单数据类型,String,Beanlean 数值等
使用@ConfigurationProperties注解标注在类或者方法上
可以指定配置属性前缀,自动绑定属性值
1.支持实体属性的自动封装,2.支持复杂类型的解析,数组,list等
apringboot 可以自动注入Environment 类读取 application.properties文件
Actuator 监控
应用监控
http
测试端点
actuator
autoconfig
beans
dump
configprops
health
info
metrics
mappings
shutdown
trace
定制端点
修改端点id
开启端点
关闭端点
只开启所需端点
定制端点访问路径
定制端点访问端口
关闭http端点
自定义端点
状态服务
自定义端点
注册端点并定义演示控制器
知识清单
https://mp.weixin.qq.com/s/LIE0MorIkcyH5YPDs3pMcQ
开发部署与测试
开发的热部署
模板热部署
Thymeleaf
FreeMarker
Groovy
Velocity
SpringLoaded
JRebel
spring-boot-devtools
常规部署
jar形式
打包
运行
注册为Linux的服务
war形式
打包方式为war时
打包方式为jar时
云部署--基于Docker的部署
Dockerfile
FROM指令
MAINTAINER指令
RUN指令
CMD指令
EXPOSE指令
ENV指令
ADD指令
ENTRYPOINT指令
安装Docker
项目目录及文件
编译镜像
运行
SpringBoot的测试
新建SpringBoot项目
业务代码
测试用例
执行测试
Spring Boot 中的 RestTemplate
常⽤方法
GET 请求
getForObject() / getForEntity()
POST 请求
postForObject() / postForEntity()
PUT 请求
put()
DELETE 请求
delete()
构造 URI
构造 URI
UriComponentsBuilder
构造相对于当前请求的 URI
ServletUriComponentsBuilder
构造指向 Controller 的 URI
MvcUriComponentsBuilder
高阶用法
传递 HTTP Header
RestTemplate.exchange()
RequestEntity<T> / ResponseEntity<T>
类型转换
JsonSerializer / JsonDeserializer
@JsonComponent
解析泛型对象
RestTemplate.exchange()
ParameterizedTypeReference<T>
简单定制 RestTemplate
优化底层请求策略
连接管理
PoolingHttpClientConnectionManager
KeepAlive 策略
超时设置
connectTimeout / readTimeout
SSL校验
证书检查策略
Springcloud(微服务)
SpringCloud电商基本架构图示
架构设计图示
调用过程
服务注册发现
第三方注册 ( 独立的服务 Registrar )
第三方注册由一个独立的服务Registrar负责注册与注销。当服务启动后以某种方式通知Registrar,
然后 Registrar 负责向注册中心发起注册工作。同时注册中心要维护与服务之间的心跳,当服务不
可用时,向注册中心注销服务。这种方式的缺点是 Registrar 必须是一个高可用的系统,否则注册
工作没法进展。
然后 Registrar 负责向注册中心发起注册工作。同时注册中心要维护与服务之间的心跳,当服务不
可用时,向注册中心注销服务。这种方式的缺点是 Registrar 必须是一个高可用的系统,否则注册
工作没法进展。
客户端发现
客户端发现是指客户端负责查询可用服务地址,以及负载均衡的工作。这种方式最方便直接,而
且也方便做负载均衡。再者一旦发现某个服务不可用立即换另外一个,非常直接。缺点也在于多
语言时的重复工作,每个语言实现相同的逻辑。
且也方便做负载均衡。再者一旦发现某个服务不可用立即换另外一个,非常直接。缺点也在于多
语言时的重复工作,每个语言实现相同的逻辑。
服务端发现
服务端发现需要额外的 Router 服务,请求先打到 Router,然后 Router 负责查询服务与负载均衡。
这种方式虽然没有客户端发现的缺点,但是它的缺点是保证 Router 的高可用。
这种方式虽然没有客户端发现的缺点,但是它的缺点是保证 Router 的高可用。
注册中心:Consul
使用注册中心前,要明白其作用和概念
使用docker搭建Consul
拉取镜像:docker pull consul
启动镜像:docker run --restart=always -d -p 8500:8500/tcp -p 8500:8500/udp -p 8600 --name=consul -e CONSUL_BIND_INTERFACE=eth0 consul
访问:http://ip:8500
使用和基础知识
使用开发模式启动
使用和zk 类似
Conslu 核心
主要功能有服务发现、健康检查、KV存储、安全服务沟通和多数据中心
service模式
Server 节点保存数据;Server 节点有一个 Leader 节点和多个 Follower 节点,Leader 节点会将数据同步到 Follower 节点,在 Leader 节点挂掉的时候会启动选举机制产生一个新的 Leader
SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。
client模式
Client 节点负责健康检查及转发数据请求到 Server;Client 节点很轻量且无状态,它以 RPC (RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议)的方式向 Server 节点做读写请求的转发,此外也可以直接向 Server 节点发送读写请求
CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息
Watch模式
S-A启动时通过服务注册和服务发现工具获取到所有的健康实例S-B,并且将这些信息放入自己的内存中,S-A 可以通过监听(Watch)注册工具来更新存入内存中的 S-B 的服务信息。比如 S-B-1 挂了,健康检查机制就会将其标为不可用,这样的信息变动就被 S-A 监听到了,S-A 就更新自己内存中 S-B-1 的服务信息
Eureka注册中心
基础知识
什么是服务治理
什么是服务注册
Eureka两组件
actuator微服务信息完善
服务发现Discovery
eureka自我保护
概述
导致原因
怎么禁止自我保护
关闭后效果
配置
https://github.com/Netflix/eureka/wiki
Eureka注册中心的原理
peer(同伴)
集群架构
单机故障
Eureka:常见问题总结
Eureka:缓存细节以及生产环境的最佳配置
Spring Cloud : 如何优雅下线微服务?
源码
zookeeper注册中心
基础知识和使用
基本使用
服务节点是临时节点还是持久节点----临时节点
子主题
客户端注册
集群架构
注册中心比较
三个注册中心异同点
AP(eureka)
子主题
CP(Zookeeper/Consul)
微服务:注册中心ZooKeeper、Eureka、Consul 、Nacos对比
面试
阐述一下你们的服务注册中心部署架构,生产环境下怎么保证高可用?
你们系统遇到过服务发现过慢的问题吗?怎么优化和解决的?
如果需要部署上万服务实例,现有的服务注册中心能否抗住?如何优化?
Spring Cloud Commons 提供的抽象
服务注册抽象
提供了了 ServiceRegistry 抽象
客户发现抽象
提供了了 DiscoveryClient 抽象
提供了了 LoadBalancerClient 抽象
OpenFeign服务接口调用
基础知识
OpenFeign是什么
能干嘛
Feign和OpenFeign两者区别
使用
总结
OpenFeign超时控制
yml
OpenFeign日志打印功能
日志级别
yml
服务间调用:Spring Cloud Feign
例子
概念
在使用微服务时,避免不了的就是各个微服务间的调用,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的URLConnection、Apache的Http Client、Netty的异步HTTP Client,Spring的RestTemplate。但是,用起来最方便的还是要属Feign了。
简介
Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。
关键类参数介绍
使用@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。
深入理解Feign之源码解析
Feign 支持Hystrix
feign.hystrix.enabled=true
@FeignClient
fallback / fallbackFactory
客户端负载均衡:Spring Cloud Ribbon
简介
Spring cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它是基于Netflix的Riboon实现的。Ribbon是客户端负载均衡器,这有别语例如Nginx服务端负载均衡器。Ribbon本身提供了不同负载均衡策略使用不同的应用场景。
客户端负载均衡和服务端负载均衡的区别
BaseLoadBalancer
BaseLoadBalancer类是Ribbon服务均衡器的基础实现类,在该类中定义了很多关于负载均衡器的基础内容。
使用
RestTemplate的使用
getForObject方法/getForEntity方法
负载均衡+RestTemplate调用
LB(负载均衡)
集中式LB
进程内LB
Ribbon核心组件IRule
图示
com.netflix.loadbalancer.RoundRobinRule
com.netflix.loadbalancer.RandomRule
com.netflix.loadbalancer.RetryRule
WeightedResponseTimeRule
BestAvailableRule
AvailabilityFilteringRule
ZoneAvoidanceRule
替换使用
Ribbon负载均衡算法
轮询算法
源码阅读
RoundRobinRule
RandomRule
统一配置中心:zookeeper/spring cloud config
ZKUI
zkui为用户提供可视化界面,方便导入导出配置;使用docker安装zkui比较方便(1)docker pull maauso/zkui(2)docker run -t -i -e ZKLIST='10.2.11.202:2181' -p 9090:9090 maauso/zkui
spring cloud config
基础知识
与GitHub整合配置
Config服务端配置
读取配置规则
Config客户端配置
Config客户端之动态刷新
服务容错保护:Spring Cloud Hystrix
基础核心知识
重要概念
服务降级
服务熔断
服务限流
隔离
服务监控hystrixDashboard
解释
效果
注意:新版本Hystrix需要在主启动MainAppHystrix8001中指定监控路径
使用
访问
监控失败
监控窗口如何看?
七色
一圈
一线
整图说明1
整图说明2
搞懂一个才能看懂复杂的
hystrix案例
服务降级使用
服务降级缺陷
缺陷原因
每个方法配置一个???膨胀
和业务逻辑混在一起???混乱
服务熔断
熔断是什么
熔断器的核心API如下图
熔断开关图示
熔断类型
断路器在什么情况下开始起作用
熔断过程
断路器打开之后
ALL配置
一个HystrixCommand的执行逻辑
Hystrixl流程图(深入 Hystrix 执行时内部原理)
配置
Hystrix 的设计原则
图示
Hystrix 更加细节的设计原则
Hystrix特性
请求熔断
当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
服务降级
Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。
依赖隔离
在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用另外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放,后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在那里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用。
请求缓存
比如一个请求过来请求我userId=1的数据,你后面的请求也过来请求同样的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。
请求合并
我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。
Hystrixl流程图(深入 Hystrix 执行时内部原理)
基于Hystrip电商网站的商品详情页系统架构
小型电商网站的商品详情页系统架构
demo
大型电商网站的商品详情页系统架构
原理分析和使用(基于上面的系统)
基于 Hystrix 线程池技术实现资源隔离
利用 HystrixCommand 获取单条数据
利用 HystrixObservableCommand 批量获取数据
我们回过头来,看看 Hystrix 线程池技术是如何实现资源隔离的。
基于 Hystrix 信号量机制实现资源隔离
信号量机制
信号量简单 Demo
线程池与信号量区别
Hystrix 隔离策略细粒度控制
execution.isolation.strategy
command key & command group
command thread pool
command key & command group & command thread pool
其他
深入 Hystrix 执行时内部原理
图示(上面特性--流程图)
子主题
步骤一:创建 command
步骤二:调用 command 执行方法
步骤三:检查是否开启缓存
步骤四:检查是否开启了断路器
步骤五:检查线程池/队列/信号量是否已满
步骤六:执行 command
步骤七:断路健康检查
步骤八:调用 fallback 降级机制
深入 Hystrix 断路器执行原理的配置
相关配置
实例 Demo
深入 Hystrix 线程池隔离与接口限流
线程池隔离技术的设计
Hystrix 应用线程池机制的场景
优缺点
接口限流 Demo
基于 request cache 请求缓存技术优化批量商品数据查询接口
图示
demo
实现 Hystrix 请求上下文过滤器并注册
command 重写 getCacheKey() 方法
controller 调用 command 查询商品信息
发起请求
删除缓存
基于本地缓存的 fallback 降级机制
demo
步骤一:本地缓存获取数据
步骤二:实现 GetBrandNameCommand
步骤三:CacheController 调用接口
基于 timeout 机制为服务接口调用超时提供安全保护
配置
实例 Demo
如何做技术选型?Sentinel 还是 Hystrix?
Hystrix使用笔记
Hystrix源码分析
https://www.cnblogs.com/kingszelda/p/10312242.html
服务容错模式:舱壁模式、熔断器的异同点
Hystrix:普通Javaweb结合AOP使用
网关
概念
API 网关
请求转发
服务转发主要是对客户端的请求安装微服务的负载转发到不同的服务上
服务转发主要是对客户端的请求安装微服务的负载转发到不同的服务上
响应合并
把业务上需要调用多个服务接口才能完成的工作合并成一次调用对外统一提供服务。
把业务上需要调用多个服务接口才能完成的工作合并成一次调用对外统一提供服务。
协议转换
重点是支持 SOAP,JMS,Rest 间的协议转换。
重点是支持 SOAP,JMS,Rest 间的协议转换。
数据转换
重点是支持 XML 和 Json 之间的报文格式转换能力(可选)
重点是支持 XML 和 Json 之间的报文格式转换能力(可选)
安全认证
1. 基于 Token 的客户端访问控制和安全策略
2. 传输数据和报文加密,到服务端解密,需要在客户端有独立的 SDK 代理包
3. 基于 Https 的传输加密,客户端和服务端数字证书支持
4. 基于 OAuth2.0 的服务安全认证(授权码,客户端,密码模式等)
1. 基于 Token 的客户端访问控制和安全策略
2. 传输数据和报文加密,到服务端解密,需要在客户端有独立的 SDK 代理包
3. 基于 Https 的传输加密,客户端和服务端数字证书支持
4. 基于 OAuth2.0 的服务安全认证(授权码,客户端,密码模式等)
Zuul
Zuul1.x
Spring Cloud Gateway
概念
核心
Route
Route 是网关的基础元素,由 ID、目标 URI、断言、过滤器组成。当请求到达网关时,由 Gateway Handler Mapping 通过断言进行路由匹配(Mapping),当断言为真时,匹配到路由。
Predicate
Predicate 是 Java 8 中提供的一个函数。输入类型是 Spring Framework ServerWebExchange。它允许开发人员匹配来自 HTTP 的请求,例如请求头或者请求参数。简单来说它就是匹配条件。
Filter
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改.
工作流程(原理)
总结
配置使用
yml
代码中注入RouteLocator的Bean
通过服务名实现动态
yml
Predicate
Route Predicate Factories这个是什么东东
常用的Route Predicate
1.After Route Predicate
子主题
2.Before Route Predicate
3.Between Route Predicate
4.Cookie Route Predicate
5.Header Route Predicate
6.Host Route Predicate
7.Method Route Predicate
8.Path Route Predicate
9.Query Route Predicate
10.RemoteAddr Route Predicate
11.Weight Route Predicate
小总结
说白了,Predicate就是为了实现一组匹配规则, 让请求过来找到对应的Route进行处理
Filter的使用
Spring Cloud Gateway的filter
常用的GatewayFilter
AddRequestParameter
yml
自定义过滤器
自定义全局GlobalFilter
案例
作用
网关的作用:在使用微服务的过程中,随着服务数量的增加,会发现大量的ip和端口难以管理,此时网关结合注册中心就很好的解决了这个问题,对外只暴露网关的ip地址和端口,大大的提高了服务的安全性,当业务向某个应用发送请求时,只需请求网关,网关通过你携带的服务名进行请求转发,在转发前可以对请求的安全性进行校验,满足系统安全要求的请求才会被转发,否则拦截。当然不仅仅是安全性,还有其他一些操作,可以根据需求添加
限流篇
常见的限流算法
计数器算法
漏桶算法
在算法实现方面,可以准备一个队列,用来保存请求,另外通过一个线程池(ScheduledExecutorService)来定期从队列中获取请求并执行,可以一次性获取多个并发执行。
这种算法,在使用过后也存在弊端:无法应对短时间的突发流量。
这种算法,在使用过后也存在弊端:无法应对短时间的突发流量。
子主题
令牌桶算法
实现思路:可以准备一个队列,用来保存令牌,另外通过一个线程池定期生成令牌放到队列中,每来一个请求,就从队列中获取一个令牌,并继续执行。
RateLimiter:结合Spring Aop应用,以及SmoothBursty原理分析
令牌桶和漏桶对比
应用级限流
限流总并发/连接/请求数
限流总资源数
限流某个接口的总并发/请求数
限流某个接口的时间窗请求数
平滑限流某个接口的请求数
分布式限流
https://crossoverjie.top/JCSprout/#/distributed/Distributed-Limit
在Spring Cloud Gateway中,有Filter过滤器,因此可以在“pre”类型的Filter中自行实现上述三种过滤器。但是限流作为网关最基本的功能,Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类,适用Redis和lua脚本实现了令牌桶的方式。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类中,lua脚本在request_rate_limiter.lua文件
灰度发布
面试
如果网关需要抗每秒10万的高并发访问,你应该怎么对网关进行生产优化?
架构图示
第一个是高并发
第二个是如何优化
说说生产环境下,你们是怎么实现网关对服务的动态路由的?
你们是如何基于网关实现灰度发布的?说说你们的灰度发布方案?
说说你们一个服务从开发到上线,服务注册、网关路由、服务调用的流程?
SpringCloud Bus消息总线
基础知识
是什么
能干嘛
为什么被称为总线
SpringCloud Bus动态刷新全局广播
设计思想
1.利用消息总线触发一个客户端/bus/refresh,从而刷新所有客户端配置
2.利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,从而刷新所有客户端配置
对比
使用
SpringCloud Bus动态刷新定点通知
总结
总体架构
Git 配置更新 Bus 架构
SpringCloud Stream消息驱动
基础知识
为什么使用Cloud Stream
stream凭什么可以统一底层差异
Binder
INPUT对应于消费者
OUTPUT对应于生产者
Stream中的消息通信方式遵循了发布-订阅模式
Spring Cloud Stream标准流程套路
编码API和常用注解
标准MQ
分组消费与持久化
Spring Cloud Stream 以及 Binder 架构
深入对比
SpringCloud Sleuth分布式链路跟踪
概述
为什么出现
1.zipkin
https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/
运行
java -jar zipkin-server-2.12.9-exec.jar
控制台
http://localhost:9411/zipkin/
术语
简化
使用
dubbo 和Spring Cloud
面试
画一下你们系统的整体架构图,说说各个服务在生产环境怎么部署的?
你们系统每天有多大访问量?每个服务高峰QPS多少?压测过服务最大QPS吗?
如果系统访问量比现在增加10倍,你们考虑过系统的扩容方案吗?
你们生产环境的服务是怎么配置超时和重试参数的?为什么要这样配置?
如果出现服务请求重试,会不会出现类似重复下单的问题?
对于核心接口的防重幂等性,你们是怎么设计的?怎么防止重复下单问题?
画一下你们电商系统的核心交易链路图,说说分布式架构下存在什么问题?
针对电商核心交易链路,你们是怎么设计分布式事务技术方案的?
对于TCC事务、最终一致性事务的技术选型,你们是怎么做的?如何调研的?
你了解RocketMQ对分布式事务支持的底层实现原理吗?
图示
具体实现
如果公司没有RocketMQ中间件,那你们如何实现最终一致性事务?
你们生产系统中有哪个业务场景是需要用分布式锁的?为什么呢?
图示
你们是用哪个开源框架实现的Redis分布式锁?能说说其核心原理么?
如果Redis是集群部署的,那么集群故障时分布式锁还有效么?
如果要实现ZooKeeper分布式锁,一般用哪个开源框架?核心原理是什么?
图示
子主题
对于ZooKeeper的羊群效应,分布式锁实现应该如何优化?
图示
子主题
如果遇到ZooKeeper脑裂问题,分布式锁应该如何保证健壮性?
你们的分布式锁做过高并发优化吗?能抗下每秒上万并发吗?
淘宝和京东的库存是怎么实现的?能不能不用分布式锁实现高并发库存更新?
使用
1.版本选择
版本技术选型
2.关于Cloud各种组件的停更/升级/替换
服务注册中心
服务调用
服务调用
服务降级
服务网关
服务配置
服务主线
参考资料见官网
Spring Cloud
https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
Spring Cloud中文文档
https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md
Spring Boot
https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/
3.微服务架构编码构建
图示
SpringCloud Alibaba Nacos服务注册和配置中心
概念
服务注册
使用
配置中心
使用
配置
Namespace+group+data ID三者关系?为什么这么设计?
Nacos集群和持久化配置(重要)
架构图
官网版本简化
注意
Nacos持久化配置解释
集群配置
SpringCloud Alibaba Sentinel实现熔断与限流
sentinel
和hystrix对比
特性
划分
控制台使用
接入客户端注意
流控规则
解释
流控模式
直接(默认)
关联
链路
流控效果
直接->快速失败
预热
场景
排队等待
源码
qps / 1 秒 = 每隔多少时间通过一个请求
降级规则
基本使用的概念
解释
Sentinel的断路器是没有半开状态的
复习Hystrix
降级策略
RT
异常比例
异常数
热点key限流
实现
使用
配置
异常
系统规则
是什么
各项配置说明
@SentinelResource
入门
按资源名称限流
按照Url地址限流
自定义限流
注意
核心API
规则持久化
怎么玩
数据源
配置 4 个数据源:
图示
添加Nacos业务规则配置
验证
SpringCloud Alibaba Seata处理分布式事务
分布式事务问题
Seata简介
怎么玩
seata的分布式交易解决方案
一个典型的分布式事务过程
分布式事务处理过程-ID+三组件模型
Transaction ID(XID)
三组件概念
处理过程
补充内容
再看TC/TM/RM三个组件
AT模式如何做到对业务的无侵入
是什么
一阶段加载
二阶段提交
三阶段回滚
过程
Seata-Server安装
3.seata-server-0.9.0.zip解压到指定目录并修改conf目录下的file.conf配置文件
file.conf
service模块
红色的自己取名字
store模块
4.mysql5.7数据库新建库seata
5.在seata库里新建表
6.修改seata-server-0.9.0\seata\conf目录下的registry.conf目录下的registry.conf配置文件
7.先启动Nacos端口号8848
8.再启动seata-server
使用注意
微服务
区别
单体架构
单体系统,所有功能模块 耦合在一个系统
打包部署 独立单元 jar war
只有一个进程
打包部署 独立单元 jar war
只有一个进程
微服务架构
架构风格
1:N=系统:多个服务
每个服务独立部署
每个服务高内聚 服务之间低耦合
1:N=系统:多个服务
每个服务独立部署
每个服务高内聚 服务之间低耦合
其他架构风格:
客户端 服务端
组件架构 EJB
分层架构 MVC
面向服务架构 SOA
客户端 服务端
组件架构 EJB
分层架构 MVC
面向服务架构 SOA
微服务架构的特征
通过服务进行组件化
围绕业务能力进行组织
智能端点和哑管
去中心化的治理
分散数据管理
基建自动化
设计时为故障做好准备
演化设计
单体架构
微服务技术栈
问题
微服务和分布式数据管理问题
事件驱动架构
1.订单服务创建一个带有 NEW 状态的 Order (订单),发布了一个 “Order Created Event(创建订单)” 的事件。
2.客户服务消费 Order Created Event 事件,为此订单预留信用,发布 “Credit Reserved Event(信用预留)” 事件。
3.订单服务消费 Credit Reserved Event ,改变订单的状态为 OPEN。
原子操作 Achieving Atomicity
使用本地交易发布事件
挖掘数据库交易日志
使用事件源
总结
微服务:通信协议
微服务:幂等机制和解决方案
深入浅出Event Sourcing和CQRS
微服务:设计模式
从分布式一致性谈到CAP理论、BASE理论
微服务:如何做好服务拆分?
为什么大型互联网都需要网关服务?
系统架构演变:SOA、微服务架构的区别和联系
微服务:全链路压测和容量规划
微服务:监控体系,容器监控
Spring详细配置版
IOC
概念
控制反转
控制:对对象的创建和管理
反转:对对象的控制由程序员转变为框架
核心目的
让spring来管理对象
优点
单例
降低耦合(类与类之间的依赖关系)
IoC核心容器
顶层接口BeanFactory和
ApplicationContext的区别
ApplicationContext的区别
单例对象适用
AplicationContext在构建核心容器时,创建对象采用的是立即加载的方式,即配置文件一读取完,立马创建对象
AplicationContext在构建核心容器时,创建对象采用的是立即加载的方式,即配置文件一读取完,立马创建对象
多例对象适用
BeanFactory在构建核心容器时,创建对象采用的是延迟加载方式,即什么时候通过Id获取对象,什么时候创建
BeanFactory在构建核心容器时,创建对象采用的是延迟加载方式,即什么时候通过Id获取对象,什么时候创建
ApplicationContext常用实现类
ClassPathXmlApplicationContext
读取类路径下的配置文件
FileSystemXmlApplicationContext
读取电脑任意位置的配置文件
AnnotationConfigApplicationContext
用于使用新注解+配置类的方式代替xml配置文件时
IOC创建对象方式
无参构造器
在spring配置文件中用bean标签配置
bean标签的属性
id
创建的对象名
class
需要被管理的类的全路径
静态工厂
条件:需要工厂类,该工厂类中需要有静态方法
配置文件语法
<bean id="factory" class="com.wxs.factory.BeanFactory" factory-method="静态方法名" />
当用spring容器调用getBean方法时会创建工厂类对象,并执行工厂类中的方法返回需要的对象并放入spring容器中
实例工厂
条件:需要工厂类,这个工厂类中需要有普通方法
配置文件语法
<bean id="factory" class="com.wxs.factory.BeanFactory" />
<bean id="car" factory-bean="factory" factory-method="普通方法名">
需要先创建工厂对象再调用工厂中的普通方法
DI(依赖注入)的方式
setter注入
条件:属性必须有setter方法
bean标签下<property>标签
name:属性名
value:属性值,针对基本类型和String类型
ref:针对对象类型,指向的是bean标签的id属性的值
复杂注入(map、list、[]...)
list类型语法
数组类型与list类型类似只是没有ref标签
map类型
<bean id="empService" class="com.wxs.service.EmpService">
<property name="list">
<map>
<entry key="" value=""></entry>
</map>
</property>
</bean>
<property name="list">
<map>
<entry key="" value=""></entry>
</map>
</property>
</bean>
properties类型
<bean id="empService" class="com.wxs.service.EmpService">
<property name="p">
<props>
<prop key="" value=""></prop>
</props>
</property>
</bean>
<property name="p">
<props>
<prop key="" value=""></prop>
</props>
</property>
</bean>
有参构造器注入
条件:必须要有构造器
bean标签下<constructor-arg>标签
name属性:属性名
value:值,针对基本类型和Stirng
ref:针对对象类型
p名称空间注入
条件:需要在配置文件中导入p的命名空间(spring提供的),底层还是set方式,所以属性也必须有setter方法
IOC三种开发方式
手动配置方式
bean标签:在配置文件中用bean标签配置一个类
id属性:用来给对象命名
class属性:用于写实体类的全路径名,供反射适用
scope属性
singleton
单例
只要配置文件被加载,就会创建对象,创建的对象放在spring容器中,这个容器底层为
map集合,key为bean标签的id值,value为这个对象
map集合,key为bean标签的id值,value为这个对象
当调用容器的getBean方法的时候,总是获取到唯一的实例
service/dao需要单例模式
proyotype
多例
当配置文件加载的时候不创建对象,当调用容器的getBean方法时,创建对象并返回,调用一次getBean则创建一次
action适合多例
request
作用于web应用的请求范围
session
作用于web应用的会话范围
globle-session
作用于集群环境的会话范围(全局范围)
对象销毁时机
singleton
当spring容器关闭的时候对象销毁
proyotype
长时间不用则被GC回收
若需要给一个类中的成员变量赋初始值则需要在bean标签中定义property子标签
name属性:类的属性名
value:定义普通成员变量的值
ref:如果一个类中引用到其他类的对象,需要用此属性注入
***注意:在配置文件中给属性设置初始值需要提供该属性的setter方法
property子标签<list>
专门用于给list集合类型的成员变量赋初始值
格式
<bean id="empService" class="com.wxs.service.EmpService">
<property name="list">
<list>
<value>11</value>
</list>
</property>
</bean>
<property name="list">
<list>
<value>11</value>
</list>
</property>
</bean>
半自动配置方式
半自动配置方式主要是将类与类之间的依赖关系用注解的方式实现
类的对象还是需要手动配置,但类的依赖关系用注解@Autowired自动实现,
例如A类中引用了B类,在配置文件中用bean标签配置A,在A中用注解标记引用的B
例如A类中引用了B类,在配置文件中用bean标签配置A,在A中用注解标记引用的B
***注意:Spring框架为了效率,默认在扫描类的时候不会扫描注解,所以默认情况下只加Autowired注解是无法
自动注入的,需要在配置文件用<context:annotation-config/ >进行配置
自动注入的,需要在配置文件用<context:annotation-config/
全自动配置方式
基本不用配置文件
在类上用@Component注解标记,类中的依赖关系用@Autowired注解标记
在配置文件中用<context:component-scan base-package="com.wxs" />配置需要扫描的包
在全自动配置方式中,对于私有的成员变量,也无须提供setter方法,反射会自动打开访问权限强制访问
***注意:如果通过一个类型匹配到了多个实现类,则会报错,解决方式为在引用类型上添加@Qualifier("")注解指明需要的类
四个创建对象的注解
Component:无法划分类的时候
Repository:一般用于标注dao层或者说标注数据库操作层
Service:业务层
Controller:控制层/表现层(springmvc替代servlet)
**以上四个注解没有区别,只是用于不同场景
Scope:定义类的单例多例
PreDestory
指定销毁方法
PostConstruct
指定初始化方法
三个依赖注入的注解
Value
针对基本数据类型和String类型
Autowired
该注解由Spring框架提供
按类型去找,如果找不到就是没有,如果找到多个就报错,解决方式是搭配Qualifier注解指明适用哪个注解
Resource
该注解由JDK提供
先按名字去找,第一种是name属性配置名字@Resource(name = "名字"),如果没有指定名字
则把变量名当作要寻找的属性名,如果再找不到,最后按类型去找
则把变量名当作要寻找的属性名,如果再找不到,最后按类型去找
spring新注解
写一个类,用新注解标注,可以让该类的作用和application.xml的作用一样
@Configuration
表名该被标注的类是一个配置类,但本质作用并不是标注它是一个配置类,而是加上这个注解之后,该类中的所有方法会被
CGLib代理,方法会跟原来的方法完全不一样,这样就保证了对象的生命周期和作用域。
如果不加该注解,在该类中用Bean注解照样好用,用AnnotationApplicationContext去容器取对象也好用,只不过如果该类
中的一个创建对象的方法调用了另一个创建对象的方法,那么另一个对象将被创建多次,不能保证对象的单例,即作用域scope
不能被保证
CGLib代理,方法会跟原来的方法完全不一样,这样就保证了对象的生命周期和作用域。
如果不加该注解,在该类中用Bean注解照样好用,用AnnotationApplicationContext去容器取对象也好用,只不过如果该类
中的一个创建对象的方法调用了另一个创建对象的方法,那么另一个对象将被创建多次,不能保证对象的单例,即作用域scope
不能被保证
@ComponentScan
通过该注解告诉spring在创建容器时需要扫描的包
属性value,和xml配置文件中的<context:component-scan>标签中的basePackage属性作用一样
@Bean
用于标注配置类中的方法,将方法的返回值对象存入spring容器中
name属性用于定义bean的id,当不写时,存入容器集合时key默认为方法名,值为对象
细节:当我们使用注解配置方法时,如果方法有参数,spring会自动去容器中找有没有可用的bean,查找的方式与@Autowired
注解的方式一致
注解的方式一致
此时不再使用ClassPathXmlApplicationContext,而是要用AnnotationConfigApplication,并将该配置类的class对象传入
原理
如何创建对象
通过IO读取配置文件
利用反射创建对象:class.forName(配置文件中的全路径名)
如果是全自动模式,则通过IO读取配置文件读到的是包,然后再通过IO去扫描这个包下所有的类(包括子包)
扫描的类如果由Component注解标记,则创建该类对象,如果没有,则忽略
扫描的类如果由Component注解标记,则创建该类对象,如果没有,则忽略
重点是反射+IO
如何管理依赖关系
扫描所有成员变量,如果成员变量带有自动注入注解,则从自己容器中寻找要注入的对象,利用反射对其进行注入,如果
找到相应对象,暴力破解直接赋值,如果没找到,则报错
找到相应对象,暴力破解直接赋值,如果没找到,则报错
AOP
面向切面编程思想:对共同内容进行抽取,在需要用到的地方用动态代理的方式进行插入,在不修改源代码的基础
上,还能对源码进行加强
上,还能对源码进行加强
底层为动态代理:对目标类进行功能增强
对目标类方法进行加强的方式
继承
缺点:需要直到要增强的方法的类才能继承
装饰者模式
缺点:需要有接口,这个接口下除了要增强的方法外别的方法也要实现
动态代理模式
JDK
需要接口但可以指定增强方法,不需要实现全部方法
Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
返回一个指定接口的代理类实例
返回一个指定接口的代理类实例
参数列表:和目标对象相同的类加载器;目标类所有的接口;增强类(可以自定义增强类并实现InvlcationHandler
接口并重写其内部方法,也可以在此处直接定义匿名内部类)
接口并重写其内部方法,也可以在此处直接定义匿名内部类)
此处的InvocationHandler可以是一个匿名内部类,实现内部的invoke方法,在该方法中定义增强逻辑
该方法的参数:代理类对象;要被增强的方法(在将目标类所有接口传进去时就已经知道所有的代理方法了);
方法需要的参数。
该方法的参数:代理类对象;要被增强的方法(在将目标类所有接口传进去时就已经知道所有的代理方法了);
方法需要的参数。
细节
proxyPerson.run(); // 执行这个方法 invoke都会执行一遍 执行的内容就是针对该方法的增强
返回值 return 谁调用返回给谁 返回的内容就是最终值而不是需要增强的方法的返回值
通过if-else判断方法名来增强指定方法
CGLIB
不需要接口,可以指定增强方法,但代码量比较大
CGLIB原理
该代理模式是用拦截器和过滤器的方式进行继承,对目标类的方法进行增强
AOP的三种方式
自由式
步骤
确定目标类(要被切的类,即需要被加强的类),需要定义切入点,此处切入点为需要增强的方法
确定切面类,即用来切类的刀,需要定义增强后的方法
织入配置,把增强方法指定在切入点之前、之后、环绕、异常、最终 执行
配置文件
织入时机
前置增强
用<aop:before>标签配置
切入点即需要增强的方法,在切入点前介入即在需要增强的方法前介入其他业务逻辑,例如在执行
原方法前打印日志或者其他操作
原方法前打印日志或者其他操作
后置增强
用<aop:after>标签配置
在原方法执行结束后介入增强后的方法
环绕增强
用<aop:around>标签配置,需要在增强后的方法中传参:ProceedingJoinPoint类型的对象,这个对象
中包含着目标类需要增强的方法,需要在增强后的方法中调用pjp.proceed()方法,相当于调用原方法,
在该方法前后需要写自己的业务逻辑实现环绕介入
中包含着目标类需要增强的方法,需要在增强后的方法中调用pjp.proceed()方法,相当于调用原方法,
在该方法前后需要写自己的业务逻辑实现环绕介入
异常增强
用<aop:after-throwing>标签配置
在原方法发生异常时会介入,一般用于对数据库事务的处理
最终增强
用<aop:after-returning>标签配置
在需要增强的方法正确地返回之后执行
接口规范式
步骤
定义切面类,让其实现特定接口(五类织入时机)
确定目标类(被介入的类),确定其切点
确定切面类(做介入角色的类)
配置文件
前置增强
定义的切面类需要实现MethodBeforeAdvice接口并实现befor方法
该方式底层会调用目标类中需要增强的方法,在该切面类中的before方法中只需要写自己的业务逻辑即可
后置增强
定义的切面类需要实现AfterReturnAdvice接口并实现afterReturn方法
参数
Object returnValue
原方法返回值
Method method
目标方法
Object[] args
目标方法执行需要的参数数组
Object target
目标对象,即被代理的类的对象
环绕增强
切面类需要实现MethodInterceptor接口并实现invoke(MethodInvocation invocation)方法
这种增强方式需要在invoke方法中调用invocation的proceed()方法调用目标方法,在该语句前后实现自己的
业务逻辑达到环绕增强的效果
业务逻辑达到环绕增强的效果
异常增强
切面类实现ThrowsAdvice接口,该接口是一个空接口,需要在该切面类中自定义名为afterThrowing(Exception e)方法
最终增强
注解介入
springmvc
什么是springmvc
springmvc实际上是springframwork的一个模块,这个模块主要是对web的支持
springmvc是基于IoC和aop的
servlet缺点
获取参数比较繁琐,如果类型不是字符串类型则需要进行类型转换,还需要判断是否为空
如果每个servlet对应一个请求,则会产生大量的servlet,如果一个servlet对应多个请求,则违反可单一原则
原理
springmvc提供了一个servlet,我们把所有的请求都发送给这个servlet,这个servlet我们称之为核心控制器
核心控制器在tomcat启动时就会创建,在其init方法中会读取配置文件并扫描指定的包,会为由@Controller注解标记
的类创建对象,并把所有的由@RequestMapping注解标记的映射关系放到HandlerMapping中,键放注解的地址,值放
方法
的类创建对象,并把所有的由@RequestMapping注解标记的映射关系放到HandlerMapping中,键放注解的地址,值放
方法
当在地址栏输入地址,核心控制器会根据资源路径从HandlerMapping中寻找要执行的方法,找到后并调用
在控制类的方法中处理请求和响应,用return实现请求转发(携带的参数放到ModelMap中)和重定向(在返回的字符串前加redirect)
三大核心组件
处理器映射器
作用:帮我们找到对应的controller
HandlerMapping
传统开发方式,即配置文件方式
依赖BeanNameUrlHandlerMapping类
注解开发方式,已过时类
AnnotationMethodHandlerAdapter(过时的注解开发方式)
注解开发方式,最新类
RequestMappingHandlerAdapter(最新版本的注解开发方式)
在springmvc内部配置文件中,注解开发方式配置的还是过时的注解驱动类,需要在springmvc配置文件中用
<mvc:annotation-driven/>标签配置新版注解驱动类
<mvc:annotation-driven/>标签配置新版注解驱动类
处理器适配器
作用:帮我们找到响应的方法
方法返回ModelAndView
视图解析器
在springmvc配置文件中配置,用来配置contorller类中方法返回的字符串类型的前缀和后缀,简化返回的静态地址的字符串
将结果渲染成页面
控制类中的注解
@Controller
标记控制类,该类拥有处理请求的能力
@RequesMapping
标注方法,定义请求路径
窄化映射,可以定义到controller类上,隔离各个控制类中的方法
value和path属性
标注这个方法处理请求的地址,支持传数组,可以响应多个请求
method
设置接收的请求的请求方式
RequestMethod.GET, RequestMethod.POST
@ResponseBody
用此注解标记该方法,则底层会将该方法的返回值转换为json格式,spring没有内置转json的类,需要依赖三方jar包
@CrossOrigin
设置跨域访问
传统方式需要设置响应头setHeader("Access-Control-Allow-Origin", "协议+ip+端口")
浏览器的同源策略
同源指的是同一个服务器
如果a服务器向b服务器发送ajax请求,b服务器接收并响应数据,在默认情况下,a服务器的ajax拒绝接收b
服务器的响应,所以需要在b服务器端设置跨域访问,解决跨域错误问题
服务器的响应,所以需要在b服务器端设置跨域访问,解决跨域错误问题
@PathVaribale
用于绑定url的占位符,例如:在请求的url中,/emplist/{empId},{empId}就是一个占位符,在参数列表中想要对应占位符的参数前用
该注解标注,该注解中的值应当与占位符的值一致。url支持占位符是在spring3.0以后引入的
该注解标注,该注解中的值应当与占位符的值一致。url支持占位符是在spring3.0以后引入的
用于实现restful风格
如果想要实现restful风格,则需要将web.xml文件中核心控制器的请求路径设置为/,但此时将会把所有的静态文件例如js、css等
也作为请求发送到核心控制器并去找相应的方法执行,此时就会访问不到静态资源,所以释放静态资源
也作为请求发送到核心控制器并去找相应的方法执行,此时就会访问不到静态资源,所以释放静态资源
在springmvc配置文件中配置静态资源,用<mvc:resources location="请求地址例如:/js/(以js开头的请求)"
mapping="映射位置例如 :/js/**(项目下js文件夹下所有的文件的子文件)" />
mapping="映射位置例如 :/js/**(项目下js文件夹下所有的文件的子文件)" />
restful风格
用占位符的方式接收参数,占位符的参数名叫啥,前端name应该叫啥
传统风格
RequestMapping("/delete")
localhost:8080/delete?id=10
localhost:8080/delete?id=10
restful风格
RequestMapping("/delete/{id}")
restful风格:localhost:8080/delete/10
restful风格:localhost:8080/delete/10
@ModelAttribute
被该注解标注的方法会先执行
适用场景:当前端提交表单,带着表单数据向控制类中的某个方法发送请求,但表单数据并不是一个完整的JavaBean对象的
数据,此时可以定义一个新的方法,用该注解标注,那么在执行对应请求方法时会先执行该方法,该方法也可以从请求中
获取请求参数,可以在该方法中通过请求参数从数据库查询完整数据,并将最后JavaBean对象返回,这样数据就会完整,另
一种方式是无返回值方法,可以参参数列表定义一个map集合,将最后的JavaBean放入map集合中,在对应的请求方法的
参数列表中也用ModelAttribute注解标注参数,并在注解中给出放入map集合的key
数据,此时可以定义一个新的方法,用该注解标注,那么在执行对应请求方法时会先执行该方法,该方法也可以从请求中
获取请求参数,可以在该方法中通过请求参数从数据库查询完整数据,并将最后JavaBean对象返回,这样数据就会完整,另
一种方式是无返回值方法,可以参参数列表定义一个map集合,将最后的JavaBean放入map集合中,在对应的请求方法的
参数列表中也用ModelAttribute注解标注参数,并在注解中给出放入map集合的key
注解语法糖
在spring4.2.x版本及以后出现了复合注解
@GetMapping("/")
@PostMapping
直接指明请求方式
@RestController
@Controller和@ResponseBody的符合注解
参数绑定
默认参数绑定
request
response
session
ModelMap
基本数据类型
在对应方法的参数列表中定义请求参数
类型写你需要的,底层会帮你转,要求参数列表中的参数名与请求参数名一致
原理
mvc会反射你的方法参数列表,根据参数名去找请求参数对应的值,会尝试将数据转成你想要的类型,
如果不能转成你想要的,抛异常
如果不能转成你想要的,抛异常
bean方式
可以使用对象接收,在参数列表定义对象类型,mvc可以直接自动封装成对象,前提是对象的属性名跟请求参数名一致
绑定包装的bean
即对象中有对象引用,要求前端数据的name为bean中的bena名称.属性名,例如订单实体中有商品实体(pro),如果要绑定商品
id,则在前端需要将参数name定义为pro.id
id,则在前端需要将参数name定义为pro.id
数组绑定
一般用于批量删除,在前端定义复选框,复选框的名称相同且和控制类对应方法的数组名一致,springmvc可自动帮你获取参数
集合绑定
应用场景不多,一般用于批量修改,前端修改n条数据,提交多个对象到后台,但只能支持向对象中接收集合,即
控制类对应方法中需要定义一个集合,接收参数时会接收到该对象的集合中,而且要求前端name属性为集合名[下标].对象属性名
在jsp页面的c:foreach标签中的status属性可以获取遍历的集合的每次索引值
控制类对应方法中需要定义一个集合,接收参数时会接收到该对象的集合中,而且要求前端name属性为集合名[下标].对象属性名
在jsp页面的c:foreach标签中的status属性可以获取遍历的集合的每次索引值
注解方式
@RequestParam注解,标记参数列表
注解属性
value/name
指明要获取的参数名,用于跟请求参数名匹配
required
默认为true,要求请求参数必须有,如果没有,则出现400,设为false则可以没有
defaultValue
用于定义参数列表的默认值,如果请求参数没有传来,则默认值生效
自定义转换器
当前端参数出现springmvc无法自动转换的参数时,例如时间,可以使用自定义转换器
步骤
创建一个类,实现Converter<T, V>,T:源,V:目标,即需要将什么类型转换为什么类型
实现convert(T t)方法并返回想要的
将自定义转换器配置到springmvc容器中
在注册新版处理器映射器,处理器适配器驱动时,将自定义转换器配置
<mvc:annotation-driven conversion-service="自定义转换器id"/>
<mvc:annotation-driven conversion-service="自定义转换器id"/>
配置自定义转换器
<bean id="" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="convers">
<set><bean class="自己定义的转换器类的全限定名"/></set>
</property>
</bean>
<bean id="" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="convers">
<set><bean class="自己定义的转换器类的全限定名"/></set>
</property>
</bean>
注解方式解决mvc不支持的参数绑定
将spring不支持的绑定类型参数上用@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
springmvc如何响应
返回String类型的地址
在方法中直接return页面地址默认就是请求转发
在返回的页面地址字符串前加redirect:则为重定向
请求转发携带的参数需要放到ModelMap中
例如
配置视图解析器
在spring配置文件中配置前缀和后缀
配置语法
将配置文件的前缀和后缀与控制类中方法return的字符串拼接即可得到想要的路径
拦截器
框架提供的有跟过滤器功能类似但更强大的拦截器
拦截器会拦截Controller类中方法的调用
在controller类中方法执行前被拦截
在controller类的方法执行之后但在视图解析前被拦截
方法执行完且视图解析之后拦截
快速入门
1. 定义一个类实现HandlerInterceptor接口
2. 实现该接口中的方法,所有的方法
返回值为boolean,真放行,假拦截
返回值为boolean,真放行,假拦截
该接口中的方法为默认方法,每个方法都有不同的拦截时机
preHandle(req,resp)
在controller的方法被调用之前执行该方法
postHandle(req, resp)
在方法被调用视图解析之前调用
afterCompletion(req, resp)
在方法执行完视图解析之后调用
3. 在配置文件中配置拦截器,可以配置多个拦截器,
哪个在上边,最先执行哪个拦截器
哪个在上边,最先执行哪个拦截器
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置哪个方法需要拦截 -->
<mvc:mapping path="/**">
<!-- 配置哪个方法不需要拦截 -->
<mvc:exclued-mapping path="">
<!-- 设置拦截器类路径 -->
<bean class="拦截器类全限定名">
</mvc:interceptor>
</mvc:interceptors>
<mvc:interceptor>
<!-- 配置哪个方法需要拦截 -->
<mvc:mapping path="/**">
<!-- 配置哪个方法不需要拦截 -->
<mvc:exclued-mapping path="">
<!-- 设置拦截器类路径 -->
<bean class="拦截器类全限定名">
</mvc:interceptor>
</mvc:interceptors>
执行顺序
两个兰拦截器,1拦截器配置在前,2拦截器配置在后
文件上传
springmvc文件上传原理
浏览器通过input标签将需要上传的文件自动读入到内存,当提交表单的时候,会将该文件发送到后台核心控制器,在请求中
会携带这个文件,此时会调用到文件解析器,文件解析器会解析请求对象,将请求对象的文件解析出来返回给核心控制器
会携带这个文件,此时会调用到文件解析器,文件解析器会解析请求对象,将请求对象的文件解析出来返回给核心控制器
核心控制器再调用处理器映射器,找到相应的控制类的方法,通过参数绑定的形式,绑定给该方法,该方法的参数类型必须
是MultipartFile类型,参数名必须要和input标签中的name属性保持一致,最后调用该MultipartFile对象的方法进行上传
是MultipartFile类型,参数名必须要和input标签中的name属性保持一致,最后调用该MultipartFile对象的方法进行上传
文件解析器配置
前后端要求
页面要求
传统表单方式
1. 表单提交方式一定是post
2. 表单的enctype的值一定是multipart/form-data
3. input的type一定是file
ajax方式
1. type:post
2. data:FormData
3. processData: false
4. contentType: false,
springmvc要求
1. 需要两个jar包commons-io.jar和commons-fileupload.jar
2. 在ppringmvc配置文件中配置文件解析器
3. 绑定参数类型一定为MultipartFile,参数名字要和input的name属性的值保持一致
springmvc和struts2优劣
相同点
都基于mvc设计模式
底层都是对ServletAPI的封装
处理请求的机制都是一个核心控制器
区别
springmvc的入口是Servlet,struts2的入口是Filter
springmvc的最小单元是方法,是基于方法设计的,struts2的最小单元是基于类,每次执行都会创建一个动作类,所以mvc更快
springmvc使用更简洁,发送ajax更方便
s2的OGNL表达式使页面开发效率更高,但执行效率没有并没有比JSTL有所提升
spring事务管理
API方式/硬编码
PlatformTransactionManager 平台事务管理器 是一个接口
定义了开启事务、提交事务、回滚的方法
定义了开启事务、提交事务、回滚的方法
我们使用DataSourceTransactionManager这一实现类 主要针对
dbutils和jdbcTemplate 对jdbc的封装这个实现类就是一个切面类
dbutils和jdbcTemplate 对jdbc的封装这个实现类就是一个切面类
TransactionDefinition:定义事务参数的接口
事务的隔离级别
事务的超时时间
事务的是否只读
事务的传播行为
TransactionStatus:事务运行状态接口
查看当前事务是否完成
查看是否为新事务
查看是否回滚
声明式/配置文件式
通过配置文件告诉spring,让spring去使用事务控制,这种配置文件的方式实际上是对API的封装
jar包
事务包spring-tx.jar
事务依赖包
AOP联盟
aspectj.jar
spring-aspects.jar
步骤
确定切面类即配置
事务管理器
事务管理器
用<bean>标签配置DataSourceTransactionManager类,
该类需要一个数据源用ref属性配置
该类需要一个数据源用ref属性配置
<bean id="事务管理器名" class="事务类全路径">
<property name="" ref="bean标签中的数据源">
</bean>
<property name="" ref="bean标签中的数据源">
</bean>
细节:需要为事务配置一些事务参数:是否只读、超时时间、传播行为(标签)
用<tx:advice transaction-manager="bean标签中配置的平台事务管理器">标签配置,
必须有这个标签进行配置,事务参数可以不写,不写就为默认值
必须有这个标签进行配置,事务参数可以不写,不写就为默认值
配置声明事务即切面
<tx:advice id="事务名" transaction-manager="需要的事务管理器名">
<tx:attributes>
<!-- 需要进行事务管理的方法 -->
<tx:method name="方法名"/>
</tx:attributes>
</tx:advice>
<tx:attributes>
<!-- 需要进行事务管理的方法 -->
<tx:method name="方法名"/>
</tx:attributes>
</tx:advice>
配置织入
用<aop:advisor>标签配置切面类,用<aop:pointcut>标签配置切点
用事务作为切点
注解
spring整合junit
在spring下junit的问题
程序的入口为main
junit单元测试中没有main方法也能执行
junit内部集成了一个main方法
当执行时,会利用反射判断该测试类有没有被@Test标注的方法
如果有,.invoke执行该方法
junit不会管我们是否用框架
在执行测试方法的时候,junit根本不知道我们是否使用了框架,所以在执行的时候根本不会为我们通过配置文件或者
配置类来创建spring容器
配置类来创建spring容器
所以,在用junit测试的时候根本没有ioc容器,就算使用Autowired方法也不会有效果
整合思路
导入spring整合junit的jar包--->spring-test.jar
使用junit提供的一个注解,把原有的main方法替换了,替换成spring自己的main
@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringJUnit4ClassRunner.class)
告知spring运行器,spring和ioc创建是基于xml还是注解,并说明位置
用@ContextConfiguration--->locations属性:指定xml文件位置,加上classpath关键字,表示该文件在类路径下
classes属性:指定配置类所在位置
用@ContextConfiguration--->locations属性:指定xml文件位置,加上classpath关键字,表示该文件在类路径下
classes属性:指定配置类所在位置
当我们用spring5.x版本的时候,要求junit版本在4.12及以上版本
开发模式
jsp开发模式
开发效率较高
执行效率与交互效果低
每次请求都是整个页面刷新,当页面数据量大,用户设备老旧或者网速较差,会出现页面卡顿问题
以至于交互效果较差
以至于交互效果较差
不灵活,解决多端变化问题较难
如果有多个前端页面例如手机版、电脑版、iPad版,那得写多套控制层,较难
前后端分离
后台一律响应数据(json格式)而不响应页面,前端利用前端语言和后台的网络接口进行接收数据和显示
优点
灵活,易于解决多端变化问题
只需要写一套后台,不同前端用不同方式与后台交互
缺点
开发效率较低
前后端分离开发模式开发前需要先设计文档,规定后台与前端所需要接口和参数的标准格式,以便于前后端同时开发且
不容易出现前端调用后台接口出问题的情况
不容易出现前端调用后台接口出问题的情况
跨域问题
跨域带数据
跨域带数据
同源策略
同源
协议相同、ip相同、端口号相同
DOM 同源策略:禁止对不同源页面 DOM 进行操作。
这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
做一个假网站,里面用 iframe 嵌套一个银行网站 http://mybank.com。
把 iframe 宽高啥的调整到页面全部,这样用户进来除了域名,
别的部分和银行的网站没有任何差别。
别的部分和银行的网站没有任何差别。
这时如果用户输入账号密码,我们的主网站可以跨域访问到
http://mybank.com 的 dom 节点,就可以拿到用户的账户密码了。
http://mybank.com 的 dom 节点,就可以拿到用户的账户密码了。
XMLHttpRequest 同源策略:
禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。
禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。
在不同源情况下,一个服务器向另一个服务器发送ajax
请求,浏览器默认是禁止的,,会产生跨域错误
请求,浏览器默认是禁止的,,会产生跨域错误
解决方案
1. 设置后台允许接受跨域请求
在后端设置响应头
response.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
该服务器路径可以通过请求对象动态获取
request.getHeader("Origin")
或者通过注解设置
在每个Controller类上加@CrossOrigin注解,该注解允许请求服务器默认为*
但是当前端设置为允许跨域携带参数后不允许将跨域访问路径设为*,虽然该注解可以设置路径,但需要在每个注解中设置
跨域请求服务器路径,所以该方式不太方便
跨域请求服务器路径,所以该方式不太方便
通过拦截器设置
在mvc.xml配置文件中配置拦截器
将该拦截器设置在所有拦截器的最上方,所有请求来之后都先被该拦截器拦截
在拦截器类中为response设置响应头
response.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
2. 设置前端允许跨域请求携带数据
在前端页面设置xhr对象的属性
在ajax请求中设置属性
xhrFields:{
withCredentials:true
},
withCredentials:true
},
XHR原生对象的withCredentials是用于跨域请求的,默认为false
如果想要跨域请求并携带数据则需要将其打开
如果想要跨域请求并携带数据则需要将其打开
***在这种可携带数据的跨域模式下不可以设置为*
3. 后台允许跨域请求携带数据
在拦截器类中设置响应头
response.setHeader("Access-Control-Allow-Credentials", "true");
ssm整合
在web.xml中配置
配置核心控制器
核心控制器路径,此处的url-pattern如果是/则指的是除jsp文件以外的所有请求都包含,/*则包含jsp
核心控制器创建时机
核心控制器需要的配置文件
配置监听器
当服务器启动时,该监听器会创建spring容器对象
配置全局参数
该参数指向spring配置文件(该配置文件用于整合spring、mybatis),监听器会加载该配置文件,将配置文件
中的数据源、对象以及mapper扫描器创建
中的数据源、对象以及mapper扫描器创建
持久层(dao)
mybatis.xml(可有可无),一般在该文件下配置settings和typeAliases,不过在配置sqlFactoryFactoryBean时也可以配置别名
applicationContext-dao.xml
数据源(druid)
sqlSessionFactory
数据源
别名
<property name="typeAliasesPackage" value="com.wxs.entity">
配置mapper扫描器
在配置sqlSession工厂时,通过property标签,让name值为mapperLocations
value值为classpath:com/wxs/mapper,这里需要使用斜线
value值为classpath:com/wxs/mapper,这里需要使用斜线
用这种方式可以扫描项目下任意路径,可以解决mapper映射器文件和接口不在同意路径下的问题
mapper扫描器
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
在该bean标签下配置sqlSessionFactoryBean,因为mapper接口的底层还是需要由sqlSession得到的
配置需要扫描的包
业务层
applicationContext-service.xml
事务
包扫描器(主要针对@Service注解)
web层(有mvc支持)
springmvc.xml
注解驱动版本
<mvc:annotation-driven/>
配置处理器适配器、处理器映射器最新驱动
包扫描器,主要针对@Controller注解
视图解析器
以setter方式注入前缀和后缀
异常处理器,文件解析器,拦截器
***父子容器关系
spring容器(配置文件)与springmvc容器(配置文件)是父子容器关系
在这两个容器中都只能出现一个<context:property-placeholder location="">
标签加载文件,且子容器可以访问父容器加载到的配置文件,而父容器不能访问子容器加载的文件
在这两个容器中都只能出现一个<context:property-placeholder location="">
标签加载文件,且子容器可以访问父容器加载到的配置文件,而父容器不能访问子容器加载的文件
0 条评论
下一页