国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

SpringMVC處理流程非常詳細(xì)的講解

開發(fā) 前端
通過HandlerMapping找到了相應(yīng)的HandlerMethod對(duì)象,最后封裝到了HandlerExecutionChain中,接下來就是根據(jù)HandlerMethod查找合適的HandlerAdapter處理程序。

1 請(qǐng)求入口

public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerExecutionChain mappedHandler = null;
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 2.1.通過HandlerMapping獲取請(qǐng)求處理鏈,該對(duì)象由處理程序(Controller,一般HandlerMethod對(duì)象)及攔截器(Interceptor)組成
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2.2.根據(jù)2.1獲取的處理程序(HandlerMethod)對(duì)象確定能夠處理該處理程序的HandlerAdapter對(duì)象
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// ...
// 2.3.執(zhí)行處理程序之前,執(zhí)行攔截器preHandle方法,如果返回了false,本次請(qǐng)求將被終止
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// 2.4.真正的執(zhí)行處理程序
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// ...
// 2.5.執(zhí)行處理程序之后,執(zhí)行攔截器postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 2.6.處理結(jié)果,根據(jù)處理程序是否發(fā)生異常,是否返回有ModelAndView對(duì)象進(jìn)行結(jié)果的處理
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
// ...
}
}

2 處理請(qǐng)求

2.1 獲取請(qǐng)求處理鏈

該步驟通過HandlerMapping獲取HandlerExecutionChain處理器執(zhí)行鏈。

public class DispatcherServlet {
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
// 遍歷當(dāng)前容器中注冊(cè)的所有HandlerMapping對(duì)象
for (HandlerMapping mapping : this.handlerMappings) {
// 針對(duì)Controller接口,使用的是RequestMappingHandlerMapping對(duì)象
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
}

這里以RequestMappingHandlerMapping為例

mapping.getHandler(request)方法調(diào)用流程如下:

public abstract class AbstractHandlerMapping {
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 調(diào)用子類實(shí)現(xiàn)的getHandlerInternal方法
Object handler = getHandlerInternal(request);
// ...
// 根據(jù)查找到的處理程序封裝到處理程序執(zhí)行鏈
// 這里會(huì)將攔截器也添加其中
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
// ...這里是跨域相關(guān)的配置
return executionChain;
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(request)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
}

調(diào)用子類RequestMappingInfoHandlerMapping#getHandlerInternal實(shí)現(xiàn)。

public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> {
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
try {
// 又調(diào)父類的實(shí)現(xiàn) (⊙o⊙)…
return super.getHandlerInternal(request);
}
}
}

調(diào)用父類AbstractHandlerMethodMapping#getHandlerInternal方法

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
private final MappingRegistry mappingRegistry = new MappingRegistry();
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 根據(jù)當(dāng)前的請(qǐng)求獲取請(qǐng)求的uri
String lookupPath = initLookupPath(request);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
}
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 系統(tǒng)啟動(dòng)時(shí)初始化RequestMappingHandlerMapping解析了整個(gè)系統(tǒng)中所有的Controller然后注冊(cè)到MappingRegistry中
// 根據(jù)當(dāng)前的請(qǐng)求uri,對(duì)應(yīng)List<RequestMappingInfo>對(duì)象,相同的uri可能對(duì)應(yīng)不同的request method,所以這里返回的是List集合
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
if (directPathMatches != null) {
// 該方法內(nèi)部會(huì)根據(jù)找到的RequestMappingInfo進(jìn)行遍歷,根據(jù)請(qǐng)求信息逐個(gè)的判斷對(duì)應(yīng)@RequestMapping配置的屬性是否匹配
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
}
// 下面if的邏輯就是判斷如果找到了匹配并且存在多個(gè)會(huì)找出最合適的
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
bestMatch = matches.get(0);
if (CorsUtils.isPreFlightRequest(request)) {
for (Match match : matches) {
if (match.hasCorsConfig()) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
}
} else {
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.getHandlerMethod().getMethod();
Method m2 = secondBestMatch.getHandlerMethod().getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
// 將當(dāng)前請(qǐng)求uri保存到request對(duì)象中setAttribute
handleMatch(bestMatch.mapping, lookupPath, request);
// 返回當(dāng)前uri對(duì)應(yīng)的HandlerMethod對(duì)象
return bestMatch.getHandlerMethod();
}
}
protected void handleMatch(T mapping, String lookupPath, HttpServletRequest request) {
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath);
}
}

