HandlerAdapter字面上的意思就是处理适配器,它的作用用一句话概括就是调用具体的方法对用户发来的请求来进行处理。当handlerMapping获取到执行请求的controller时,DispatcherServlte会根据controller对应的controller类型来调用相应的HandlerAdapter来进行处理。

在贴源码之前先说一下HandlerAdapter处理的大体流程,这样就有一个大体的掌握。大体流程有三步:

1.DispatcherServlte会根据配置文件信息注册HandlerAdapter,如果在配置文件中没有配置,那么DispatcherServlte会获取HandlerAdapter的默认配置,如果是读取默认配置的话,DispatcherServlte会读取DispatcherServlte.properties文件,该文件中配置了三种HandlerAdapter:HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter和AnnotationMethodHandlerAdapter。DispatcherServlte会将这三个HandlerAdapter对象存储到它的handlerAdapters这个集合属性中,这样就完成了HandlerAdapter的注册。

2.DispatcherServlte会根据handlerMapping传过来的controller与已经注册好了的HandlerAdapter一一匹配,看哪一种HandlerAdapter是支持该controller类型的,如果找到了其中一种HandlerAdapter是支持传过来的controller类型,那么该HandlerAdapter会调用自己的handle方法,handle方法运用Java的反射机制执行controller的具体方法来获得ModelAndView,例如SimpleControllerHandlerAdapter是支持实现了controller接口的控制器,如果自己写的控制器实现了controller接口,那么SimpleControllerHandlerAdapter就会去执行自己写控制器中的具体方法来完成请求。

下面是我自己写的代码。

1.自己写的controller,就是我们自己写的控制器

  1. package com.wangbiao.springMVC;
  2. import javax.servlet.ServletContext;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import org.springframework.web.servlet.ModelAndView;
  6. import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
  7. public class HelloWorld extends  MultiActionController{
  8. public ModelAndView sayHelloWorld(HttpServletRequest request, HttpServletResponse response) {
  9. String param = request.getParameter("param");
  10. System.out.println("springMVC测试:helloWorld;"+param);
  11. ModelAndView mv = new ModelAndView();
  12. mv.addObject("content", "springMVC HelloWorld:"+param);
  13. mv.setViewName("springMVC/helloWorld");
  14. ServletContext ctx = this.getServletContext();
  15. return mv;
  16. }
  17. }
package com.wangbiao.springMVC;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController; public class HelloWorld extends MultiActionController{ public ModelAndView sayHelloWorld(HttpServletRequest request, HttpServletResponse response) {
String param = request.getParameter("param");
System.out.println("springMVC测试:helloWorld;"+param);
ModelAndView mv = new ModelAndView();
mv.addObject("content", "springMVC HelloWorld:"+param);
mv.setViewName("springMVC/helloWorld");
ServletContext ctx = this.getServletContext();
return mv;
} }

2.SpringMVC配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:mvc="http://www.springframework.org/schema/mvc"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xmlns:tx="http://www.springframework.org/schema/tx"
  8. xsi:schemaLocation="http://www.springframework.org/schema/beans
  9. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  10. http://www.springframework.org/schema/mvc
  11. http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
  12. http://www.springframework.org/schema/context
  13. http://www.springframework.org/schema/context/spring-context-3.0.xsd
  14. http://www.springframework.org/schema/aop
  15. http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
  16. http://www.springframework.org/schema/tx
  17. http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
  18. <!-- handlerMapping  -->
  19. <bean id="beanNameUrlMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
  20. <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  21. <property name="mappings">
  22. <props>
  23. <prop key="/springMVC.d">/HelloWorld</prop>
  24. </props>
  25. </property>
  26. </bean>
  27. <bean name="/HelloWorld" class="com.wangbiao.springMVC.HelloWorld">
  28. <property name="methodNameResolver">
  29. <ref local="methodNameResolver"/>
  30. </property>
  31. </bean>
  32. <!-- 在url中对应具体的方法,通过m后面带的参数来确定方法 -->
  33. <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
  34. <property name="paramName"><value>m</value></property>
  35. <property name="defaultMethodName"><value>execute</value></property>
  36. </bean>
  37. <!--视图解析器-->
  38. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  39. <!-- webroot到一指定文件夹文件路径 -->
  40. <property name="prefix" value="/"/>
  41. <!-- 视图名称后缀  -->
  42. <property name="suffix" value=".jsp"/>
  43. </bean>
  44. </beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- handlerMapping -->
<bean id="beanNameUrlMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/springMVC.d">/HelloWorld</prop>
</props>
</property>
</bean> <bean name="/HelloWorld" class="com.wangbiao.springMVC.HelloWorld">
<property name="methodNameResolver">
<ref local="methodNameResolver"/>
</property>
</bean>
<!-- 在url中对应具体的方法,通过m后面带的参数来确定方法 -->
<bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName"><value>m</value></property>
<property name="defaultMethodName"><value>execute</value></property>
</bean> <!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- webroot到一指定文件夹文件路径 -->
<property name="prefix" value="/"/>
<!-- 视图名称后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
</beans>

下面是源码

