Spring MVC-HandlerAdapter

HandlerAdapter接口中定义的方法为ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)看这个方法就明白了,就是HanlerMapping负责找到Handler(更具体的是找到Handler中处理的方法),然后交给HandlerAdapter负责执行这个方法,最终返回视图对象ModelAndView 。
Spring中默认定义的HandlerAdapter为HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter ,重点也就是在这三个类,下面分别来看下关键代码。

  • HttpRequestHandlerAdapter
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         //返回null,相当于空白处理
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
}

具体的处理交给了HttpRequestHandler类,看下这个类的继承关系:
这里写图片描述
这里看下有代表性的DefaultServletHttpRequestHandler类的实现。

public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    RequestDispatcher rd =this.servletContext.getNamedDispatcher(this.defaultServletName);
    //简单的forward
    rd.forward(request, response);
}
  • SimpleControllerHandlerAdapter
    这个类返回的对象是ModelAndView,这是和HttpRequestHandlerAdapter的不同之处。
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler){
    return ((Controller) handler).handleRequest(request, response);
}

通过上面代码我们知道实际的处理在Controller类中。其中handleRequest()的默认实现是在抽象的类AbstractController中。
AbstractController实现了一些特殊功能,如继承了WebContentGenerator缓存控制功能,并提供了可选的会话的串行化访问功能。而且提供了handleRequestInternal方法。

//委托给WebContentGenerator进行缓存控制                                   
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);       
        }                                                          
    }                                                              
}                                                                                                                                

然后看抽象方法handleRequestInternal()在子类中的实现,这里以AbstractUrlViewController为例说明,关键代码如下:、

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);                            
    //交给子类去实现                                                                                           
    String viewName = getViewNameForRequest(request);                                                   
    if (logger.isDebugEnabled()) {                                                                      
        logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");    
    }                                                                                                   
    //这才是关键                                                                                             
    return new ModelAndView(viewName, RequestContextUtils.getInputFlashMap(request));                   
}                                                                                                       

getViewNameForRequest在子类UrlFilenameViewController中实现,看代码:

protected String getViewNameForUrlPath(String uri) {
    String viewName = this.viewNameCache.get(uri);  
    if (viewName == null) {                         
        //通过/index.html得到 index                     
        viewName = extractViewNameFromUrlPath(uri); 
        //将前缀和后缀组合                                  
        viewName = postProcessViewName(viewName);   
        this.viewNameCache.put(uri, viewName);      
    }                                               
    return viewName;                                
}                                                   
  • AnnotationMethodHandlerAdapter
    这是基于注解配置的handler,只要是注解的肯定用到反射调用。
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler){                                                                                                                                                                                                  
    ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);                                      
    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;                                                                                                    
}                                                                                                                  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值