激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - SpringMVC源碼解讀之HandlerMapping

SpringMVC源碼解讀之HandlerMapping

2020-04-03 14:50出門向左 JAVA教程

這篇文章主要介紹了SpringMVC源碼解讀之HandlerMapping 的相關(guān)資料,需要的朋友可以參考下

概述

對(duì)于Web開(kāi)發(fā)者,MVC模型是大家再熟悉不過(guò)的了,SpringMVC中,滿足條件的請(qǐng)求進(jìn)入到負(fù)責(zé)請(qǐng)求分發(fā)的DispatcherServlet,DispatcherServlet根據(jù)請(qǐng)求url到控制器的映射(HandlerMapping中保存),HandlerMapping最終返回HandlerExecutionChain,其中包含了具體的處理對(duì)象handler(也即我們編程時(shí)寫的controller)以及一系列的攔截器interceptors,此時(shí)DispatcherServlet會(huì)根據(jù)返回的HandlerExecutionChain中的handler找到支持這一處理器類型的適配器(handlerAdapter),在處理器適配器中最終會(huì)去調(diào)用控制器的請(qǐng)求響應(yīng)方法并返回結(jié)果視圖(ModelAndView),得到結(jié)果視圖后,通過(guò)render方法完成結(jié)果的顯示。

HanderMapping的繼承體系:

SpringMVC源碼解讀之HandlerMapping

SpringMVC在請(qǐng)求到handler處理器的分發(fā)這步是通過(guò)HandlerMapping模塊解決的.handlerMapping 還處理攔截器.

先看看HandlerMapping的繼承樹(shù)吧

SpringMVC源碼解讀之HandlerMapping

可以大致這樣做個(gè)分類:

  1. 一個(gè)接口HandlerMapping,定義一個(gè)api: HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

  2. 一個(gè)基礎(chǔ)抽象類:主要是準(zhǔn)備上下文環(huán)境,提供getHandlerInternal鉤子,封裝攔截器到HandlerExecutionChain

  3. 基于注解@Controller,@RequestMapping的使用

  4. 配置文件中直接配置url到 handler的SimpleUrlHandlerMapping

  5. 默認(rèn)實(shí)現(xiàn)BeanNameUrlHandlerMapping

  6. Controller子類的映射

看看HandlerMapping吧,就一個(gè)getHandler api 非常簡(jiǎn)單.

?
1
2
3
4
5
// HandlerMapping
package org.springframework.web.servlet;
public interface HandlerMapping {
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

AbstractHandlerMapping就沒(méi)有這么簡(jiǎn)單了

先看AbstractHandlerMapping繼承的類,實(shí)現(xiàn)的接口

?
1
2
3
4
5
package org.springframework.web.servlet.handler;
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered {
// ...
}

WebApplicationObjectSupport用于提供上下文ApplicationContext和ServletContext.

  還有這邊的initApplicationContext方法,在后續(xù)經(jīng)常會(huì)使用到.AbstractHandlerMapping就直接覆寫了.

  父類里還是實(shí)現(xiàn)了ApplicationContextAware和ServletContextAware接口,spring概念很統(tǒng)一.

Ordered用于集合排序.

再接著看AbstractHandlerMapping的屬性吧

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// AbstractHandlerMapping
// order賦了最大值,優(yōu)先級(jí)是最小的
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
// 默認(rèn)的Handler,這邊使用的Obejct,子類實(shí)現(xiàn)的時(shí)候,使用HandlerMethod,HandlerExecutionChain等
private Object defaultHandler;
// url計(jì)算的輔助類
private UrlPathHelper urlPathHelper = new UrlPathHelper();
// 基于ant進(jìn)行path匹配,解決如/books/{id}場(chǎng)景
private PathMatcher pathMatcher = new AntPathMatcher();
// 攔截器配置:,HandlerMapping屬性設(shè)置;,extendInterceptors設(shè)置
private final List<Object> interceptors = new ArrayList<Object>();
// 從interceptors中解析得到,直接添加給全部handler
private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<HandlerInterceptor>();
// 使用前需要跟url進(jìn)行匹配,匹配通過(guò)才會(huì)使用
private final List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();

看下攔截器的初始化:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// AbstractHandlerMapping
@Override
protected void initApplicationContext() throws BeansException {
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);
initInterceptors();
}
/**
* 提供給子類擴(kuò)展攔截器,可惜都沒(méi)有使用
*/
protected void extendInterceptors(List<Object> interceptors) {
}
/**
* 掃描應(yīng)用下的MappedInterceptor,并添加到mappedInterceptors
*/
protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
getApplicationContext(),MappedInterceptor.class, true, false).values());
}
/**
* 歸集MappedInterceptor,并適配HandlerInterceptor和WebRequestInterceptor
*/
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
for (int i = ; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
if (interceptor == null) {
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
if (interceptor instanceof MappedInterceptor) {
mappedInterceptors.add((MappedInterceptor) interceptor);
}
else {
adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
}
protected HandlerInterceptor adaptInterceptor(Object interceptor) {
if (interceptor instanceof HandlerInterceptor) {
return (HandlerInterceptor) interceptor;
}
else if (interceptor instanceof WebRequestInterceptor) {
return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
}
else {
throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
}
}

然后是getHandler(HttpServletRequest request)的實(shí)現(xiàn),這邊同時(shí)預(yù)留getHandlerInternal(HttpServletRequest request)給子類實(shí)現(xiàn)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// AbstractHandlerMapping
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
return getHandlerExecutionChain(handler, request);
}
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

最后是封裝攔截器到HandlerExecutionChain

  adaptedInterceptors直接添加

  mappedInterceptors需要根據(jù)url匹配通過(guò)后添加

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// AbstractHandlerMapping
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain =
(handler instanceof HandlerExecutionChain) ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
chain.addInterceptors(getAdaptedInterceptors());
String lookupPath = urlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}

