环境:Springboot2.4.11
工作原理
先来看看Controller接口的返回值是如何做输出的,以如下接口为例:
@GetMapping("/rv")
public Users us() {
return new Users() ;
}
实际方法的执行是在HandlerAdapter中执行,默认实现是
RequestMappingHandlerAdapter
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// ...
// 为方法的执行设置返回值处理句柄
// this.returnValueHandlers = HandlerMethodReturnValueHandlerComposite
// 在HandlerMethodReturnValueHandlerComposite中保存了当前容器中的所有HandlerMethodReturnValueHandler集合
// 值是在afterPropertiesSet中设置
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
// ...
// 执行方法调用
invocableMethod.invokeAndHandle(webRequest, mavContainer);
// ...
}
}
执行方法调用
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 执行方法调用,获取接口执行的返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// ...
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
}
接口返回值处理
public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 遍历所有的HandlerMethodReturnValueHandler,找出合适的对象
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
// ...
// 调用HandlerMethodReturnValueHandler#handleReturnValue方法处理返回结果信息
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
// 上面的selectHandler方法查找合适的HandlerMethodReturnValueHandler方法。
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
// ...
// 调用每一个Handler的supportsReturnType判断是否支持当前接口的返回值对象
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
}
向客户端响应数据调用
HandlerMethodReturnValueHandler#handleReturnValue方法,根据上面的示例确定RequestResponseBodyMethodProcessor处理返回值。
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// 该方法中会对返回值进行转换(HttpMessageConverter),然后对内容进行输出到客户端(默认就是JSON)
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
}
到这里知道了原理输出的内容,如何进行输出是由
HandlerMethodReturnValueHandler对象决定的那么接下来就可以自定义HandlerMethodReturnValueHandler对象进行输出了。
自定义HandlerMethodReturnValueHandler
自定义
public class CustomHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 如果返回值类型为Users则匹配,就会调用下面的方法进行内容的输出
return returnType.getParameterType() == Users.class ;
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
HttpServletResponse response = (HttpServletResponse) webRequest.getNativeResponse() ;
PrintWriter out = response.getWriter() ;
out.println("Custom HandlerMethodReturnValueHandler") ;
out.flush() ;
out.close() ;
}
}
注册自定义的
HandlerMethodReturnValueHandler对象
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
handlers.add(new CustomHandlerMethodReturnValueHandler()) ;
}
}
测试
发现并没有生效,按照原来的内容进行了输出。
分析原因
先看自定义的是否生效被注册了
通过调试发现自定义的确实被注册了,但是呢
RequestResponseBodyMethodProcessor系统默认的这个处理器在前,所以被它处理了。
通过查看源码知道了HandlerAdapter是如何定义这些系统默认的处理器和自定义处理器的
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
public void afterPropertiesSet() {
// ...
if (this.returnValueHandlers == null) {
// 在这个getDefaultReturnValueHandlers方法中处理
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);
// ...
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice));
// ...
// 自定义返回值类型处理器
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
return handlers;
}
}
通过源码查看 本身自定义的就会排在
RequestResponseBodyMethodProcessor后面,同时
HandlerMethodReturnValueHandler也没有实现Ordered接口,我们也没法进行排序。
接下来我们可以通过如下的方式来使其生效
重新设置
HandlerMethodReturnValueHandler,把自定义的添加到最前面。
测试
生效,成功了!!!
完毕!!!
求个关注+转发
公众:Springboot实战案例锦集
本文暂时没有评论,来添加一个吧(●'◡'●)