2.2 獲取HandlerAdapter

在上一步中通過HandlerMapping找到了相應(yīng)的HandlerMethod對(duì)象,最后封裝到了HandlerExecutionChain中,接下來就是根據(jù)HandlerMethod查找合適的HandlerAdapter處理程序。

public class DispatcherServlet {
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
// 這里的參數(shù)handler一般都是HandlerMethod對(duì)象
for (HandlerAdapter adapter : this.handlerAdapters) {
// 這個(gè)根據(jù)handler判斷哪個(gè)HandlerAdapter支持,一般都是RequestMappingHandlerAdapter
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
}

RequestMappingHandlerAdapter 這調(diào)用的是父類方法

public abstract class AbstractHandlerMethodAdapter {
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
}
public class RequestMappingHandlerAdapter {
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
}

2.3 執(zhí)行攔截器preHandle方法

在真正調(diào)用處理程序前,執(zhí)行攔截器preHandle方法

public class HandlerExecutionChain {
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
// 如果任何一個(gè)攔截器返回了false,本次請(qǐng)求都會(huì)被終止
if (!interceptor.preHandle(request, response, this.handler)) {
// 該攔截器的完成回調(diào)會(huì)被執(zhí)行
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
}

2.4 實(shí)際請(qǐng)求處理

public class DispatcherServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
}

AbstractHandlerMethodAdapter

public abstract class AbstractHandlerMethodAdapter {
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 子類重寫了該方法
return handleInternal(request, response, (HandlerMethod) handler);
}
}

RequestMappingHandlerAdapter

public class RequestMappingHandlerAdapter {
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
if (this.synchronizeOnSession) {
// ...
} else {
// No synchronization on session demanded at all...
// 執(zhí)行HandlerMethod調(diào)用
mav = invokeHandlerMethod(request, response, handlerMethod);
}
// ...
return mav;
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
// 創(chuàng)建數(shù)據(jù)綁定工廠,主要作用就是將請(qǐng)求的參數(shù)信息與Controller方法的參數(shù)進(jìn)行綁定(數(shù)據(jù)類型的轉(zhuǎn)換)及參數(shù)校驗(yàn)
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 處理@ModelAttribute和@SessionAttribute注解,它將做兩件事:
// 1.將@SessionAttribute注解的方法的相關(guān)數(shù)據(jù)合并到下面的ModelAndViewContainer中
// 2.將@ModelAttribute注解的方法返回值添加到ModelAndViewContainer中
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 實(shí)際HandlerMethod調(diào)用對(duì)象
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
// 設(shè)置參數(shù)解析器
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
// 設(shè)置Controller方法返回值的處理器
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
// 執(zhí)行上面說的兩個(gè)步驟
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// ...
// 執(zhí)行調(diào)用HandlerMethod
// 在這個(gè)過程中會(huì)應(yīng)用到參數(shù)解析器和返回值處理器,這里就不展開說了
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 這里會(huì)返回ModelAndView對(duì)象,這個(gè)根據(jù)情況,如果你是RestController,那么在通過返回值處理器就已經(jīng)將結(jié)果進(jìn)行了輸出如使用@ResponseBody注解的方法
// 如果是RestController,請(qǐng)求結(jié)果就提前輸出了,同時(shí)會(huì)將ModelAndViewContainer的requestHandled屬性設(shè)置為true。
return getModelAndView(mavContainer, modelFactory, webRequest);
} finally {
webRequest.requestCompleted();
}
}
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

modelFactory.updateModel(webRequest, mavContainer);
// 如果是@ResponseBody注解的方法,那么直接返回null
if (mavContainer.isRequestHandled()) {
return null;
}
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
// ...
return mav;
}
}

2.5 執(zhí)行攔截器postHandle方法

