文章环境说明:
spring mvc 版本3.2.4.RELEASE,项目中注解方式注册Controller。
众所周知Spring Mvc 中的DispatcherServlet中会使用HandlerMapping 将请求Url解析成为handler处理器。
关于HandlerMapping 实际只有两个突出的功能注册和查找。由于注册是在spring容器加载时就已将Controller的每一个方法注册成handler,学起来门槛较高。因此此文将先说查找反推出注册。
注:由于Spring Mvc 的版本不同所以相应代码存在出入,以下代码全部出于spring Mvc 3.2.4.RELEASE。
查找:
在DispatcherServlet中doDispatch方法中可以看到根据request使用HandlerMapping获取HandlerExecutionChain对象。代码如下所示:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//在spring-servlet中是否配有MultipartResolver用于解析特殊
//的request 比如附件上传:CommonsMultipartResolver
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// Determine handler for the current request.
//根据request 在HandlerMapping 查找handler信息
mappedHandler = getHandler(processedRequest, false);
.....
}catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
DispatcherServlet中的getHandler代码如下所示:
@Deprecated
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
return getHandler(request);
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//handlerMappings 在容器启动时就已经将handlerMapping进行了赋值
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
关于handlerMappings 的赋值代码同样在DispatcherServlet代码中,代码如下所示
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
//初始化handlerMapping
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
//可在Web.xml进行显示指定,默认是true 是否默认加载所有HandlerMapping下的values
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
//获取context中的所有HandlerMappings的子类,并将其下的values 初始化到handlerMappings中
//其中的子类有
//RequestMappingHandlerMapping(所有使用注解定义的Controller)
//BeanNameUrlHandlerMapping(配置文件中定义的Interceptor)
//SimpleUrlHandlerMapping(配置文件中的mvc:resources显示定义的)
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
OrderComparator.sort(this.handlerMappings);
}
}else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
至于在DispatcherServlet的getHandler调用的hm.getHandler()方法就比较简单,在RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping类中并没有对其父类AbstractHandlerMapping的getHandler方法进行重写。其AbstractHandlerMapping的getHandler方法如下所示(spring MVC升级中对并未对此方法进行修改):
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//此段代码只会在controller是注解方式定义的时候使用到
Object handler = getHandlerInternal(request);
//如果在注解中没有查到相应Handler 取默认defaultHandler
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
//当handler是String类型时直接从Contest容器中查找
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
return getHandlerExecutionChain(handler, request);
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//将handler转换为HandlerExecutionChain对象
HandlerExecutionChain chain =
(handler instanceof HandlerExecutionChain) ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
//将拦截器放到HandlerExecutionChain 处理器中此处的拦截器继承自HandlerInterceptor
chain.addInterceptors(getAdaptedInterceptors());
//将拦截器放到HandlerExecutionChain 处理器中此处的拦截器继承自MappedInterceptor
String lookupPath = urlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
关于getHandlerInternal()方法,只在其子类AbstractHandlerMethodMapping<T>对其进行了实现。由于AbstractHandlerMethodMapping 此类较复杂,将于后续文章对其补充说明!
分享到:
相关推荐
第一步:发起请求到前端控制器(DispatcherServlet) 第二步:前端控制器请求 HandlerMapping 查找 Handler,可以根据xml配
NULL 博文链接:https://yihuawuye1.iteye.com/blog/2104547
2、前端控制器请求处理器映射器(HandlerMapping)去查找处理器(Handler)。 3、找到以后处理器映射器(HandlerMappering)向前端控制器返回执行链(HandlerExecutionChain)。 HANDLEREXECUTIONCHAIN,即处理处理...
org.apache.cxf.spring.remoting.Jsr181HandlerMapping.jar
2、前端控制器请求处理器映射器(HandlerMapping)去查找处理器(Handler) 3、找到以后处理器映射器(HandlerMappering)向前端
HandlerMapping HandlerAdapter View ViewResolver类图 矢量图文件 https://blog.csdn.net/qq_39609993/article/details/105435850
1.前端控制器接收请求 2.前端控制器调用HandlerMapping(处理器映射器)根据url查找Handler 3.调用处理器适配器执行Handler,得到
主要介绍了SpringMVC源码解读之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化的相关资料,需要的朋友可以参考下
主要介绍了SpringMVC源码解读之HandlerMapping 的相关资料,需要的朋友可以参考下
该资源主要是SpringMVC工作流程,各个组件(DispatcherServlet、HandlerMapping、ViewResolver、Handler)的说明以及工作流程的文字说明等等。
主要介绍了SpringMVC源码解读之HandlerMapping - AbstractUrlHandlerMapping系列request分发 的相关资料,需要的朋友可以参考下
2、 DispatcherServlet把请求转交给HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器对象、多个HandlerInterceptor拦截器)对象.(后面会学习到拦截器) 3、 ...
(3)、 处理器映射器(HandlerMapping)找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet(前端控制器)。 (4)、 DispatcherServlet...
分别是:RequestMappingHandlerMapping与BeanNameUrlHandlerMapping实现组成结构:RequestMappingH
springMVC相关技术配置使用注解的HandlerMapping和HandlerAdapter使用<mvc:annotation-driver> 不过springBoot已经省略了这些配置 配置使用注解的Handler和Service等等使用<context:component-scan> 不过springBoot...
NULL 博文链接:https://endeavor416.iteye.com/blog/269974
1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器...
1、 户发送请求前端控制器DispatcherServlet 2、 DispatcherServlet收到请求调HandlerMapping处理器映射器 3、
1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器...
1. 客户端请求提交到DispatcherServlet 2. 由DispatcherServlet控制器查询个或多个HandlerMapping,找到处理 3