SpringMVC中DispatcherServlet的doService->doDispatch方法
我们知道Servlet的service方法是被Servlet容器调用的,这个时机是发生的有客户端向servlet请求服务时调用的,而这些都将其委托给DispatcherServlet的doDispatch方法。我们查看其关键代码。processedRequest = checkMultipart(request);multipartRequestParsed = processedR...
·
我们知道Servlet的service方法是被Servlet容器调用的,这个时机是发生的有客户端向servlet请求服务时调用的,而这些都将其委托给DispatcherServlet的doDispatch方法。我们查看其关键代码。
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest, false);//1:获得HandlerExecutionChain
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.参数为HandlerExcutionChain中的handler
//handlerAdapter在初始化servlet时就已经设置好了
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//2:获得HandlerAdapter
// Process last-modified header, if supported by the handler.
String method = request.getMethod();//获得请求的方法
//判定method....做出相关执行
//利用chain中的拦截器,调用拦截器的preHandle方法,对请求进行拦截处理,如果出现异常,则直接返回
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
// Actually invoke the handler.
//真正的对request进行处理,并返回一个ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
//如果没有设置viewName,则通过方法设置默认的viewName
applyDefaultViewName(request, mv);
//得到ModelAndView,执行拦截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
//将mv或者exception写入response中。。返回给客户端
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
1.1首先获取HandlerExcutionChain
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
return getHandler(request);
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {//遍历这个handerMappings,那我们就需要知道handlerMappings是怎么设置
//handlerMappings是在初始化策略中初始化handlerMappings时通过扫描ApplicationContext时获取的
//其中HandlerMapping类的Bean,其中就包括RequestMappingHandlerMapping实例
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}//我们暂时讨论其中的RequestMappingHandlerMapping实例
HandlerExecutionChain handler = hm.getHandler(request);//所以关键的需要chain的方法在这
if (handler != null) {
return handler;
}
}
return null;
}
1.2:跳到RequestMappingHandlerMapping的getHandler方法中
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);//获取内部的handler,如果没有则返回默认的handler,是一个MethodHandler
//。。。。。。
// Bean name or resolved handler?判定是bean名字还是实例
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
//通过获得到的HandlerMethod创建一个HandlerExcutionChain。
return getHandlerExecutionChain(handler, request);//1.5
}
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);//获取request的查找路径
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
//获得存入RequestMappingHandlerMapping中的handlerMethods属性的HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
//。。。。。。。。
return (handlerMethod != null) ? handlerMethod.createWithResolvedBean() : null;
}
1.3:如何获取HandlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<Match>();
List<T> directPathMatches = this.urlMap.get(lookupPath);//直接根据path获取存入urlMap中的MappingInfo
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);//将匹配好的MappingInfo放入matches
}
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
Collections.sort(matches, comparator);//排序
Match bestMatch = matches.get(0);//只会返回第一个匹配的Match
//有多个则比较,相等则抛出异常。。。。
//将uri中的模板参数暴露在request的属性上
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;//返回HandlerMethod
}
else {
return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
}
}
1.4:通过传入一个Match的集合引用,将HandlerMethod和MappingInfo封装进Match当中
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);//不太懂里面的作用,反正还是返回MappingInfo
if (match != null) {
//通过mappingInfo从handlerMethods那得到HandlerMethod,所以返回的match中有MappingInfo以及HandlerMethod
matches.add(new Match(match, handlerMethods.get(mapping)));
}
}
}
1.5创建一个HandlerExcutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain =
(handler instanceof HandlerExecutionChain) ?//传入handler
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);//新建一个chain对象
chain.addInterceptors(getAdaptedInterceptors());//往chain中添加拦截器,这个以后再讲
//这两种拦截器是有区别的,一个应该是全局的,一个是根据正则匹配的,只有符合表达式的chain才能添加拦截器。。
String lookupPath = urlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());//往chain中添加拦截器
}
}
return chain;
}
最后对ModelAndView进行渲染
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
//异常暂时不考虑其实现细节
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);//渲染modelAndView
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
//省略。。。
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);//通过localResolver解析出request中的local
response.setLocale(locale);//对响应设置local,肯定要一致才行不,。。
View view;
if (mv.isReference()) {//mv中的view是不是一个字符串,
// We need to resolve the view name.//是,则需要通过viewName以及内部数据模型解析得到View
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
}
// Delegate to the View object for rendering.将渲染工作交给view,并传入内部数据模型,所以实际的渲染工作是view完成的
view.render(mv.getModelInternal(), request, response);
}
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
}
//合并一些静态数据以及requestContext中的数据
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
//预处理request和response
prepareResponse(request, response);
//这个方法的实现每个视图引擎都有不同的处理
renderMergedOutputModel(mergedModel, request, response);//通过合并完的model进行渲染
}
可以预测,最后通过渲染得到的内容会写入到reponse当中。。。。
更多推荐
已为社区贡献2条内容
所有评论(0)