//1 获取handlerAdapter // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); //2 执行handlerAdapter.handle // 以UserController extends MultiActionController extends AbstractController extends WebContentGenerator为例 // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
DispatcherServlet#getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace("Testing handler adapter [" + ha + "]"); } // 1.1 判断handlerAdapter是否适合处理该处理器 if (ha.supports(handler)) { return ha; } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
对于某个系统而言,handlerAdapter一般只用到一种(ps:这个地方是否可以优化),以下以SimpleControllerHandlerAdapter为例
适配器模式-对象适配器模式:-委托关系
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
https://zh.wikipedia.org/wiki/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F
SimpleControllerHandlerAdapter#support
public boolean supports(Object handler) { // 1.1.1 判断处理器是否是Controller实例,如果是则返回该handler return (handler instanceof Controller); }
SimpleControllerHandlerAdapter#handle
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //2.1 调用Controller接口的handleRequest-面向接口编程 return ((Controller) handler).handleRequest(request, response); }
AbstractController#handleRequest
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); }
MultiActionController#handleRequestInternal
@Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { try { //解析方法参数如method=? String methodName = this.methodNameResolver.getHandlerMethodName(request); //根据方法名称,反射调用实例方法 return invokeNamedMethod(methodName, request, response); } catch (NoSuchRequestHandlingMethodException ex) { return handleNoSuchRequestHandlingMethod(ex, request, response); } }
MultiActionController#invokeNamedMethod
protected final ModelAndView invokeNamedMethod( String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception { //获取方法执行体,handlerMethodMap在构造函数里面初始化 Method method = this.handlerMethodMap.get(methodName); if (method == null) { throw new NoSuchRequestHandlingMethodException(methodName, getClass()); } try { //设置方法参数(处理方法前面2个必须是request和response) Class[] paramTypes = method.getParameterTypes(); List
handlerMethodMap在初始化时缓存起来
springmvc 如何根据request设置command对象?
参考:
How to perform Spring validation in MultiActionController?
https://stackoverflow.com/questions/2744587/how-to-perform-spring-validation-in-multiactioncontroller