1.DispatcherServlet注册HandlerAdapter。DispatcherServlet的initHandlerAdapters方法,红色标记的部分是关键。由于在配置文件中没有对HandlerAdapter的相关配置,所以DispatcherServlet获取到的HandlerAdapter是三个默认的HandlerAdapter对象,分别是HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter和AnnotationMethodHandlerAdapter,并将这三个对象存入handlerAdapter属性中去。

  1. private void initHandlerAdapters(ApplicationContext context) {
  2. this.handlerAdapters = null;
  3. if (this.detectAllHandlerAdapters) {
  4. // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
  5. Map<String, HandlerAdapter> matchingBeans =
  6. BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
  7. if (!matchingBeans.isEmpty()) {
  8. this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
  9. // We keep HandlerAdapters in sorted order.
  10. OrderComparator.sort(this.handlerAdapters);
  11. }
  12. }
  13. else {
  14. try {
  15. HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
  16. this.handlerAdapters = Collections.singletonList(ha);
  17. }
  18. catch (NoSuchBeanDefinitionException ex) {
  19. // Ignore, we'll add a default HandlerAdapter later.
  20. }
  21. }
  22. // Ensure we have at least some HandlerAdapters, by registering
  23. // default HandlerAdapters if no other adapters are found.
  24. if (this.handlerAdapters == null) {
  25. this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
  26. if (logger.isDebugEnabled()) {
  27. logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
  28. }
  29. }
  30. }
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null; if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
OrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
} // Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}

2.根据handlerMapping传过来的Handler对象与DispatcherServlet集合属性handlerAdapter中的HandlerAdapter一一匹配,如果有支持Handler对象的HandlerAdapter,那么HandlerAdapter就会调用自己的handle方法处理请求。

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. HttpServletRequest processedRequest = request;
  3. HandlerExecutionChain mappedHandler = null;
  4. int interceptorIndex = -1;
  5. try {
  6. ModelAndView mv;
  7. boolean errorView = false;
  8. try {
  9. processedRequest = checkMultipart(request);
  10. // Determine handler for the current request.
  11. mappedHandler = getHandler(processedRequest, false);
  12. if (mappedHandler == null || mappedHandler.getHandler() == null) {
  13. noHandlerFound(processedRequest, response);
  14. return;
  15. }
  16. // Determine handler adapter for the current request.
  17. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  18. // Process last-modified header, if supported by the handler.
  19. String method = request.getMethod();
  20. boolean isGet = "GET".equals(method);
  21. if (isGet || "HEAD".equals(method)) {
  22. long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
  23. if (logger.isDebugEnabled()) {
  24. String requestUri = urlPathHelper.getRequestUri(request);
  25. logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
  26. }
  27. if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
  28. return;
  29. }
  30. }
  31. // Apply preHandle methods of registered interceptors.
  32. HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
  33. if (interceptors != null) {
  34. for (int i = 0; i < interceptors.length; i++) {
  35. HandlerInterceptor interceptor = interceptors[i];
  36. if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
  37. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
  38. return;
  39. }
  40. interceptorIndex = i;
  41. }
  42. }
  43. // Actually invoke the handler.
  44. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  45. // Do we need view name translation?
  46. if (mv != null && !mv.hasView()) {
  47. mv.setViewName(getDefaultViewName(request));
  48. }
  49. // Apply postHandle methods of registered interceptors.
  50. if (interceptors != null) {
  51. for (int i = interceptors.length - 1; i >= 0; i--) {
  52. HandlerInterceptor interceptor = interceptors[i];
  53. interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
  54. }
  55. }
  56. }
  57. catch (ModelAndViewDefiningException ex) {
  58. logger.debug("ModelAndViewDefiningException encountered", ex);
  59. mv = ex.getModelAndView();
  60. }
  61. catch (Exception ex) {
  62. Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
  63. mv = processHandlerException(processedRequest, response, handler, ex);
  64. errorView = (mv != null);
  65. }
  66. // Did the handler return a view to render?
  67. if (mv != null && !mv.wasCleared()) {
  68. render(mv, processedRequest, response);
  69. if (errorView) {
  70. WebUtils.clearErrorRequestAttributes(request);
  71. }
  72. }
  73. else {
  74. if (logger.isDebugEnabled()) {
  75. logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
  76. "': assuming HandlerAdapter completed request handling");
  77. }
  78. }
  79. // Trigger after-completion for successful outcome.
  80. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
  81. }
  82. catch (Exception ex) {
  83. // Trigger after-completion for thrown exception.
  84. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
  85. throw ex;
  86. }
  87. catch (Error err) {
  88. ServletException ex = new NestedServletException("Handler processing failed", err);
  89. // Trigger after-completion for thrown exception.
  90. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
  91. throw ex;
  92. }
  93. finally {
  94. // Clean up any resources used by a multipart request.
  95. if (processedRequest != request) {
  96. cleanupMultipart(processedRequest);
  97. }
  98. }
  99. }
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1; try {
ModelAndView mv;
boolean errorView = false; try {
processedRequest = checkMultipart(request); // Determine handler for the current request.
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
} // Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
} // Apply preHandle methods of registered interceptors.
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (interceptors != null) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
} // Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // Do we need view name translation?
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
} // Apply postHandle methods of registered interceptors.
if (interceptors != null) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
} // Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
} // Trigger after-completion for successful outcome.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
} catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
} finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}

getHandlerAdapter方法

  1. protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
  2. for (HandlerAdapter ha : this.handlerAdapters) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Testing handler adapter [" + ha + "]");
  5. }
  6. if (ha.supports(handler)) {
  7. return ha;
  8. }
  9. }
  10. throw new ServletException("No adapter for handler [" + handler +
  11. "]: Does your handler implement a supported interface like Controller?");
  12. }
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: Does your handler implement a supported interface like Controller?");
}