Controller子類的映射,這一分支先看類繼承

SpringMVC源碼解讀之HandlerMapping

我們來(lái)說(shuō)說(shuō),這邊每個(gè)類主要的職責(zé)

  1. AbstractHandlerMapping 準(zhǔn)備上下文環(huán)境;提供getHandlerInternal鉤子;封裝攔截器到HandlerExecutionChain

  2. AbstractUrlHandlerMapping 實(shí)現(xiàn)注冊(cè)handler的方法供子類使用;實(shí)現(xiàn)getHandlerInternal,根據(jù)子類初始化的配置信息,查找handler

  3. AbstractDetectingUrlHandlerMapping 掃描應(yīng)用下的Object,迭代后提供鉤子方法determineUrlsForHandler由子類決定如何過(guò)濾

  4. AbstractControllerUrlHandlerMapping 實(shí)現(xiàn)determineUrlsForHandler,添加過(guò)濾排除的handler操作(配置文件配置),預(yù)留鉤子方法buildUrlsForHandler給子類實(shí)現(xiàn);同時(shí)判斷controller的子類

  5. ControllerBeanNameHandlerMapping 根據(jù)bean name生成url

    ControllerClassNameHandlerMapping根據(jù)class name生成url

從AbstractUrlHandlerMapping開(kāi)始看吧,這邊只是大致看下代碼,如果需要仔細(xì)分析,請(qǐng)移步<SpringMVC源碼解讀 - HandlerMapping - AbstractUrlHandlerMapping系列request分發(fā)>

handler的注冊(cè)

?
1
2
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException { }
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { }

handler的查找

?
1
2
3
4
5
6
7
8
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {}
// 根據(jù)url查找handler
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {}
// 校驗(yàn)handler
protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {}
// 封裝攔截器到HandlerExecutionChain
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
String pathWithinMapping, Map<String, String> uriTemplateVariables) {}

AbstractDetectingUrlHandlerMapping,這邊一樣不展開(kāi),具體移步<SpringMVC源碼解讀 - HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化>

具體做的事情:

  1. 通過(guò)覆寫initApplicationContext,調(diào)用detectHandlers掃描Obejct

  2. 提供鉤子方法determineUrlsForHandler給子類根據(jù)handler生成url

  3. 調(diào)用父類的registerHandler進(jìn)行注冊(cè)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
detectHandlers();
}
protected void detectHandlers() throws BeansException {
// ...
}
/**
* Determine the URLs for the given handler bean.
* 鉤子而已
*/
protected abstract String[] determineUrlsForHandler(String beanName);
 
AbstractControllerUrlHandlerMapping,這邊一樣不展開(kāi),具體移步<SpringMVC源碼解讀 - HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化>

具體做的事情;

  1. 覆寫determineUrlsForHandler添加剔除部分類的邏輯,通過(guò)配置文件配置的excludedClasses和excludedPackages在這邊使用

  2. 判斷是否controller的子類

  3. 預(yù)留buildUrlsForHandler給子類生成url

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
protected String[] determineUrlsForHandler(String beanName) {
Class beanClass = getApplicationContext().getType(beanName);
if (isEligibleForMapping(beanName, beanClass)) {
return buildUrlsForHandler(beanName, beanClass);
}
else {
return null;
}
}
protected boolean isEligibleForMapping(String beanName, Class beanClass) {}
protected boolean isControllerType(Class beanClass) {}
protected abstract String[] buildUrlsForHandler(String beanName, Class beanClass);
 