public class HandlerExecutionChain {
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
}

2.6 處理結(jié)果

public class DispatcherServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {

boolean errorView = false;

// 在處理過程中如果出現(xiàn)了異常會(huì)進(jìn)入這里進(jìn)行異常處理
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}

// 如果Controller方法返回有ModelAndView
if (mv != null && !mv.wasCleared()) {
// 進(jìn)行視圖的渲染輸出到客戶端
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}

if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}

// 如果是RestController接口,那么上面的代碼都不會(huì)執(zhí)行
if (mappedHandler != null) {
// 執(zhí)行攔截器的afterCompletion回調(diào)方法
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
}

責(zé)任編輯:武曉燕 來源: 實(shí)戰(zhàn)案例錦集
相關(guān)推薦

2011-06-17 13:39:47

Qt 文件

2011-06-17 13:18:17

Qt 文件

2023-03-08 08:54:59

SpringMVCJava

2010-05-10 15:09:03

Unix文件

2013-01-10 15:36:44

Android開發(fā)組件Intent

2009-04-03 08:21:37

AndroidGoogle移動(dòng)OS

2011-06-14 15:39:46

單元測(cè)試

2010-05-17 16:31:04

IIS Request

2010-01-06 09:40:07

Ubuntu時(shí)間設(shè)置

2010-04-29 10:15:01

Unix系統(tǒng)

2010-06-17 12:57:27

如何修復(fù)Grub

2009-09-25 17:03:29

Hibernate是什

2009-12-14 11:29:19

Linux查看命令

2009-12-03 16:39:09

phpCB批量轉(zhuǎn)換

2010-05-17 09:19:03

Subversion

2010-05-07 14:11:06

Unix--Tripw

2009-12-21 11:22:37

Linux網(wǎng)絡(luò)操作命令

2021-01-04 05:42:48

數(shù)倉模型設(shè)計(jì)

2011-07-06 10:32:07

Xcode

2009-06-04 10:33:10

struts vali框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