HandlerAdapter接口

  1. /*
  2. * Copyright 2002-2008 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.web.servlet;
  17. import javax.servlet.http.HttpServletRequest;
  18. import javax.servlet.http.HttpServletResponse;
  19. /**
  20. * MVC framework SPI interface, allowing parameterization of core MVC workflow.
  21. *
  22. * <p>Interface that must be implemented for each handler type to handle a request.
  23. * This interface is used to allow the {@link DispatcherServlet} to be indefinitely
  24. * extensible. The DispatcherServlet accesses all installed handlers through this
  25. * interface, meaning that it does not contain code specific to any handler type.
  26. *
  27. * <p>Note that a handler can be of type <code>Object</code>. This is to enable
  28. * handlers from other frameworks to be integrated with this framework without
  29. * custom coding, as well as to allow for annotation handler objects that do
  30. * not obey any specific Java interface.
  31. *
  32. * <p>This interface is not intended for application developers. It is available
  33. * to handlers who want to develop their own web workflow.
  34. *
  35. * <p>Note: HandlerAdaptger implementators may implement the
  36. * {@link org.springframework.core.Ordered} interface to be able to specify a
  37. * sorting order (and thus a priority) for getting applied by DispatcherServlet.
  38. * Non-Ordered instances get treated as lowest priority.
  39. *
  40. * @author Rod Johnson
  41. * @author Juergen Hoeller
  42. * @see org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
  43. * @see org.springframework.web.servlet.handler.SimpleServletHandlerAdapter
  44. */
  45. public interface HandlerAdapter {
  46. /**
  47. * Given a handler instance, return whether or not this HandlerAdapter can
  48. * support it. Typical HandlerAdapters will base the decision on the handler
  49. * type. HandlerAdapters will usually only support one handler type each.
  50. * <p>A typical implementation:
  51. * <p><code>
  52. * return (handler instanceof MyHandler);
  53. * </code>
  54. * @param handler handler object to check
  55. * @return whether or not this object can use the given handler
  56. */
  57. boolean supports(Object handler);
  58. /**
  59. * Use the given handler to handle this request.
  60. * The workflow that is required may vary widely.
  61. * @param request current HTTP request
  62. * @param response current HTTP response
  63. * @param handler handler to use. This object must have previously been passed
  64. * to the <code>supports</code> method of this interface, which must have
  65. * returned <code>true</code>.
  66. * @throws Exception in case of errors
  67. * @return ModelAndView object with the name of the view and the required
  68. * model data, or <code>null</code> if the request has been handled directly
  69. */
  70. ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  71. /**
  72. * Same contract as for HttpServlet's <code>getLastModified</code> method.
  73. * Can simply return -1 if there's no support in the handler class.
  74. * @param request current HTTP request
  75. * @param handler handler to use
  76. * @return the lastModified value for the given handler
  77. * @see javax.servlet.http.HttpServlet#getLastModified
  78. * @see org.springframework.web.servlet.mvc.LastModified#getLastModified
  79. */
  80. long getLastModified(HttpServletRequest request, Object handler);
  81. }
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* MVC framework SPI interface, allowing parameterization of core MVC workflow.
*
* <p>Interface that must be implemented for each handler type to handle a request.
* This interface is used to allow the {@link DispatcherServlet} to be indefinitely
* extensible. The DispatcherServlet accesses all installed handlers through this
* interface, meaning that it does not contain code specific to any handler type.
*
* <p>Note that a handler can be of type <code>Object</code>. This is to enable
* handlers from other frameworks to be integrated with this framework without
* custom coding, as well as to allow for annotation handler objects that do
* not obey any specific Java interface.
*
* <p>This interface is not intended for application developers. It is available
* to handlers who want to develop their own web workflow.
*
* <p>Note: HandlerAdaptger implementators may implement the
* {@link org.springframework.core.Ordered} interface to be able to specify a
* sorting order (and thus a priority) for getting applied by DispatcherServlet.
* Non-Ordered instances get treated as lowest priority.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
* @see org.springframework.web.servlet.handler.SimpleServletHandlerAdapter
*/
public interface HandlerAdapter { /**
* Given a handler instance, return whether or not this HandlerAdapter can
* support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p><code>
* return (handler instanceof MyHandler);
* </code>
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler); /**
* Use the given handler to handle this request.
* The workflow that is required may vary widely.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler to use. This object must have previously been passed
* to the <code>supports</code> method of this interface, which must have
* returned <code>true</code>.
* @throws Exception in case of errors
* @return ModelAndView object with the name of the view and the required
* model data, or <code>null</code> if the request has been handled directly
*/
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /**
* Same contract as for HttpServlet's <code>getLastModified</code> method.
* Can simply return -1 if there's no support in the handler class.
* @param request current HTTP request
* @param handler handler to use
* @return the lastModified value for the given handler
* @see javax.servlet.http.HttpServlet#getLastModified
* @see org.springframework.web.servlet.mvc.LastModified#getLastModified
*/
long getLastModified(HttpServletRequest request, Object handler); }