ControllerBeanNameHandlerMapping和ControllerClassNameHandlerMapping 直接看源碼吧,或者移步<SpringMVC源碼解讀 - HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化>

配置文件中直接配置url到 handler的SimpleUrlHandlerMapping,就是使用registerHandlers注冊(cè)配置文檔中的handler,直接看代碼或者移步<SpringMVC源碼解讀 - HandlerMapping - SimpleUrlHandlerMapping初始化>吧

BeanNameUrlHandlerMapping 實(shí)現(xiàn)determineUrlsForHandler生成url,直接看代碼或者移步<SpringMVC源碼解讀 - HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化>吧

基于注解@Controller,@RequestMapping的使用

最難吭的骨頭

先看類繼承吧

SpringMVC源碼解讀之HandlerMapping

說(shuō)下各個(gè)類的職責(zé)吧,具體的分析還是移步下面的文章

<SpringMVC源碼解讀 - HandlerMapping - RequestMappingHandlerMapping初始化>

<SpringMVC源碼解讀 - HandlerMapping - RequestMappingHandlerMapping請(qǐng)求分發(fā)>

  1. AbstractHandlerMethodMaping 定義初始化流程,請(qǐng)求時(shí)如何映射

  初始化:

    1.1.1 掃描應(yīng)用下的Object

    1.1.2 預(yù)留isHandler鉤子方法給子類判斷Object是否handler

    1.1.3 迭代掃描每一個(gè)handler,找出符合要求的方法,這邊判斷依然是留給子類實(shí)現(xiàn)getMappingForMethod

    1.1.4 注冊(cè)查找到的處理器,需要確保一個(gè)匹配條件RequestMappingInfo只能映射到一個(gè)handler

    1.1.5 根據(jù)匹配條件獲取url,同樣的只是定義流程,具體的算法留給子類實(shí)現(xiàn)getMappingPathPatterns

  請(qǐng)求request分發(fā)處理:

    1.2.1 直接字符串匹配的方式,查找handler 

    1.2.2 匹配條件查找,這邊具體的算法交由子類處理getMatchingMapping

    1.2.3 排序并獲取最佳匹配handler,這邊的排序方式還是子類處理getMappingConmparator

   1.2.4 分別封裝匹配到和未匹配到handler的情況

  2. RequestMappingInfoHandlerMapping使用RequestMappingInfo實(shí)現(xiàn)匹配條件,RequestMappingInfo的初始化留給子類

    2.1 根據(jù)RequestMappingInfo生成url ->getMappingPathPatterns

    2.2 使用匹配條件查找Handler -> getMatchingMapping

    2.3 完成比較器算法 -> getMappingComparator

    2.4 覆寫handleMatch,緩存n多信息到request

      注冊(cè)pattern,最佳匹配的pattern,url中解析出來(lái)的參數(shù),url中解析出來(lái)的多值參數(shù),mediaType

    2.1.5 覆寫handlerNoMatch,最后的掙扎,再嘗試匹配一次

  3. RequestMappingHandlerMapping 根據(jù)注解@Controller @RequestMapping生成RequestMappingInfo,并校驗(yàn)isHandler

    3.1 覆寫afterPropertiesSet,添加文件后綴判斷

    3.2 實(shí)現(xiàn)isHandler,類上有@Controller @RequestMapping其中一個(gè)注解就對(duì)

    3.3 解析注解內(nèi)容,生產(chǎn)RequestMappingInfo實(shí)例

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲一区二区在线 | 操操插插| xxxxhdhdhdhd日本| 久久久久久久99 | 国产毛片毛片 | 91在线免费观看 | 黄色影院一级片 | 亚洲成人国产 | 精品久久久久久久久久久aⅴ | 黄网站在线免费 | 欧美日韩亚洲不卡 | 性盈盈盈影院 | 极品五月天 | 久久新地址 | 黄在线观看在线播放720p | 制服下着マ○コ航空5 | 久久中文字幕在线观看 | 久久福利在线 | 一区二区三区欧美在线 | 国产做爰全免费的视频黑人 | 成人毛片100部免费观看 | av在线直播观看 | 精品一区二区视频在线观看 | 主人在调教室性调教女仆游戏 | 精品国产一区二区三区久久久蜜 | 亚洲视频黄 | 国产精品成人亚洲一区二区 | 一本到免费视频 | 亚洲日本韩国精品 | 成人福利视频网站 | 亚洲一区二区观看播放 | 羞羞羞网站 | 精品一区二区中文字幕 | 久久综合狠狠综合久久 | 国产男女 爽爽爽爽视频 | 欧美成人免费在线视频 | 久久精品美乳 | 欧美日韩在线中文 | 久久人人做 | 亚洲成人免费电影 | 99精品视频久久精品视频 |