Skip to content

Commit 42e2cc8

Browse files
committed
sping-mvc:session同步
1 parent ce9e4bc commit 42e2cc8

File tree

4 files changed

+350
-7
lines changed

4 files changed

+350
-7
lines changed

note/images/MappedInterceptor.jpg

32.8 KB
Loading
6.61 KB
Loading

note/spring-mvc.md

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ initFlashMapManager方法会向容器注册SessionFlashMapManager对象,类图
417417

418418
![RequestMappingHandlerMapping类图](images/RequestMappingHandlerMapping.jpg)
419419

420-
初始化的入口位于AbstractHandlerMethodMapping的afterPropertiesSet方法,afterPropertiesSet调用了initHandlerMethods:
420+
初始化的入口位于AbstractHandlerMethodMapping的afterPropertiesSet方法和AbstractHandlerMapping的initApplicationContext方法,afterPropertiesSet调用了initHandlerMethods:
421421

422422
```java
423423
protected void initHandlerMethods() {
@@ -523,6 +523,21 @@ Cors的原理可以参考:
523523

524524
而initCorsConfiguration方法的作用便是将@CrossOrigin注解的各种属性封装在CorsConfiguration中。
525525

526+
#### 拦截器初始化
527+
528+
AbstractHandlerMapping.initApplicationContext:
529+
530+
```java
531+
@Override
532+
protected void initApplicationContext() throws BeansException {
533+
detectMappedInterceptors(this.adaptedInterceptors);
534+
}
535+
```
536+
537+
作用就是从容器中获取所有MappedInterceptor bean并放到adaptedInterceptors中,前面提到过了,我们使用mvc:interceptor定义的拦截器其实就是MappedInterceptor对象。类图:
538+
539+
![MappedInterceptor类图](images/MappedInterceptor.jpg)
540+
526541
## HandlerAdapter初始化
527542

528543
同样,我们以RequestMappingHandlerAdapter为例进行说明,类图:
@@ -653,6 +668,7 @@ AbstractHandlerMapping.getHandler:
653668
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
654669
Object handler = getHandlerInternal(request);
655670
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
671+
//判断请求头中是否有ORIGIN字段
656672
if (CorsUtils.isCorsRequest(request)) {
657673
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
658674
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
@@ -664,4 +680,65 @@ public final HandlerExecutionChain getHandler(HttpServletRequest request) throws
664680
}
665681
```
666682

667-
getHandlerInternal方法便是根据url进行查找的过程,可以参见MVC初始化-HandlerMapping初始化一节。下面重点是执行链的生成。
683+
getHandlerInternal方法便是根据url进行查找的过程,可以参见MVC初始化-HandlerMapping初始化一节。下面重点是执行链的生成。
684+
685+
getHandlerExecutionChain方法的原理就是从adaptedInterceptors中获得所有可以适配当前请求URL的MappedInterceptor并将其添加到HandlerExecutionChain的拦截器列表中。拦截器的顺序其实就是我们定义/注册的顺序。
686+
687+
从getCorsHandlerExecutionChain的源码中可以看出,对于跨域请求其实是向调用链插入了一个CorsInterceptor。
688+
689+
### 适配器查找
690+
691+
DispatcherServlet.getHandlerAdapter:
692+
693+
```java
694+
protected HandlerAdapter getHandlerAdapter(Object handler) {
695+
for (HandlerAdapter ha : this.handlerAdapters) {
696+
if (ha.supports(handler)) {
697+
return ha;
698+
}
699+
}
700+
}
701+
```
702+
703+
从前面配置解析-注解驱动可以看出,第一个适配器是RequestMappingHandlerAdapter,而其support方法直接返回true,这就导致了使用的适配器总是这一个。
704+
705+
## 请求处理
706+
707+
RequestMappingHandlerAdapter.handleInternal:
708+
709+
```java
710+
@Override
711+
protected ModelAndView handleInternal(HttpServletRequest request,
712+
HttpServletResponse response, HandlerMethod handlerMethod){
713+
ModelAndView mav;
714+
// Execute invokeHandlerMethod in synchronized block if required.
715+
if (this.synchronizeOnSession) {
716+
HttpSession session = request.getSession(false);
717+
if (session != null) {
718+
Object mutex = WebUtils.getSessionMutex(session);
719+
synchronized (mutex) {
720+
mav = invokeHandlerMethod(request, response, handlerMethod);
721+
}
722+
} else {
723+
// No HttpSession available -> no mutex necessary
724+
mav = invokeHandlerMethod(request, response, handlerMethod);
725+
}
726+
} else {
727+
// No synchronization on session demanded at all...
728+
mav = invokeHandlerMethod(request, response, handlerMethod);
729+
}
730+
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
731+
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
732+
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
733+
}
734+
else {
735+
prepareResponse(response);
736+
}
737+
}
738+
return mav;
739+
}
740+
```
741+
742+
### Session同步
743+
744+
可以看出,如果开启了synchronizeOnSession,那么**同一个session的请求将会串行执行**,这一选项默认是关闭的,当然我们可以通过注入的方式进行改变。

0 commit comments

Comments
 (0)