再来看一下自己写的控制器HelloWorld继承了MultiActionController。MultiActionController又继承了AbstractController,AbstractController实现了Controller。这样就看DispatcherServlet属性中的HandlerApater谁支持Controller类型的处理器了。在运行的过程中发现SimpleControllerHandlerAdapter是支持Controller类型的控制器的。
来看一下SimpleControllerHandlerAdapter的代码

  1. public class SimpleControllerHandlerAdapter implements HandlerAdapter {
  2. public boolean supports(Object handler) {
  3. return (handler instanceof Controller);
  4. }
  5. public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
  6. throws Exception {
  7. return ((Controller) handler).handleRequest(request, response);
  8. }
  9. public long getLastModified(HttpServletRequest request, Object handler) {
  10. if (handler instanceof LastModified) {
  11. return ((LastModified) handler).getLastModified(request);
  12. }
  13. return -1L;
  14. }
  15. }
public class SimpleControllerHandlerAdapter implements HandlerAdapter {

	public boolean supports(Object handler) {
return (handler instanceof Controller);
} public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { return ((Controller) handler).handleRequest(request, response);
} public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
} }

再看一下Controller源码,Controller接口只有一个handleRequest方法

  1. public interface Controller {
  2. /**
  3. * Process the request and return a ModelAndView object which the DispatcherServlet
  4. * will render. A <code>null</code> return value is not an error: It indicates that
  5. * this object completed request processing itself, thus there is no ModelAndView
  6. * to render.
  7. * @param request current HTTP request
  8. * @param response current HTTP response
  9. * @return a ModelAndView to render, or <code>null</code> if handled directly
  10. * @throws Exception in case of errors
  11. */
  12. ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
  13. }
public interface Controller {

	/**
* Process the request and return a ModelAndView object which the DispatcherServlet
* will render. A <code>null</code> return value is not an error: It indicates that
* this object completed request processing itself, thus there is no ModelAndView
* to render.
* @param request current HTTP request
* @param response current HTTP response
* @return a ModelAndView to render, or <code>null</code> if handled directly
* @throws Exception in case of errors
*/
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; }

再看看实现了Controller接口的AbstractController类

  1. public abstract class AbstractController extends WebContentGenerator implements Controller {
  2. private boolean synchronizeOnSession = false;
  3. /**
  4. * Set if controller execution should be synchronized on the session,
  5. * to serialize parallel invocations from the same client.
  6. * <p>More specifically, the execution of the <code>handleRequestInternal</code>
  7. * method will get synchronized if this flag is "true". The best available
  8. * session mutex will be used for the synchronization; ideally, this will
  9. * be a mutex exposed by HttpSessionMutexListener.
  10. * <p>The session mutex is guaranteed to be the same object during
  11. * the entire lifetime of the session, available under the key defined
  12. * by the <code>SESSION_MUTEX_ATTRIBUTE</code> constant. It serves as a
  13. * safe reference to synchronize on for locking on the current session.
  14. * <p>In many cases, the HttpSession reference itself is a safe mutex
  15. * as well, since it will always be the same object reference for the
  16. * same active logical session. However, this is not guaranteed across
  17. * different servlet containers; the only 100% safe way is a session mutex.
  18. * @see org.springframework.web.servlet.mvc.AbstractController#handleRequestInternal
  19. * @see org.springframework.web.util.HttpSessionMutexListener
  20. * @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)
  21. */
  22. public final void setSynchronizeOnSession(boolean synchronizeOnSession) {
  23. this.synchronizeOnSession = synchronizeOnSession;
  24. }
  25. /**
  26. * Return whether controller execution should be synchronized on the session.
  27. */
  28. public final boolean isSynchronizeOnSession() {
  29. return this.synchronizeOnSession;
  30. }
  31. public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
  32. throws Exception {
  33. // Delegate to WebContentGenerator for checking and preparing.
  34. checkAndPrepare(request, response, this instanceof LastModified);
  35. // Execute handleRequestInternal in synchronized block if required.
  36. if (this.synchronizeOnSession) {
  37. HttpSession session = request.getSession(false);
  38. if (session != null) {
  39. Object mutex = WebUtils.getSessionMutex(session);
  40. synchronized (mutex) {
  41. return handleRequestInternal(request, response);
  42. }
  43. }
  44. }
  45. return handleRequestInternal(request, response);
  46. }
  47. /**
  48. * Template method. Subclasses must implement this.
  49. * The contract is the same as for <code>handleRequest</code>.
  50. * @see #handleRequest
  51. */
  52. protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
  53. throws Exception;
  54. }
public abstract class AbstractController extends WebContentGenerator implements Controller {

	private boolean synchronizeOnSession = false;

	/**
* Set if controller execution should be synchronized on the session,
* to serialize parallel invocations from the same client.
* <p>More specifically, the execution of the <code>handleRequestInternal</code>
* method will get synchronized if this flag is "true". The best available
* session mutex will be used for the synchronization; ideally, this will
* be a mutex exposed by HttpSessionMutexListener.
* <p>The session mutex is guaranteed to be the same object during
* the entire lifetime of the session, available under the key defined
* by the <code>SESSION_MUTEX_ATTRIBUTE</code> constant. It serves as a
* safe reference to synchronize on for locking on the current session.
* <p>In many cases, the HttpSession reference itself is a safe mutex
* as well, since it will always be the same object reference for the
* same active logical session. However, this is not guaranteed across
* different servlet containers; the only 100% safe way is a session mutex.
* @see org.springframework.web.servlet.mvc.AbstractController#handleRequestInternal
* @see org.springframework.web.util.HttpSessionMutexListener
* @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)
*/
public final void setSynchronizeOnSession(boolean synchronizeOnSession) {
this.synchronizeOnSession = synchronizeOnSession;
} /**
* Return whether controller execution should be synchronized on the session.
*/
public final boolean isSynchronizeOnSession() {
return this.synchronizeOnSession;
} public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception { // Delegate to WebContentGenerator for checking and preparing.
checkAndPrepare(request, response, this instanceof LastModified); // Execute handleRequestInternal in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return handleRequestInternal(request, response);
}
}
} return handleRequestInternal(request, response);
} /**
* Template method. Subclasses must implement this.
* The contract is the same as for <code>handleRequest</code>.
* @see #handleRequest
*/
protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception; }

