定制app开发springboot Controller接口返回流程详解

目录

前言

定制app开发我们在使用springboot开发rest定制app开发接口时往往是直接写一个接口,定制app开发然后返回对象,定制app开发最后结果就转化为Json定制app开发格式返回了,定制app开发本文就探究下这个过程中是如何完成这个过程的。

源码分析

首先我们写了个最简单的接口,并且返回了一个Test对象

@RestControllerpublic class TestController {    @GetMapping("/test")    public Test test() {        Test test = new Test();        test.setName("my name");        return test;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
@Datapublic class Test {    private String name;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

首先我们都知道springmvc最终是由DispatcherServlet来调用到业务代码的,这个过程此处不做介绍,不了解的可以参考此文:

我们直接看DispatcherServlet的doService方法,本文只拉出核心代码,不抓具体细节

@Override	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {		......		try {			// 核心代码			doDispatch(request, response);		}		finally {			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {				// Restore the original attribute snapshot, in case of an include.				if (attributesSnapshot != null) {					restoreAttributesAfterInclude(request, attributesSnapshot);				}			}		}	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {				......				if (!mappedHandler.applyPreHandle(processedRequest, response)) {					return;				}				// Actually invoke the handler.				// 核心代码,处理业务流程				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());				if (asyncManager.isConcurrentHandlingStarted()) {					return;				}				applyDefaultViewName(processedRequest, mv);				mappedHandler.applyPostHandle(processedRequest, response, mv);			}			......	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

打断点进入AbstractHandlerMethodAdapter的handle

@Override	@Nullable	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)			throws Exception {		return handleInternal(request, response, (HandlerMethod) handler);	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

进入RequestMappingHandlerAdapter的handleInternal

@Override	protected ModelAndView handleInternal(HttpServletRequest request,			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {		ModelAndView mav;		checkRequest(request);		// Execute invokeHandlerMethod in synchronized block if required.		if (this.synchronizeOnSession) {			HttpSession session = request.getSession(false);			if (session != null) {				Object mutex = WebUtils.getSessionMutex(session);				synchronized (mutex) {					mav = invokeHandlerMethod(request, response, handlerMethod);				}			}			else {				// No HttpSession available -> no mutex necessary				// 核心代码,拿到要处理的方法handlerMethod,继续处理业务				mav = invokeHandlerMethod(request, response, handlerMethod);			}		}		else {			// No synchronization on session demanded at all...			mav = invokeHandlerMethod(request, response, handlerMethod);		}		......		return mav;	}
  • 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
@Nullable	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {		ServletWebRequest webRequest = new ServletWebRequest(request, response);		try {			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);			if (this.argumentResolvers != null) {				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);			}			if (this.returnValueHandlers != null) {				// 核心代码1,returnValueHandlers是个集合,包含了很多内置的处理器,根据不同的返回要求处理不同的返回数据				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);			}			invocableMethod.setDataBinderFactory(binderFactory);			......			// 核心代码2,继续处理			invocableMethod.invokeAndHandle(webRequest, mavContainer);			if (asyncManager.isConcurrentHandlingStarted()) {				return null;			}			return getModelAndView(mavContainer, modelFactory, webRequest);		}		finally {			webRequest.requestCompleted();		}	}
  • 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

进入了ServletInvocableHandlerMethod的invokeAndHandle,到这里大概逻辑已经可以看出来了

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,			Object... providedArgs) throws Exception {		// 核心代码1,处理请求,返回了returnValue,很明显就是我们调用http请求查询到的Controller		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);		// 设置返回状态		setResponseStatus(webRequest);		if (returnValue == null) {			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {				mavContainer.setRequestHandled(true);				return;			}		}		else if (StringUtils.hasText(getResponseStatusReason())) {			mavContainer.setRequestHandled(true);			return;		}		mavContainer.setRequestHandled(false);		Assert.state(this.returnValueHandlers != null, "No return value handlers");		try {			// 核心代码2,处理返回结果			this.returnValueHandlers.handleReturnValue(					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);		}		catch (Exception ex) {			if (logger.isTraceEnabled()) {				logger.trace(formatErrorForReturnValue(returnValue), ex);			}			throw ex;		}	}
  • 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
@Nullable	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,			Object... providedArgs) throws Exception {		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);		if (logger.isTraceEnabled()) {			logger.trace("Arguments: " + Arrays.toString(args));		}		// 处理		return doInvoke(args);	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
protected Object doInvoke(Object... args) throws Exception {		ReflectionUtils.makeAccessible(getBridgedMethod());		try {			// 核心代码,这里很明显了,找到要调用的方法,拿到调用的Controller对象,获取到参数,反射调用,然后返回结果			return getBridgedMethod().invoke(getBean(), args);		}		......	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里如何根据http请求找到对应的方法,其实原理也很容易理解,无非就是项目启动时把/url和方法的对应关系保存到ioc容器,在需要使用的时候去查询

至此,我们已经拿到Controller相应的方法调用的结果了,然后我们看handleReturnValue方法。

@Override	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {		// 核心代码1		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);		if (handler == null) {			throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());		}		// 核心代码2		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
@Nullable	private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {		boolean isAsyncValue = isAsyncReturnValue(value, returnType);		// 循环所有返回值处理器,找可以适配的处理器		for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {			if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {				continue;			}			// 调用每一个处理器的supportsReturnType,直到找到适配的处理器			if (handler.supportsReturnType(returnType)) {				return handler;			}		}		return null;	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

supportsReturnType最终匹配到的是RequestResponseBodyMethodProcessor处理器,我们看下他的supportsReturnType方法

@Override	public boolean supportsReturnType(MethodParameter returnType) {		// 判断类上或者方法上是否存在ResponseBody注解,这里我们类上使用了@RestController注解,@RestController默认是		// 引用了@ResponseBody的注解的,所以这里就可以适配了		return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||				returnType.hasMethodAnnotation(ResponseBody.class));	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后调用RequestResponseBodyMethodProcessor的handleReturnValue方法

@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

进入AbstractMessageConverterMethodProcessor的writeWithMessageConverters

protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,			ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {		Object body;		Class<?> valueType;		Type targetType;		if (value instanceof CharSequence) {			body = value.toString();			valueType = String.class;			targetType = String.class;		}		else {			body = value;			valueType = getReturnValueType(body, returnType);			targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());		}		......		MediaType selectedMediaType = null;		MediaType contentType = outputMessage.getHeaders().getContentType();		if (contentType != null && contentType.isConcrete()) {			if (logger.isDebugEnabled()) {				logger.debug("Found 'Content-Type:" + contentType + "' in response");			}			selectedMediaType = contentType;		}		......		// 当前情况下selectedMediaType最终被设置为application/json;q=0.8		if (selectedMediaType != null) {			selectedMediaType = selectedMediaType.removeQualityValue();			// 核心代码1 messageConverters是处理数据的解析器,从所有解析器中找到匹配的处理器			for (HttpMessageConverter<?> converter : this.messageConverters) {				GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?						(GenericHttpMessageConverter<?>) converter : null);				if (genericConverter != null ?						((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :						converter.canWrite(valueType, selectedMediaType)) {					// 主要是根据canWrite来判断,最终找到MappingJackson2HttpMessageConverter解析器					body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,							(Class<? extends HttpMessageConverter<?>>) converter.getClass(),							inputMessage, outputMessage);					if (body != null) {						Object theBody = body;						LogFormatUtils.traceDebug(logger, traceOn ->								"Writing [" + LogFormatUtils.formatValue(theBody, traceOn) + "]");						addContentDispositionHeader(inputMessage, outputMessage);						if (genericConverter != null) {							genericConverter.write(body, targetType, selectedMediaType, outputMessage);						}						else {							// 最终找到MappingJackson2HttpMessageConverter解析器,执行MappingJackson2HttpMessageConverter的write							((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);						}					}					else {						if (logger.isDebugEnabled()) {							logger.debug("Nothing to write: null body");						}					}					return;				}			}		}		if (body != null) {			throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);		}	}
  • 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
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

进入父类AbstractGenericHttpMessageConverter的write

public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,		HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {	final HttpHeaders headers = outputMessage.getHeaders();	addDefaultHeaders(headers, t, contentType);	if (outputMessage instanceof StreamingHttpOutputMessage) {		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;		streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() {			@Override			public OutputStream getBody() {				return outputStream;			}			@Override			public HttpHeaders getHeaders() {				return headers;			}		}));	}	else {		// 核心代码,write body数据到输出流,里面具体就不细看了		writeInternal(t, type, outputMessage);		// flush		outputMessage.getBody().flush();	}}
  • 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

至此,总流程就走完了,数据提供输出流write出去了

总结

梳理下总体流程如下:

  1. 通过DispatcherServlet根据request的信息找到IOC容器中相应的方法,反射调用
  2. 根据注解或者返回值类型找到对应的返回值处理器RequestResponseBodyMethodProcessor
  3. 找到相应的解析器MappingJackson2HttpMessageConverter,这里也就是默认标记了@ResponseBody注解的Controller方法,最终会使用Jackson来进行json序列化,最终返回给客户端
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发