在线观看亚洲成人| 国产精品久久久久久久岛一牛影视| 久久国产精品久久久久久| 色老头视频在线观看| 国产精品久久看| 国产www免费| 九九**精品视频免费播放| 成人www视频在线观看| 日韩一级电影| 国外成人在线直播| 色综合久久久| 日韩中文字幕av| 在线观看福利电影| 欧美成人精品3d动漫h| 超碰人人在线| 日韩午夜激情av| 幼a在线观看| 欧美在线影院一区二区| 在线免费观看h| 一本一道久久a久久精品综合蜜臀| 91婷婷韩国| 亚洲精品乱码久久久久久 | 欧美aaa大片视频一二区| 亚洲经典中文字幕| 国产免费拔擦拔擦8x高清在线人| 91精品国产91久久综合桃花 | 91精品久久久久久久久不口人| 伦理一区二区| 日韩免费在线播放| 久操国产精品| 北条麻妃高清一区| 久久字幕精品一区| 波多野结衣与黑人| 国产欧美一区二区在线| 天堂资源av| 欧美日韩中文字幕一区| caoporn免费在线视频| 亚洲国产欧美一区二区丝袜黑人| 亚洲天堂导航| 久久国产精品首页| 国产伦一区二区三区| 国产日韩欧美成人| 亚洲一区二区伦理| 自拍视频一区二区三区| 91丨porny丨最新| 免费观看羞羞视频网站| 狠狠躁夜夜躁人人躁婷婷91 | 亚洲精品日韩专区silk| 免费在线视频你懂得| 欧美一区二区在线免费播放| 国模雨婷捆绑高清在线| 一个色综合导航| 91欧美极品| 成人综合av网| 精品一区二区久久| 国产精品区在线| 天天操天天干天天综合网| 成人黄视频在线观看| www.久久久久| 先锋资源久久| 特级黄色录像片| 亚洲欧美日本韩国| 福利在线视频网站| 久久成人在线视频| 黑人一区二区| 国产精品宾馆在线精品酒店| 亚洲风情在线资源站| 欧美成人免费在线观看| 一区二区三区在线资源| 亚洲aa中文字幕| 国产伦精品一区二区三区视频青涩| 成年人免费大片| 欧洲av在线精品| 精品国产亚洲一区二区三区在线| 成人国产精品久久久久久亚洲| 精品一区二区三区在线观看| 成人午夜激情| 亚洲激情中文字幕| 九九热爱视频精品视频| 一本一道久久a久久综合精品 | 免费观看亚洲视频| 亚洲激情综合网| 亚洲免费福利| 91精品久久久久久蜜桃| 久久久噜噜噜久久人人看| 成人精品一区| 欧美激情视频网站| 日韩av一级片| 在线中文字幕观看| 久久综合88中文色鬼| 亚洲毛片在线| 天天爽天天爽夜夜爽| 欧美一个色资源| 成人看的羞羞网站| 国产天堂在线播放| 亚洲成av人片在线观看香蕉| 秋霞欧美视频| 青青在线视频观看| 亚洲成人久久电影| 成人在线国产| 激情五月俺来也| 最近2019中文字幕一页二页| 老司机午夜精品视频| 簧片在线观看| 久久伊人精品天天| 日韩av电影天堂| h网站视频在线观看| 国产精品流白浆视频| 久久久久久久久伊人| 亚洲精品一区三区三区在线观看| 久久久精品国产一区二区三区| 亚洲亚洲精品在线观看| va天堂va亚洲va影视| 五月天激情图片| 日韩美女主播在线视频一区二区三区| 久久视频国产| 美臀av在线| 日韩免费黄色av| 中文字幕色av一区二区三区| 成人精品国产亚洲| 欧美一区二区视频在线播放| 日韩西西人体444www| 国产精品日韩欧美一区| av免费在线一区二区三区| 国产精品亚洲片夜色在线| 一区二区三区在线免费播放| 在线日韩一区| 在线观看理论片| 国产精品欧美久久久| 国产人妖一区| 国产精品日韩高清| 欧美日韩三级视频| 一区二区不卡| xxxxx日韩| 精品视频第一区| 欧美日韩精品免费观看视频| 在线亚洲一区| 成人福利影视| 日本男女交配视频| 欧美剧在线观看| 国产精品毛片高清在线完整版| 老牛影视av一区二区在线观看| 天天操,天天操| 欧美专区日韩视频| 亚洲成人综合在线| 国产精品久久久久久影院8一贰佰| 欧美aaa一级片| 91精品美女在线| 91九色最新地址| 国产农村妇女精品一区二区| 黄视频网站在线看| 欧美少妇一区二区三区| 国产99精品| 国产精品水嫩水嫩| jizzjizz少妇亚洲水多| 丰满少妇大力进入| 久久天天躁狠狠躁夜夜躁2014 | 亚洲va久久久噜噜噜久久狠狠| 欧美不卡一二三| 成人综合在线观看| 国产伦乱精品| 欧洲综合视频| 欧美在线播放一区| 亚洲网站视频福利| 国产午夜精品福利| 国产成人影院| 国产精品一区在线看| 日本成人三级| 久久综合久久八八| 国产欧美一区二区三区鸳鸯浴 | 在线电影院国产精品| 美女诱惑一区二区| 国产成人视屏| 久草在线资源视频| 日韩欧美99| 久久久噜噜噜久久久| 岛国精品视频在线播放| 日欧美一区二区| 国产亚洲久久| 一本大道香蕉8中文在线视频| 欧美一级日本a级v片| 最新国产精品拍自在线播放| 亚洲自拍偷拍九九九| 综合激情视频| 久久国产精品亚洲77777| 最近中文字幕在线中文视频| 欧美乱偷一区二区三区在线| 精品视频在线导航| 成人欧美一区二区三区1314 | 欧美一区二区视频97| 欧美精品日韩综合在线| www.亚洲免费av| 91亚洲国产成人久久精品| 日日夜夜天天综合入口| 欧美精品第三页| 国产一区二区三区四区hd| 久久综合国产精品台湾中文娱乐网| 91国偷自产一区二区开放时间 | 欧美激情综合在线| 午夜宅男久久久|