在上一篇HandlerMapping中,HandlerMapping在初始化时就将@RequestMapping对应的url与Controller建立了对应关系,前端的Http请求通过对应关系找到Controller,这就是HandlerMapping的使命,接下来就是HandlerAdapter来进行处理了。在HandlerMapping中有讲到DispatcherServlet的初始化中会调用initStrategies()方法,这里面也包含了HanderAdapter的初始化
initHandlerAdapters(context);
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.
AnnotationAwareOrderComparator.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");
}
}
}
同HandlerMapping初始化一样,默认的HanderAdapter实现也是配置在DispatcherServlet.properties文件中
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
配置可以看出,HandlerAdapter默认有三种类型的实现,分别是:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter
现在回到DispatcherServlet中来,看到请求处理的方法doDispatch()方法中有这么一段:
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
这段就是通过HandlerMapping返回的Handler,来找到对应的Controller执行相应的逻辑,下面我们来具体看一下内部实现
//重点看一下AnnotationMethodHandlerAdapter的handler方法
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//获取class对象
Class<?> clazz = ClassUtils.getUserClass(handler);
//检查class对象是否含有SessionAttributes注解
Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
if (annotatedWithSessionAttributes == null) {
annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
}
if (annotatedWithSessionAttributes) {
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
}
else {
checkAndPrepare(request, response, true);
}
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return invokeHandlerMethod(request, response, handler);
}
}
}
//重点是invoke方法来做的调用
return invokeHandlerMethod(request, response, handler);
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//我们知道handler就是从上一步HandlerMapping拿到的Controller,这里通过handler拿到HandlerMethodResolver
//那HandlerMethodResolver到底是个什么鬼?它里面主要是存储Controller中方法上@RequestMapping的url以及所有的方法
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
//通过methodResolver与当前的request进行匹配,通过请求的url找到需要调用的方法
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ExtendedModelMap implicitModel = new BindingAwareModelMap();
//重点看该方法调用,看下面具体源码
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
ModelAndView mav =
methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
return mav;
}
public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
try {
boolean debug = logger.isDebugEnabled();
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
if (attrValue != null) {
implicitModel.addAttribute(attrName, attrValue);
}
}
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
}
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
continue;
}
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
if ("".equals(attrName)) {
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
}
if (!implicitModel.containsAttribute(attrName)) {
implicitModel.addAttribute(attrName, attrValue);
}
}
//这里即将调用方法的参数,对参数进行处理
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
}
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
//将参数传入,利用反射来进行方法调用
return handlerMethodToInvoke.invoke(handler, args);
}
catch (IllegalStateException ex) {
// Internal assertion failed (e.g. invalid signature):
// throw exception with full handler method context...
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
}
catch (InvocationTargetException ex) {
// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
ReflectionUtils.rethrowException(ex.getTargetException());
return null;
}
}
好,进行到这里已经调用完了方法,再回到上一步看看返回值的情况
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//我们知道handler就是从上一步HandlerMapping拿到的Controller,这里通过handler拿到HandlerMethodResolver
//那HandlerMethodResolver到底是个什么鬼?它里面主要是存储Controller中方法上@RequestMapping的url以及所有的方法
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
//通过methodResolver与当前的request进行匹配,通过请求的url找到需要调用的方法
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ExtendedModelMap implicitModel = new BindingAwareModelMap();
//进行方法调用返回Object
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
//将返回的Object对象进行封装,返回ModelAndView给DispatcherServlet
ModelAndView mav =
methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
//BindingResult、SessionAttribute等后续处理
methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
//处理完成,返回ModelAndView给Dispathcher
return mav;
}
下面来看一下ModelAndView是个啥?
//根据handler处理的结果,封装一个ModelAndView给前端
public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {
ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class);
if (responseStatus != null) {
HttpStatus statusCode = responseStatus.code();
String reason = responseStatus.reason();
if (!StringUtils.hasText(reason)) {
webRequest.getResponse().setStatus(statusCode.value());
}
else {
webRequest.getResponse().sendError(statusCode.value(), reason);
}
// to be picked up by the RedirectView
webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, statusCode);
this.responseArgumentUsed = true;
}
// Invoke custom resolvers if present...
if (customModelAndViewResolvers != null) {
for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
ModelAndView mav = mavResolver.resolveModelAndView(
handlerMethod, handlerType, returnValue, implicitModel, webRequest);
if (mav != ModelAndViewResolver.UNRESOLVED) {
return mav;
}
}
}
//以下是判断返回值的各种类型,给出不同的处理
if (returnValue instanceof HttpEntity) {
handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest);
return null;
}
//@ResponseBody注解的处理
else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
handleResponseBody(returnValue, webRequest);
return null;
}
//看这里,就是我们很熟悉的ModelAndView的处理
else if (returnValue instanceof ModelAndView) {
ModelAndView mav = (ModelAndView) returnValue;
mav.getModelMap().mergeAttributes(implicitModel);
return mav;
}
//返回Model
else if (returnValue instanceof Model) {
return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
}
//返回View
else if (returnValue instanceof View) {
return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
}
//@ModelAttribute注解的处理
else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
return new ModelAndView().addAllObjects(implicitModel);
}
//返回Map
else if (returnValue instanceof Map) {
return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue);
}
//返回String
else if (returnValue instanceof String) {
return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
}
//返回null的处理
else if (returnValue == null) {
// Either returned null or was 'void' return.
if (this.responseArgumentUsed || webRequest.isNotModified()) {
return null;
}
else {
// Assuming view name translation...
return new ModelAndView().addAllObjects(implicitModel);
}
}
else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
// Assume a single model attribute...
addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
return new ModelAndView().addAllObjects(implicitModel);
}
else {
throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
}
}
总结一下:
- HanderAdapter从上一步HandlerMapping拿到Controller
- 通过Controller,经过反射拿到Controller中@requestMapping上url与方法的对应关系,返回ServletHandlerMethodResolver
- 通过request请中的url与ServletHandlerMethodResolver中的mappings匹配,可以找到需要调用的方法
- 利用反射调用找到的方法,返回Object
- 处理返回结果,根据不同的返回值类型(ModelAndView、String、Map、View等)进行处理后,封装成ModelAndView返回给前台