再看一下继承了AbstractController的MultiActionController,MultiActionController中有对AbstractController的handleRequestInternal的实现

  1. protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
  2. throws Exception {
  3. try {
  4. String methodName = this.methodNameResolver.getHandlerMethodName(request);
  5. return invokeNamedMethod(methodName, request, response);
  6. }
  7. catch (NoSuchRequestHandlingMethodException ex) {
  8. return handleNoSuchRequestHandlingMethod(ex, request, response);
  9. }
  10. }
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
try {
String methodName = this.methodNameResolver.getHandlerMethodName(request);
return invokeNamedMethod(methodName, request, response);
}
catch (NoSuchRequestHandlingMethodException ex) {
return handleNoSuchRequestHandlingMethod(ex, request, response);
}
}

可以看出在MultiActionController的handleRequestInternal方法中分为两步,第一步是找寻执行该请求的方法名,第二步是调用invokeNamedMethod方法。
invokeNamedMethod方法源码

  1. protected final ModelAndView invokeNamedMethod(
  2. String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception {
  3. Method method = this.handlerMethodMap.get(methodName);
  4. if (method == null) {
  5. throw new NoSuchRequestHandlingMethodException(methodName, getClass());
  6. }
  7. try {
  8. Class[] paramTypes = method.getParameterTypes();
  9. List<Object> params = new ArrayList<Object>(4);
  10. params.add(request);
  11. params.add(response);
  12. if (paramTypes.length >= 3 && paramTypes[2].equals(HttpSession.class)) {
  13. HttpSession session = request.getSession(false);
  14. if (session == null) {
  15. throw new HttpSessionRequiredException(
  16. "Pre-existing session required for handler method '" + methodName + "'");
  17. }
  18. params.add(session);
  19. }
  20. // If last parameter isn't of HttpSession type, it's a command.
  21. if (paramTypes.length >= 3 &&
  22. !paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
  23. Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
  24. params.add(command);
  25. bind(request, command);
  26. }
  27. //执行该方法
  28. Object returnValue = method.invoke(this.delegate, params.toArray(new Object[params.size()]));
  29. return massageReturnValueIfNecessary(returnValue);
  30. }
  31. catch (InvocationTargetException ex) {
  32. // The handler method threw an exception.
  33. return handleException(request, response, ex.getTargetException());
  34. }
  35. catch (Exception ex) {
  36. // The binding process threw an exception.
  37. return handleException(request, response, ex);
  38. }
  39. }
protected final ModelAndView invokeNamedMethod(
String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception { Method method = this.handlerMethodMap.get(methodName);
if (method == null) {
throw new NoSuchRequestHandlingMethodException(methodName, getClass());
} try {
Class[] paramTypes = method.getParameterTypes();
List<Object> params = new ArrayList<Object>(4);
params.add(request);
params.add(response); if (paramTypes.length >= 3 && paramTypes[2].equals(HttpSession.class)) {
HttpSession session = request.getSession(false);
if (session == null) {
throw new HttpSessionRequiredException(
"Pre-existing session required for handler method '" + methodName + "'");
}
params.add(session);
} // If last parameter isn't of HttpSession type, it's a command.
if (paramTypes.length >= 3 &&
!paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
params.add(command);
bind(request, command);
}
//执行该方法
Object returnValue = method.invoke(this.delegate, params.toArray(new Object[params.size()]));
return massageReturnValueIfNecessary(returnValue);
}
catch (InvocationTargetException ex) {
// The handler method threw an exception.
return handleException(request, response, ex.getTargetException());
}
catch (Exception ex) {
// The binding process threw an exception.
return handleException(request, response, ex);
}
}

根据方法名在MultiActionController的方法集合属性handlerMethodMap中寻找对应的方法对象,然后执行该方法对象,执行该方法对象后获得一个object的返回值,通过massageReturnValueIfNecessary方法判断这个返回值的类型,如果这个值的返回类型是ModelAndView类型,就返回ModelAndView。到此我们找到响应请求的方法并执行获得了返回值。

虽然总体走完了,但是有两个地方还没有说,1如何根据用户发来的url请求来确定url中哪一段是执行该请求的方法名;2.确定方法名后是怎么找到该方法的。
MultiActionController中有一个构造函数,registerHandlerMethods(this.delegate);方法就是对我们所写的controller中的方法的注册。

  1. public MultiActionController() {
  2. this.delegate = this;
  3. registerHandlerMethods(this.delegate);
  4. // We'll accept no handler methods found here - a delegate might be set later on.
  5. }
	public MultiActionController() {
this.delegate = this;
registerHandlerMethods(this.delegate);
// We'll accept no handler methods found here - a delegate might be set later on.
}

registerHandlerMethods方法

this.delegate其实就是继承了MultiActionController的控制对象,比如HelloWorld继承了MultiActionController,那么传过来的就是HelloWorld对象,就会将HelloWorld对象中的所有方法放到MultiActionController的handlerMethodMap属性中去了。

  1. private void registerHandlerMethods(Object delegate) {
  2. this.handlerMethodMap.clear();
  3. this.lastModifiedMethodMap.clear();
  4. this.exceptionHandlerMap.clear();
  5. // Look at all methods in the subclass, trying to find
  6. // methods that are validators according to our criteria
  7. Method[] methods = delegate.getClass().getMethods();
  8. for (Method method : methods) {
  9. // We're looking for methods with given parameters.
  10. if (isExceptionHandlerMethod(method)) {
  11. registerExceptionHandlerMethod(method);
  12. }
  13. else if (isHandlerMethod(method)) {
  14. registerHandlerMethod(method);
  15. registerLastModifiedMethodIfExists(delegate, method);
  16. }
  17. }
  18. }
	private void registerHandlerMethods(Object delegate) {
this.handlerMethodMap.clear();
this.lastModifiedMethodMap.clear();
this.exceptionHandlerMap.clear(); // Look at all methods in the subclass, trying to find
// methods that are validators according to our criteria
Method[] methods = delegate.getClass().getMethods();
for (Method method : methods) {
// We're looking for methods with given parameters.
if (isExceptionHandlerMethod(method)) {
registerExceptionHandlerMethod(method);
}
else if (isHandlerMethod(method)) {
registerHandlerMethod(method);
registerLastModifiedMethodIfExists(delegate, method);
}
}
}

在配置文件中有这样一段代码

  1. <!-- 在url中对应具体的方法,通过m后面带的参数来确定方法 -->
  2. <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
  3. <property name="paramName"><value>m</value></property>
  4. <property name="defaultMethodName"><value>execute</value></property>
  5. </bean>
<!-- 在url中对应具体的方法,通过m后面带的参数来确定方法 -->
<bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName"><value>m</value></property>
<property name="defaultMethodName"><value>execute</value></property>
</bean>

ParameterMethodNameResolver这个类的作用就是根据url链接中带的参数来确定执行该url的方法名是什么。在ioc容器初始ParameterMethodNameResolver的时候,容器会将“m”这个参数赋值给ParameterMethodNameResolver的属性paramName,然后ParameterMethodNameResolver会根据url中m后面跟的参数来获取方法名

  1. public String getHandlerMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException {
  2. String methodName = null;
  3. // Check parameter names where the very existence of each parameter
  4. // means that a method of the same name should be invoked, if any.
  5. if (this.methodParamNames != null) {
  6. for (String candidate : this.methodParamNames) {
  7. if (WebUtils.hasSubmitParameter(request, candidate)) {
  8. methodName = candidate;
  9. if (logger.isDebugEnabled()) {
  10. logger.debug("Determined handler method '" + methodName +
  11. "' based on existence of explicit request parameter of same name");
  12. }
  13. break;
  14. }
  15. }
  16. }
  17. // Check parameter whose value identifies the method to invoke, if any.
  18. if (methodName == null && this.paramName != null) {
  19. methodName = request.getParameter(this.paramName);
  20. if (methodName != null) {
  21. if (logger.isDebugEnabled()) {
  22. logger.debug("Determined handler method '" + methodName +
  23. "' based on value of request parameter '" + this.paramName + "'");
  24. }
  25. }
  26. }
  27. if (methodName != null && this.logicalMappings != null) {
  28. // Resolve logical name into real method name, if appropriate.
  29. String originalName = methodName;
  30. methodName = this.logicalMappings.getProperty(methodName, methodName);
  31. if (logger.isDebugEnabled()) {
  32. logger.debug("Resolved method name '" + originalName + "' to handler method '" + methodName + "'");
  33. }
  34. }
  35. if (methodName != null && !StringUtils.hasText(methodName)) {
  36. if (logger.isDebugEnabled()) {
  37. logger.debug("Method name '" + methodName + "' is empty: treating it as no method name found");
  38. }
  39. methodName = null;
  40. }
  41. if (methodName == null) {
  42. if (this.defaultMethodName != null) {
  43. // No specific method resolved: use default method.
  44. methodName = this.defaultMethodName;
  45. if (logger.isDebugEnabled()) {
  46. logger.debug("Falling back to default handler method '" + this.defaultMethodName + "'");
  47. }
  48. }
  49. else {
  50. // If resolution failed completely, throw an exception.
  51. throw new NoSuchRequestHandlingMethodException(request);
  52. }
  53. }
  54. return methodName;
  55. }
public String getHandlerMethodName(HttpServletRequest request) throws NoSuchRequestHandlingMethodException {
String methodName = null; // Check parameter names where the very existence of each parameter
// means that a method of the same name should be invoked, if any.
if (this.methodParamNames != null) {
for (String candidate : this.methodParamNames) {
if (WebUtils.hasSubmitParameter(request, candidate)) {
methodName = candidate;
if (logger.isDebugEnabled()) {
logger.debug("Determined handler method '" + methodName +
"' based on existence of explicit request parameter of same name");
}
break;
}
}
} // Check parameter whose value identifies the method to invoke, if any.
if (methodName == null && this.paramName != null) {
methodName = request.getParameter(this.paramName);
if (methodName != null) {
if (logger.isDebugEnabled()) {
logger.debug("Determined handler method '" + methodName +
"' based on value of request parameter '" + this.paramName + "'");
}
}
} if (methodName != null && this.logicalMappings != null) {
// Resolve logical name into real method name, if appropriate.
String originalName = methodName;
methodName = this.logicalMappings.getProperty(methodName, methodName);
if (logger.isDebugEnabled()) {
logger.debug("Resolved method name '" + originalName + "' to handler method '" + methodName + "'");
}
} if (methodName != null && !StringUtils.hasText(methodName)) {
if (logger.isDebugEnabled()) {
logger.debug("Method name '" + methodName + "' is empty: treating it as no method name found");
}
methodName = null;
} if (methodName == null) {
if (this.defaultMethodName != null) {
// No specific method resolved: use default method.
methodName = this.defaultMethodName;
if (logger.isDebugEnabled()) {
logger.debug("Falling back to default handler method '" + this.defaultMethodName + "'");
}
}
else {
// If resolution failed completely, throw an exception.
throw new NoSuchRequestHandlingMethodException(request);
}
} return methodName;
}

当找到了方法名后,就会去MultiActionController属性handlerMethodMap中根据方法名找方法对象。再执行这个方法就好了。

再来看看是如何从handlerMethodMap集合中找到方法并执行方法的

  1. protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
  2. throws Exception {
  3. try {
  4. String methodName = this.methodNameResolver.getHandlerMethodName(request);
  5. return invokeNamedMethod(methodName, request, response);
  6. }
  7. catch (NoSuchRequestHandlingMethodException ex) {
  8. return handleNoSuchRequestHandlingMethod(ex, request, response);
  9. }
  10. }
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
try {
String methodName = this.methodNameResolver.getHandlerMethodName(request);
return invokeNamedMethod(methodName, request, response);
}
catch (NoSuchRequestHandlingMethodException ex) {
return handleNoSuchRequestHandlingMethod(ex, request, response);
}
}
  1. protected final ModelAndView invokeNamedMethod(
  2. String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception {
  3. Method method = this.handlerMethodMap.get(methodName);
  4. if (method == null) {
  5. throw new NoSuchRequestHandlingMethodException(methodName, getClass());
  6. }
  7. try {
  8. Class[] paramTypes = method.getParameterTypes();
  9. List<Object> params = new ArrayList<Object>(4);
  10. params.add(request);
  11. params.add(response);
  12. if (paramTypes.length >= 3 && paramTypes[2].equals(HttpSession.class)) {
  13. HttpSession session = request.getSession(false);
  14. if (session == null) {
  15. throw new HttpSessionRequiredException(
  16. "Pre-existing session required for handler method '" + methodName + "'");
  17. }
  18. params.add(session);
  19. }
  20. // If last parameter isn't of HttpSession type, it's a command.
  21. if (paramTypes.length >= 3 &&
  22. !paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
  23. Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
  24. params.add(command);
  25. bind(request, command);
  26. }
  27. Object returnValue = method.invoke(this.delegate, params.toArray(new Object[params.size()]));
  28. return massageReturnValueIfNecessary(returnValue);
  29. }
  30. catch (InvocationTargetException ex) {
  31. // The handler method threw an exception.
  32. return handleException(request, response, ex.getTargetException());
  33. }
  34. catch (Exception ex) {
  35. // The binding process threw an exception.
  36. return handleException(request, response, ex);
  37. }
  38. }
protected final ModelAndView invokeNamedMethod(
String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception { Method method = this.handlerMethodMap.get(methodName);
if (method == null) {
throw new NoSuchRequestHandlingMethodException(methodName, getClass());
} try {
Class[] paramTypes = method.getParameterTypes();
List<Object> params = new ArrayList<Object>(4);
params.add(request);
params.add(response); if (paramTypes.length >= 3 && paramTypes[2].equals(HttpSession.class)) {
HttpSession session = request.getSession(false);
if (session == null) {
throw new HttpSessionRequiredException(
"Pre-existing session required for handler method '" + methodName + "'");
}
params.add(session);
} // If last parameter isn't of HttpSession type, it's a command.
if (paramTypes.length >= 3 &&
!paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
params.add(command);
bind(request, command);
} Object returnValue = method.invoke(this.delegate, params.toArray(new Object[params.size()]));
return massageReturnValueIfNecessary(returnValue);
}
catch (InvocationTargetException ex) {
// The handler method threw an exception.
return handleException(request, response, ex.getTargetException());
}
catch (Exception ex) {
// The binding process threw an exception.
return handleException(request, response, ex);
}
}

HandlerAdapter,大家都叫它适配处理器,就是适配不同的处理器,将他们封装起来调用同一个借口方法,这样DispatcherServlet就只需要调用接口方法,而不需要在DispatcherServlet判断调用哪一个具体的HandlerAdapter的实现类了。
         当时看到自己项目里面的所有的处理器都是实现了MultiActionController的Controller,再去看MultiActionController的源码时,发现MultiActionController实现了Controller接口,Controller接口只有一个handleRequest方法,我想DispatcherServlet直接用Controller的handleRequest方法执行具体请求就行了,何必还要用HandlerAdapter将Controller封装起来,再在HandlerAdapter的handle方法里执行Controller的handleRequest方法呢,这不是多此一举?
        只怪自己目光短浅,由于用的是配置的方式来做项目的,而且平时自己写的Controller只继承了MultiActionController,以为Controller接口就是所有的处理器的接口,眼里就只有Controller了。
        今天再来看源码,发现处理器根本就不只有Controller这一种。还有HttpRequestHandler,Servlet等处理器。下面来介绍一下几种适配器对应的处理器以及这些处理器的作用\
        1. AnnotationMethodHandlerAdapter主要是适配注解类处理器,注解类处理器就是我们经常使用的@Controller的这类处理器
        2. HttpRequestHandlerAdapter主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler接口的处理器,这类处理器的作用是处理通过SpringMVC来访问的静态资源的请求。        
        3.SimpleControllerHandlerAdapter是Controller处理适配器,适配实现了Controller接口或Controller接口子类的处理器,比如我们经常自己写的Controller来继承MultiActionController,那么自己写的这些Controller就会由SimpleControllerHandlerAdapter来适配
        4.SimpleServletHandlerAdapter是Servlet处理适配器,适配实现了Servlet接口或Servlet的子类的处理器,我们不仅可以在web.xml里面配置Servlet,其实也可以用SpringMVC来配置Servlet,不过这个适配器很少用到,而且SpringMVC默认的适配器没有他,默认的是前面的三种。

SpringMVC之 HandlerAdapter和handlerMapping的更多相关文章

  1. springMVC源码分析--HandlerMapping(一)

    HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler,其实现机制简单来说就是维持了一个url到Controller关系的Map结构,其提供的实际功能也是根据req ...

  2. SpringMVC源码解读 - HandlerMapping

    SpringMVC在请求到handler处理器的分发这步是通过HandlerMapping模块解决的.handlerMapping 还处理拦截器. 先看看HandlerMapping的继承树吧 可以大 ...

  3. SpringMVC之HandlerAdapter解析

    HandlerAdapter字面上的意思就是处理适配器,它的作用用一句话概括就是调用具体的方法对用户发来的请求来进行处理.当handlerMapping获取到执行请求的controller时,Disp ...

  4. SpringMVC笔记- 不配置HandlerMapping

    使用SpringMVC框架时发现有的配置了HandlerMapping,而有的没有,那么它们有什么区别呢?不配置能不能正常使用框架呢? 下面我们看一看不配置任何HandlerMapping时,框架会使 ...

  5. springmvc源码笔记-HandlerMapping注入

    在springmvc中,如何根据url找到controller以及对应方法,依赖的是HandlerMapping接口的getHandler方法 在spring容器中默认注册的HandlerMappin ...

  6. 01基于配置文件方式的SpringMVC,三种HandlerMapping,三种控制器

     1 添加Spring MVC所需的jar包. 2 创建一个以下项目结构的springmvc项目 3 web.xml的配置如下: <?xmlversion="1.0"en ...

  7. SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping请求分发

    AbstractHandlerMethodMapping实现接口getHandlerInternal,定义查找流程 RequestMappingInfoHandlerMapping根据RequestM ...

  8. SpringMVC源码解读 - HandlerMapping - AbstractUrlHandlerMapping系列request分发

    AbstractHandlerMapping实现HandlerMapping接口定的getHandler 1. 提供getHandlerInternal模板方法给子类实现 2. 如果没有获取Handl ...

  9. SpringMVC源码解读 - HandlerMapping - SimpleUrlHandlerMapping初始化

    摘要: SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定. 初始化时,通过setMappings(Prop ...

随机推荐

  1. hdu-5744 Keep On Movin(思维)

    题目链接: Keep On Movin Time Limit: 4000/2000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Oth ...

  2. 「UOJ#117」 欧拉回路

    欧拉回路 - 题目 - Universal Online Judge 题意: 给定有向图或无向图,求一条欧拉回路. 题解 心路历程:woc什么傻哔东西->哇真香我的吗!(逃 首先我知道很多人把欧 ...

  3. 关闭页面,window.onunload事件未执行的原因

    1.问题描述: JS中定义widow.onunload= function(),页面关闭时,logout()函数未执行. window.onunload = function() { logout() ...

  4. Appleman and a Sheet of Paper

    题意: 给一纸条,两种操作: 1.将左侧长度为$x$的纸条向右翻折. 2.询问位于$[l,r]$的纸条总长度. 解法: 考虑启发式,每一次一个小纸条折叠我们可以看做是一次合并,如果我们每一次将较小的纸 ...

  5. 2.7-2.8 导入、导出数据(进/出)hive表的方式

    一.导入数据进hive表 1.语法 LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (p ...

  6. laravel SQL语句

    DB::table('表名')->get();   //查询表里的所有数据 DB::table('表名')->where()->find(需要查询的条数);    查询单或多条数据 ...

  7. Forward Rendering 正向渲染

    Forward Rendering 正向渲染        正向渲染一个基于着色器的渲染路径.它支持逐像素计算光照(包括法线贴图和灯光Cookies)和来自一个平行光的实时阴影.在默认设置中,少数最亮 ...

  8. C#基础知识回顾

    值类型和引用类型 值类型存在栈上,结构,枚举,数值类型 引用类型存在堆上,数组,类,接口,委托 把值类型存到引用类型中就是封箱,耗时 引用类型中的值类型是存在堆上,不是栈上,但是作为参数传递时,还是会 ...

  9. 2014-9-9 NOIP模拟赛

    东方幻想乡系列模拟赛Stage 1命题 Nettle审题 Barty ccy1991911 FlanS39 Wagner T2 高精除高精,从来没写过,不知道怎么写,我就用大数减小数ans次,果断超时 ...

  10. 洛谷P1919 【模板】A*B Problem升级版(FFT)

    传送门 话说FFT该不会真的只能用来做这种板子吧…… 我们把两个数字的每一位都看作多项式的系数 然后这就是一个多项式乘法 上FFT就好了 然后去掉前导零 (然而连FFT的板子都背不来orz,而且空间又 ...