Insight springmvc 对controller 结果的处理

Insight 目的:从处理request 流程学习 springmvc 对各种返回结果处理的设计思路、了解处理优先级Rule。

另外,通过对比Deprecated 以及推荐的实现,看spring是如何设计的。

...

核心class: DispatcherServlet,核心方法: doDispatch.

springmvc 会根据controller 执行方法的returnType 决定response 的处理。

1、废弃的实现:具体体现在HandlerAdapter.handle 调用完handlerMethod(即:controller 方法)后对result 的的处理。对于result 处理靠的是if-else 逻辑实现,优先级Rule参考代码。

// @Deprecated
public ModelAndView getModelAndView(Method handlerMethod, Class handlerType, Object returnValue, ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {

    ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
    if (responseStatusAnn != null) {
    	HttpStatus responseStatus = responseStatusAnn.value();
    	String reason = responseStatusAnn.reason();
    	if (!StringUtils.hasText(reason)) {
            webRequest.getResponse().setStatus(responseStatus.value());
    	}
    	else {
            webRequest.getResponse().sendError(responseStatus.value(), reason);
    	}
    
    	// to be picked up by the RedirectView
    	webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, responseStatus);
    
    	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;
    }
    else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
    	handleResponseBody(returnValue, webRequest);
    	return null;
    }
    else if (returnValue instanceof ModelAndView) {
    	ModelAndView mav = (ModelAndView) returnValue;
    	mav.getModelMap().mergeAttributes(implicitModel);
    	return mav;
    }
    else if (returnValue instanceof Model) {
        return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
    }
    else if (returnValue instanceof View) {
        return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
    }
    else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
        addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
        return new ModelAndView().addAllObjects(implicitModel);
    }
    else if (returnValue instanceof Map) {
        return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map) returnValue);
    }
    else if (returnValue instanceof String) {
        return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
    }
    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);
    }
}
...

2、推荐的实现:调用handlerMethod 实现是通过create ServletInvocableHandlerMethod完成的。ServletInvocableHandlerMethod对于result 处理通过检测、委派的机制实现,优先级Rule有明显变化,参考一下的源码。

需要注意的是:create HandlerMethod 的过程中,HandlerMethodReturnValueHandler 组件来源于容器的启动过程中,参考:mvc:annotation-driven 处理过程。

HandlerMethodReturnValueHandler 组件列表:

/**
 * Return the list of return value handlers to use including built-in and
 * custom handlers provided via setReturnValueHandlers. 注意注册的优先级-顺序
 */
private List
   
   
    
     getDefaultReturnValueHandlers() {
    List
    
    
     
      handlers = new ArrayList
     
     
      
      ();
    
    // Single-purpose return value types
    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ModelMethodProcessor());
    handlers.add(new ViewMethodReturnValueHandler());
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
    
    // Annotation-based return value types
    handlers.add(new ModelAttributeMethodProcessor(false));
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
    
    // Multi-purpose return value types
    handlers.add(new ViewNameMethodReturnValueHandler());
    handlers.add(new MapMethodProcessor());
    
    // Custom return value types
    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }
    
    // Catch-all
    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    }
    else {
        handlers.add(new ModelAttributeMethodProcessor(true));
    }
    
    return handlers;
}
     
     
    
    
   
   
tips: return-value-handlers 初始化是在RequestMappingHandlerAdapter.afterPropertiesSet()。

...

设计借鉴:

1.对于不同返回结果-处理的设计,可以采用if-else,但这样的设计可扩展性差;可以将处理抽象为接口,根据业务分发不同的处理逻辑 implement this Interface。

2.采用了Composite 设计模式去实现,具体参考HandlerMethodReturnValueHandlerComposite,实现了handler-method 对于各种返回结果情况处理的解耦。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值