• 源码解析SpringMVC处理请求的完整流程


    1.WebMvcAutoConfiguration

    在这里插入图片描述
    EnableWebMvcConfiguration自动装配类负责加载SpringMVC涉及的HandlerAdapterHandlerMappingExceptionHandlerExceptionResolver等。
    SpringMVC利用 DispatchServlet 处理上游Tomcat的请求时,会被HandlerMapping、HandlerAdapter的相关子类分别先后执行,这样做的原因是:

    1. 通过RequestUril找到相应的handler是因为HandlerMapping提前建立了 RequestUril & Handler 之间的映射关系。
    2. 不同HandlerMapping表明解析Handler上的Uri方式是不同的。
    3. HandlerAdapter触发执行 Uri 在Handler中的目标方法。

    在这里插入图片描述
    WebMvcAutoConfigurationAdapter自动装配类负责加载SpringMVC涉及的静态资源等Web资源。例如LocaleResolver、视图解析器InternalResourceViewResolver、ContentNegotiatingViewResolver等。

    @Configuration(proxyBeanMethods = false)
    public class WebMvcAutoConfiguration {
    
    	private static final String[] SERVLET_LOCATIONS = { "/" };
    
    	@Configuration(proxyBeanMethods = false)
    	@Import(EnableWebMvcConfiguration.class)
    	@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
    	@Order(0)
    	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    		...
    		@Bean
    		@ConditionalOnBean(ViewResolver.class)
    		@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
    		public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {...}
    		...
    	}
    	// 该注解保证父类WebMvcConfigurationSupport也参与SpringBoot启动过程中各个注解的解析过程
    	@Configuration(proxyBeanMethods = false)
    	public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
    		...
    		@Bean
    		@Override
    		public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
    				@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager m,
    				@Qualifier("mvcConversionService") FormattingConversionService c,
    				@Qualifier("mvcValidator") Validator v) {
    			RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(m,c, v);
    			boolean ignoreDefaultModelOnRedirect = this.mvcProperties.isIgnoreDefaultModelOnRedirect();
    			adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || ignoreDefaultModelOnRedirect);
    			return adapter;
    		}
    		...
    		@Bean
    		@Primary
    		@Override
    		public RequestMappingHandlerMapping requestMappingHandlerMapping(
    				@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager manager,
    				@Qualifier("mvcConversionService") FormattingConversionService conversionService,
    				@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    			// 调用父类WebMvcConfigurationSupport
    			return super.requestMappingHandlerMapping(manager, conversionService,resourceUrlProvider);
    		}
    		...
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    1.2.WebMvcConfigurationSupport

    public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    	@Bean
    	public RequestMappingHandlerMapping requestMappingHandlerMapping(...}
    	
    	@Bean
    	public PathMatcher mvcPathMatcher() {...}
    	
    	@Bean
    	public BeanNameUrlHandlerMapping beanNameHandlerMapping(...}
    	
    	@Bean
    	public HandlerExceptionResolver handlerExceptionResolver(
    			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
    		List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
    		configureHandlerExceptionResolvers(exceptionResolvers);
    		if (exceptionResolvers.isEmpty()) {
    			addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
    		}
    		extendHandlerExceptionResolvers(exceptionResolvers);
    		HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
    		composite.setOrder(0);
    		composite.setExceptionResolvers(exceptionResolvers);
    		return composite;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    1.2.1.生成HandlerMapping

    默认生成的众多HandlerMapping子类中,核心包括RequestMappingHandlerMappingBeanNameUrlHandlerMappingSimpleUrlHandlerMapping

    HandlerMapping其核心功能是建立RequestUri与目标handler之间的映射关系。
    在这里插入图片描述
    RequestMappingHandlerMapping解析的handler其Uri是被注解@RequestMapping标识的。
    BeanNameUrlHandlerMapping解析的Handler其Uri就是该Handler在IOC容器中bean实例对应的beanName。
    SimpleUrlHandlerMapping解析的handler其Uri是显式指定的。如下所示:

    public SimpleUrlHandlerMapping simpleUrlHandlerMapping(){
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        Properties properties = new Properties();
    //      suHm:访问uri,suHmBean:对应的控制器bean
        properties.setProperty("suHm","suHmBean");
        simpleUrlHandlerMapping.setMappings(properties);
        simpleUrlHandlerMapping.setOrder(1);
        return simpleUrlHandlerMapping;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    BeanNameUrlHandlerMapping & SimpleUrlHandlerMapping的异同:

    1. 相同点:两者解析的handler存在的共同点其中一点是都必须实现Controller接口,另外一点是每一个handler跟Uri是一一对应关系。
    2. 不同点:BeanNameUrlHandlerMapping对应的Uri没得选,只能是该handler在IOC容器中bean实例对应的beanName。SimpleUrlHandlerMapping对应的handler其具体的Uri,如上所示,是可以被任意指定的。

    1.2.2.生成HandlerAdapter

    类HandlerAdapter负责触发目标类目标方法的执行。

    BeanNameUrlHandlerMapping & SimpleUrlHandlerMapping对应的HandlerAdapter为SimpleControllerHandlerAdapter。

    RequestMappingHandlerAdapter、SimpleControllerHandlerAdapter是常见的HandlerAdapter,其中SimpleControllerHandlerAdapter负责处理实现接口Controller的handler。
    在这里插入图片描述

    1.2.3.生成HandlerExceptionResolver

    具体参考文章

    2.DispatcherServlet

    public class DispatcherServlet extends FrameworkServlet {
    	protected void doDispatch(HttpServletRequest request, HttpServletResponse response){
    		HttpServletRequest processedRequest = request;
    		HandlerExecutionChain mappedHandler = null;
    		boolean multipartRequestParsed = false;
    	
    		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    	
    		try {
    			ModelAndView mv = null;
    			Exception dispatchException = null;
    			try {
    				processedRequest = checkMultipart(request);
    				multipartRequestParsed = (processedRequest != request);
    				// Determine handler for the current request.
    				mappedHandler = getHandler(processedRequest);
    				...
    				// Determine handler adapter for the current request.
    				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    				// Process last-modified header, if supported by the handler.
    				...
    				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    					return;
    				}
    				// Actually invoke the handler. 
    				// 执行目标类的目标方法,即有可能返回ModelAndView,也可能只有HttpServletResponse。其实ModelAndView是执行完目标方法	
    				//进一步渲染视图,渲染后的视图最终还是通过HttpServletResponse响应到客户端。如果没有视图则ModelAndView为null,最终目标
    				//方法的返回值被对应handler写到HttpServletResponse并响应到客户端。
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    				if (asyncManager.isConcurrentHandlingStarted()) {
    					return;
    				}
    				// 如果存在ModelAndView 则渲染视图,否则直接忽略
    				applyDefaultViewName(processedRequest, mv);
    				mappedHandler.applyPostHandle(processedRequest, response, mv);
    			}...
    			//渲染目标方法返回结果
    			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    		}
    		catch (Exception ex) {
    			mappedHandler.triggerAfterCompletion(request, response, ex);
    		}
    		...
    	}
    	
    	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
    							HandlerExecutionChain mappedHandler,ModelAndView mv,Exception exception) {
    		boolean errorView = false;
    		if (mv != null && !mv.wasCleared()) {
    			// 这种情况主要是对视图View的渲染
    			render(mv, request, response);
    			...
    		}
    		if (mappedHandler != null) {
    			mappedHandler.triggerAfterCompletion(request, response, null);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    对于SimpleControllerHandlerAdapter,其目标方法即为接口Controller的抽象方法,在子类重写其方法内部最终返回值为ModelAndView类型以及HttpServletResponse。如果最终结果存在视图渲染则ModelAndView类型是视图相关内容,最终将HttpServletResponse内部响应结果渲染至ModelAndView代表的视图中。

    2.1.Servlet维护SpringMVC九大组件

    public class DispatcherServlet extends FrameworkServlet {
    
    	private List<HandlerMapping> handlerMappings;
    	private List<HandlerExceptionResolver> handlerExceptionResolvers;
    	private List<HandlerAdapter> handlerAdapters;
    	
    	@Override//Tomcat处理请求过程中触发
    	protected void onRefresh(ApplicationContext context) {
    		initStrategies(context);
    	}
    	
    	protected void initStrategies(ApplicationContext context) {
    		initMultipartResolver(context);
    		initLocaleResolver(context);
    		initThemeResolver(context);
    		//handlerMappings中添加所有元素:从IOC容器中获取HandlerMapping接口的全部相关子类。
    		initHandlerMappings(context);
    		//HandleAdapter中添加所有元素:从IOC容器中获取HandleAdapter接口的全部相关子类。
    		initHandlerAdapters(context);
    		//同理...
    		initHandlerExceptionResolvers(context);
    		initRequestToViewNameTranslator(context);
    		initViewResolvers(context);
    		initFlashMapManager(context);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Servlet容器之Tomcat处理请求过程中触发 初始化SpringMVC九大组件 的流程。此时DispatcherServlet类中集合类型的属性之handlerMappings & handlerExceptionResolvers & handlerAdapters中元素均为SpringBoot自动装配类组件,截止当前所有组件已经初始化完毕,只需从IOC容器获取相关类型的组件即可。目的是用于处理客户端请求,由此得知该集合类型赋值过程有且仅有一次,即处理首次客户端请求。

    2.2.执行HandlerMapping

    着重关注三种类型之RequestMappingHandlerMappingBeanNameUrlHandlerMappingSimpleUrlHandlerMapping的执行流程。

    public class DispatcherServlet extends FrameworkServlet {
    	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    		if (this.handlerMappings != null) {
    			for (HandlerMapping mapping : this.handlerMappings) {
    				HandlerExecutionChain handler = mapping.getHandler(request);
    				if (handler != null) {
    					return handler;
    				}
    			}
    		}
    		return null;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping{
    	
    	public final HandlerExecutionChain getHandler(HttpServletRequest request) {
    		// 通过requestUri获取对应的handler
    		Object handler = getHandlerInternal(request);
    		...
    		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    		...
    		return executionChain;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    其中,RequestMappingHandlerMapping得到的handler类型为HandlerMethod【对目标方法的抽象化】,在HandlerMethod内部维护元素:目标handler的真实类型 以及 目标方法Method

    2.2.1.RequestMappingHandlerMapping

    public class RequestMappingHandlerMapping{
    	@Override
    	protected HandlerMethod getHandlerInternal(HttpServletRequest request){
    		// AbstractHandlerMethodMapping#getHandlerInternal
    		return super.getHandlerInternal(request);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping {
    	@Override
    	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
    		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2.1.BeanNameUrlHandlerMapping & SimpleUrlHandlerMapping

    BeanNameUrlHandlerMapping & SimpleUrlHandlerMapping 该俩HandlerMapping通过requestUri获取得到的handler为接口Controller类型的没有做任何抽象的实际handler。

    2.3.执行HandlerAdapter

    RequestMappingHandlerAdapter、SimpleControllerHandlerAdapter是常见的HandlerAdapter。

    通过如下方法返回符合当前请求的HandlerAdapter。

    public class DispatcherServlet extends FrameworkServlet {
    
    	protected HandlerAdapter getHandlerAdapter(Object handler)  {
    		if (this.handlerAdapters != null) {
    			for (HandlerAdapter adapter : this.handlerAdapters) {
    				if (adapter.supports(handler)) {
    					return adapter;
    				}
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.3.1.RequestMappingHandlerAdapter

    由其抽象类AbstractHandlerMethodAdapter完成目标HandlerAdapter的鉴定条件。

    public abstract class AbstractHandlerMethodAdapter{
    	@Override
    	public final boolean supports(Object handler) {
    		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.3.2.SimpleControllerHandlerAdapter

    符合处理BeanNameUrlHandlerMapping & SimpleUrlHandlerMapping的HandlerAdapter两种类型的HandlerAdapter即为当前的SimpleControllerHandlerAdapter。因为两者HandlerMapping对应目标handler都是直接实现Controller接口。

    public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    
    	@Override
    	public boolean supports(Object handler) {
    		return (handler instanceof Controller);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.执行handler目标方法

    着重分析RequestMappingHandlerAdapter以及SimpleControllerHandlerAdapter。

    3.1.RequestMappingHandlerAdapter

    public abstract class AbstractHandlerMethodAdapter{
    	@Override
    	@Nullable
    	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    			throws Exception {
    		return handleInternal(request, response, (HandlerMethod) handler);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
    		implements BeanFactoryAware, InitializingBean {
    		
    	@Override
    	protected ModelAndView handleInternal(HttpServletRequest request,
    			HttpServletResponse response, HandlerMethod handlerMethod){
    			...
    		return invokeHandlerMethod(request, response, handlerMethod);;
    	}
    	
    	@Nullable
    	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
    			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
    		ServletWebRequest webRequest = new ServletWebRequest(request, response);
    		try {
    			...
    			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
    			//设置目标方法所有参数的抽象体
    			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
    			//设置目标方法返回值的抽象体
    			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
    			...
    			invocableMethod.invokeAndHandle(webRequest, mavContainer);
    			return getModelAndView(mavContainer, modelFactory, webRequest);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3.1.1.ServletInvocableHandlerMethod

    public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
    
    	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
    	
    	public void invokeAndHandle(ServletWebRequest wr,ModelAndViewContainer mc,Object... args){
    		// 调用目标方法得到的实际返回值
    		Object returnValue = invokeForRequest(webRequest, mc, args);
    		if(returnValue == null)return;
    		MethodParameter mp = getReturnValueType(returnValue);
    		// 处理返回值
    		this.returnValueHandlers.handleReturnValue(returnValue, mp, mc, wr);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.2.SimpleControllerHandlerAdapter

    BeanNameUrlHandlerMapping & SimpleUrlHandlerMapping 两者对应的实际handler都是直接实现接口Controller。所以对于上述两种HandlerMapping,当前HandlerAdapter执行两者目标类的目标方法其实都是重写接口Controller的方法handleRequest。

    public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    
    	@Override
    	public boolean supports(Object handler) {
    		return (handler instanceof Controller);
    	}
    
    	@Override
    	@Nullable
    	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    			throws Exception {
    		// 直接调用目标类的目标方法
    		return ((Controller) handler).handleRequest(request, response);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4.响应内容之HandlerMethodReturnValueHandlerComposite

    本章节不分析SpringMVC渲染视图等结果行为,只分析RequestMappingHandlerMapping对应的响应结果。

    public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
    		implements BeanFactoryAware, InitializingBean {
    
    	@Override
    	public void afterPropertiesSet() {
    		// 注意与全部异常拦截的区别
    		initControllerAdviceCache();
    		...
    		if (this.returnValueHandlers == null) {
    			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
    			// 一共提供了15种类型
    			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {
    	//returnValueHandlers元素:支持返回值类型为15种
    	private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<>();
    	
    	public HandlerMethodReturnValueHandlerComposite addHandlers(
    			List<? extends HandlerMethodReturnValueHandler> handlers) {
    	
    		if (handlers != null) {
    			this.returnValueHandlers.addAll(handlers);
    		}
    		return this;
    	}
    	
    	@Override
    	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
    			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    		//将 handler实际返回值returnValue 包装为 ReturnValueMethodParameter类型
    		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    	}
    	
    	@Nullable
    	private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {
    		for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
    			// 本文着重分析handler之RequestResponseBodyMethodProcessor
    			if (handler.supportsReturnType(returnType)) {
    				return handler;
    			}
    		}
    		return null;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    15种返回值类型解析handler,如下所示:
    在这里插入图片描述

    4.1.RequestResponseBodyMethodProcessor

    public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
    	@Override
    	public boolean supportsReturnType(MethodParameter returnType) {
    		//目标类注解中是否存在ResponseBody注解
    		return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
    				// 目标方法是否存在ResponseBody注解
    				returnType.hasMethodAnnotation(ResponseBody.class));
    	}
    	
    	@Override
    	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);
    		// 最后通过响应头的响应类型返回,否则根据目标方法实际返回值类型返回
    		// Try even with null return value. ResponseBodyAdvice could get involved.
    		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    KUKA机器人后台控制程序(SPS)介绍
    基于python的CLI应用程序开发(第一节):简单了解一下Typer
    【Mybatis】使用PageHelper进行分页查询
    Day18_8 Java学习之缓冲流、转换流与序列化流
    【ARKUI】HarmonyOS 如何设置桌面壁纸
    Spring配置文件的详细介绍
    RS485电工详解
    c++视觉--通道分离,合并处理,在分离的通道中的ROI感兴趣区域里添加logo图片
    基于Spark的大规模日志分析
    QT中的JSON存储时无序问题的思考与解决
  • 原文地址:https://blog.csdn.net/qq_36851469/article/details/133932152