简单直接让你也读懂springmvc源码分析(3.1)-- HandlerMethodReturnValueHandler

该源码分析系列文章分如下章节:

  1. springmvc源码分析(1)-- DispatcherServlet
  2. springmvc源码分析(2)-- HandlerMapping
  3. springmvc源码分析(3)-- HandlerAdapter
  4. springmvc源码分析(3.1)-- HandlerMethodReturnValueHandler
  5. springmvc源码分析(4)-- ViewResolver

该接口的调用请参考springmvc源码分析(3)-- HandlerAdapter

本章只分析该接口的一些用法和常用实现类

该接口有两个方法

public interface HandlerMethodReturnValueHandler {

	/**
	 * Whether the given {@linkplain MethodParameter method return type} is
	 * supported by this handler.
	 * @param returnType the method return type to check
	 * @return {@code true} if this handler supports the supplied return type;
	 * {@code false} otherwise
	 */
	boolean supportsReturnType(MethodParameter returnType);

	/**
	 * Handle the given return value by adding attributes to the model and
	 * setting a view or setting the
	 * {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
	 * to indicate the response has been handled directly.
	 * @param returnValue the value returned from the handler method
	 * @param returnType the type of the return value. This type must have
	 * previously been passed to {@link #supportsReturnType} which must
	 * have returned {@code true}.
	 * @param mavContainer the ModelAndViewContainer for the current request
	 * @param webRequest the current request
	 * @throws Exception if the return value handling results in an error
	 */
	void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}

supportsReturnType表示支持的return类型

handleReturnValue执行实际逻辑

该接口实现默认有n多个,在处理器适配器初始化bean时执行afterPropertiesSet进行构建,我们直接从RequestMappingHandlerAdapter该适配器里开始: 这里我们可以看到进行获取默认HandlerMethodReturnValueHandler列表,getDefaultReturnValueHandlers调用:

private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
		List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();

		// Single-purpose return value types
		handlers.add(new ModelAndViewMethodReturnValueHandler());
		handlers.add(new ModelMethodProcessor());
		handlers.add(new ViewMethodReturnValueHandler());
		handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
				this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
		handlers.add(new StreamingResponseBodyReturnValueHandler());
		handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
				this.contentNegotiationManager, this.requestResponseBodyAdvice));
		handlers.add(new HttpHeadersReturnValueHandler());
		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, this.requestResponseBodyAdvice));

		// 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;
	}

这里面可以看到添加了很多个默认实现类,其中也包括用户自定义的:

我们拿出几个常用到的来分析下:

1.ModelAndViewMethodReturnValueHandler:

这里可以看到支持的返回类型为ModelAndView,当controller执行后返回类型是ModelAndView的,那么将采用该类的handleReturnValue方法进行结果处理:

public boolean isReference() {
		return (this.view instanceof String);
	}

这里处理比较简单直接判断返回的返回的view是否String,是则将视图的名字放入视图容器里,然后接着判断是否重定向是则

setRedirectModelScenario(true)

如果view非String,获取视图对象放入视图容器里然后接着判断是否重定向。

 

2.RequestResponseBodyMethodProcessor:

这里判断仅支持有@ResponseBody注解的返回,也就是我们的接口json返回,那么将用其handleReturnValue调用对我们结果处理:

 设置标识mavContainer.setRequestHandled(true);

接着writeWithMessageConverters,其实调用该方法已经完成进行结果输出了,也就是对浏览器进行响应输出,因为是json,所以不需要进入视图解析器渲染,所以直接输出即可。

当然我们也是可以自定义HandlerMethodReturnValueHandler,在springmvc实用篇 -- WebMvcConfigurer这一章中我们有提到过里面有很多自定义配置供我们添加,其中就有HandlerMethodReturnValueHandler的添加,下面我们来试一下:

1.实现WebMvcConfigurer:

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
        handlers.add(0, new HandlerMethodReturnValueHandler() {
            @Override
            public boolean supportsReturnType(MethodParameter returnType) {
                return UserA.class.isAssignableFrom(returnType.getParameterType()) ;
            }

            @Override
            public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
                mavContainer.setRequestHandled(true);
                HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
                response.getWriter().println("diyReturnValueHandlers:"+returnValue);
            }
        });
    }
}

这里我们设定该返回值处理仅适合UserA,然后进入处理,将结果直接输出到浏览器,mavContainer.setRequestHandled(true)表示不再视图解析

2.创建controller让其返回UserA

@Controller
@RequestMapping("/user")
public class UserController {
   
    @RequestMapping("/user")
    public UserA user() {
        return new UserA("cwh",22);
    }
}

3.访问结果:

ok,一切在我们掌握之中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值