Springboot中HandlerInterceptor与HttpMessageConverter异常冲突

为何要讲HandlerInterceptorHttpMessageConverter异常冲突呢?其实社区也有不少文章讲过(没有讲清楚),很多时候也存在滥用的情况,这里更多是从源码分析他们,并从中学习spring在请求处理这块优秀之处。

目录

示例代码

HandlerInterceptor

基础知识

源码

HttpMessageConverter

基础知识:HandlerAdapter

基础知识:ServletInvocableHandlerMethod

基础知识:HandlerMethodArgumentResolver

基础知识:HandlerMethodReturnValueHandler

RequestResponseBodyMethodProcessor源码

HttpMessageConverter源码

总结


示例代码

下面提供的示例代码(可能比较复杂),UserSecurityInterceptor对未登陆的进行拦截,ESBMessageConverter主要是对url中存在“*/esb/*”的请求报文进行解析(当请求Controller(public ResponseVO test2(@RequestBody RequestVO requestVO) 它把request body内容(提前部分)填充到的RequestVO中,并把返回的ResponseVO再按某种封装成一个新的VO返回 )。

//这是一个请求拦截器
@Configuration
public class UserSecurityInterceptor extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String[] securityUrls = new String[]{"/**"};
        String[] excludeUrls = new String[]{"/**/esb/**", "/**/dictionary/**"};        registry.addInterceptor(userLoginInterceptor()).addPathPatterns(securityUrls).excludePathPatterns(excludeUrls);
        super.addInterceptors(registry);
    }
    @Bean
    public AuthInterceptor userLoginInterceptor() {
        return new AuthInterceptor();
    }
    public class AuthInterceptor implements HandlerInterceptor {
        public Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);
        @Autowired
        private ApplicationContext applicationContext;
        public AuthInterceptor() {
        }
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            LoginUserInfo user = null;
            try {
                user = (LoginUserInfo) SSOUserUtils.getCurrentLoginUser();
            } catch (Exception e) {
                logger.error("从SSO登录信息中获取用户信息失败! 详细错误信息:%s", e);
                throw new ServletException("从SSO登录信息中获取用户信息失败!", e);
            }

            String[] profiles = applicationContext.getEnvironment().getActiveProfiles();
            if (!Arrays.isNullOrEmpty(profiles)) {
                if ("dev".equals(profiles[0])) {
                    return true;
                }
            }
            if (user == null || UserUtils.ANONYMOUS_ROLE_ID.equals(user.getRoleId())) {
                throw new ServletException("获取登录用户信息失败!");
            }
            return true;
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        }
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        }
    }
}
@Configuration
public class Esbconfig {
    @Bean
    public JSONMessageConverter jsonMessageConverter(ESBMessageConverter esbMessageConverter, GsonHttpMessageConverter gsonHttpMessageConverter) {
        JSONMessageConverter jsonMessageConverter = new JSONMessageConverter();
        Map<HttpMessageConverter, List<String>> converterPathMap = new HashMap<>();
        List<String> path = new ArrayList<>();
        path.add("/**/esb/**");
        converterPathMap.put(esbMessageConverter, path);
        jsonMessageConverter.setConverterPathMap(converterPathMap);
		
        List<String> swagger = new ArrayList<>();
        swagger.add("/");
        converterPathMap.put(gsonHttpMessageConverter, swagger);
        jsonMessageConverter.setConverterPathMap(converterPathMap);
        return jsonMessageConverter;
    }
	@Bean
    public ESBMessageConverter esbMessageConverter(ServerConfiguration serverConfiguration) {
        ESBMessageConverter esbMessageConverter = new ESBMessageConverter();
        List<MediaType> mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        esbMessageConverter.setSupportedMediaTypes(mediaTypes);
        esbMessageConverter.setObjectMapper(JsonMapperHolder.objectMapper);
        esbMessageConverter.setServerConfiguration(serverConfiguration);
        return esbMessageConverter;
    }
}
//这是一个MessageConverter
public class ESBMessageConverter extends MappingJackson2HttpMessageConverter implements InitializingBean {
    public static final Logger ESB_LOGGER = LoggerFactory.getLogger(ESBMessageConverter.class);
    private ObjectMapper objectMapper = EntityUtils.OBJECT_MAPPER;
    private String jsonPrefix;
    private Boolean prettyPrint;
    private ServerConfiguration serverConfiguration;
    public ESBMessageConverter() {
        super();
    }
    @Override
    public void setObjectMapper(final ObjectMapper objectMapper) {
        Assert.notNull(objectMapper, "ObjectMapper must not be null");
        this.objectMapper = objectMapper;
        configurePrettyPrint();
    }
    private void configurePrettyPrint() {
        if (this.prettyPrint != null) {
            this.objectMapper.configure(SerializationFeature.INDENT_OUTPUT, this.prettyPrint);
        }
    }
    @Override
    public ObjectMapper getObjectMapper() {
        return this.objectMapper;
    }
    @Override
    public void setJsonPrefix(final String jsonPrefix) {
        this.jsonPrefix = jsonPrefix;
    }
    @Override
    public void setPrefixJson(final boolean prefixJson) {
        this.jsonPrefix = prefixJson ? "{} && " : null;
    }
    @Override
    public void setPrettyPrint(final boolean prettyPrint) {
        this.prettyPrint = prettyPrint;
        configurePrettyPrint();
    }
    @Override
    public boolean canRead(final Class<?> clazz, final MediaType mediaType) {
        return canRead(clazz, null, mediaType);
    }
    @Override
    public boolean canRead(final Type type, final Class<?> contextClass, final MediaType mediaType) {
        final JavaType javaType = getJavaType(type, contextClass);
        return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
    }
    @Override
    public boolean canWrite(final Class<?> clazz, final MediaType mediaType) {
        return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
    }
    @Override
    protected boolean supports(final Class<?> clazz) {
        throw new UnsupportedOperationException();
    }
    @Override
    protected Object readInternal(final Class<?> clazz, final HttpInputMessage inputMessage)
            throws IOException {

        final JavaType javaType = getJavaType(clazz, null);
        return readJavaType(javaType, inputMessage);
    }
    @Override
    public Object read(final Type type, final Class<?> contextClass, final HttpInputMessage inputMessage)
            throws IOException {

        final JavaType javaType = getJavaType(type, contextClass);
        return readJavaType(javaType, inputMessage);
    }
    private Object readJavaType(final JavaType javaType, final HttpInputMessage inputMessage) {
        try {
            final Request<Object> request = objectMapper.readValue(inputMessage.getBody(), Request.class);
            if (request.getHeader() == null) {
                request.setHeader(new RequestHeader());
            }
            if (ESB_LOGGER.isDebugEnabled()) {
                ESB_LOGGER.debug("ESB请求报文为:\n{}", objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(request));
            }
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            HttpServletRequest httpServletRequest;
            if (requestAttributes != null) {
                ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
                httpServletRequest = servletRequestAttributes.getRequest();
                httpServletRequest.setAttribute(ESBConstants.ESB_REQUEST, request);
            }
            return buildRequestBody(javaType, request);
        } catch (final IOException ex) {
            throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
        }
    }
    private Object buildRequestBody(JavaType javaType, Request<Object> request) throws IOException {
        Object obj = request.getBody();
        if (obj instanceof List) {
            if (javaType.isArrayType()) {
                String body = EntityUtils.toJSONString(obj);
                return objectMapper.readValue(body, javaType);
            }
        } else if (obj instanceof Map) {
            obj = EntityUtils.map2Bean((Map<String, Object>) request.getBody(), javaType.getRawClass());
        }
        request.setBody(obj);
        if (serverConfiguration.getServerPlugins() != null && !serverConfiguration.getServerPlugins().isEmpty()) {
            List<ServerPlugin> serverPlugins = serverConfiguration.getServerPlugins();
            for (ServerPlugin serverPlugin : serverPlugins) {
                serverPlugin.afterRequest(request);
            }
        }
        return obj;
    }
    @Override
    protected void writeInternal(final Object object, final HttpOutputMessage outputMessage)
            throws IOException {
        ServletResponse servletResponse = RequestAndResponseContextHolder.response();
        if (servletResponse != null) {
            servletResponse.setContentType("application/json");
        }
        final JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
        final JsonGenerator jsonGenerator =
                this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
        if (this.objectMapper.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
            jsonGenerator.useDefaultPrettyPrinter();
        }
        try {
            if (this.jsonPrefix != null) {
                jsonGenerator.writeRaw(this.jsonPrefix);
            }
            final Response response = buildResponse(object);
            if (serverConfiguration.getServerPlugins() != null && !serverConfiguration.getServerPlugins().isEmpty()) {
                List<ServerPlugin> serverPlugins = serverConfiguration.getServerPlugins();
                for (ServerPlugin serverPlugin : serverPlugins) {
                    serverPlugin.beforeResponse(response);
                }
            }
            if (ESB_LOGGER.isDebugEnabled()) {
                ESB_LOGGER.debug("ESB响应报文为:\n{}", EntityUtils.toJSONString(response));
            }
            this.objectMapper.writeValue(jsonGenerator, response);
        } catch (final JsonProcessingException ex) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }
    /**
     * 构造响应消息
     *
     * @param object
     * @return
     */
    private Response buildResponse(Object object) {
        HttpServletRequest servletRequest = ESBCommonKit.request();
        Request request = (Request) servletRequest.getAttribute(ESBConstants.ESB_REQUEST);
        RequestHeader requestHeader = request.getHeader();
        final Response response = new Response();
        final ResponseHeader header = new ResponseHeader();
        header.setReqSysCode(requestHeader.getReqSysCode());
        header.setServiceCode(requestHeader.getServiceCode());
        header.setProviderSysId(serverConfiguration.getProviderSysId());
        header.setReturnCode(ResponseHeader.DEFAULT_SUCCESS_CODE);
        header.setReturnMessage(null);
        header.setSerialNumber(requestHeader.getSerialNumber());
        response.setHeader(header);
        response.setBody(object);
        return response;
    }
    @Override
    protected JavaType getJavaType(final Type type, final Class<?> contextClass) {
        return (contextClass != null) ?
                this.objectMapper.getTypeFactory().constructType(type, contextClass) :
                this.objectMapper.constructType(type);
    }
    @Override
    protected JsonEncoding getJsonEncoding(final MediaType contentType) {
        if (contentType != null && contentType.getCharSet() != null) {
            final Charset charset = contentType.getCharSet();
            for (final JsonEncoding encoding : JsonEncoding.values()) {
                if (charset.name().equals(encoding.getJavaName())) {
                    return encoding;
                }
            }
        }
        return JsonEncoding.UTF8;
    }
    public ServerConfiguration getServerConfiguration() {
        return serverConfiguration;
    }
    public void setServerConfiguration(ServerConfiguration serverConfiguration) {
        this.serverConfiguration = serverConfiguration;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(serverConfiguration, "请配置ESB接收服务端配置信息");
    }
}

HandlerInterceptor

基础知识

在DispatcherServlet中,每个request根据url在HandlerMapping(@RequestMapping的解析)中拿到一个对应处理程序执行链HandlerExecutionChain,它内部可以定义各种HandlerInterceptor和一个处理器 handler【如:HandlerMethod 】)

Workflow interface that allows for customized handler execution chains. Applications can register any number of existing or custom interceptors for certain groups of handlers, to add common preprocessing behavior without needing to modify each handler implementation.

A HandlerInterceptor gets called before the appropriate HandlerAdapter triggers the execution of the handler itself. This mechanism can be used  for a large field of preprocessing aspects, e.g. for authorization checks, or common handler behavior like locale or theme changes. Its main purpose  is to allow for factoring out repetitive handler code.

源码

HandlerInterceptor是工作流接口,而它执行在HandlerAdapter(真正处理请求)前后,看源码吧

public interface HandlerInterceptor {
	//拦截一个处理程序的执行,在执行HandlerAdapter之前运行
	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception;
	//HandlerAdapter执行完之后,但在renders the view之前
	void postHandle(
			HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception;
	//请求处理完成后的回调,rendering the view之后
	void afterCompletion(
			HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception;
}
//请求执行链
public class HandlerExecutionChain {
	//决定HandlerAdapter
	private final Object handler;
	private HandlerInterceptor[] interceptors;
	//执行一组HandlerInterceptor.preHandle
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}
	//执行一组HandlerInterceptor.postHandle
	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}
	//执行一组HandlerInterceptor.afterCompletion
	void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = this.interceptorIndex; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				try {
					interceptor.afterCompletion(request, response, this.handler, ex);
				}
				catch (Throwable ex2) {
					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
				}
			}
		}
	}
	//执行一组AsyncHandlerInterceptor.afterConcurrentHandlingStarted
	void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = interceptors.length - 1; i >= 0; i--) {
				if (interceptors[i] instanceof AsyncHandlerInterceptor) {
					try {
						AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
						asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
					}
					catch (Throwable ex) {
						logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
					}
				}
			}
		}
	}
}
public class DispatcherServlet extends FrameworkServlet {
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		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);
				// 获取一个HandlerExecutionChain
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}
				// 获取一个HandlerAdapter链
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
				// 执行HandlerExecutionChain.applyPreHandle
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
				//执行请求
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}                
				applyDefaultViewName(processedRequest, mv);
				// 执行HandlerExecutionChain.applyPreHandle
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			// 执行HandlerExecutionChain.triggerAfterCompletion
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			// 执行HandlerExecutionChain.triggerAfterCompletion
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			// 执行HandlerExecutionChain.triggerAfterCompletion
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {//异步时
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}
}

HttpMessageConverter

如果你可以看懂下面的执行链(response返回的调用链),那基础知识就可以跳过

org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
 at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113)
     at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
      at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174)
       at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:247)
        at com.kxtx.esb.api.converter.JSONMessageConverter.write(JSONMessageConverter.java:81)
         at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:226)
          at com.kxtx.esb.api.converter.ESBMessageConverter.writeInternal(ESBMessageConverter.java:199)

基础知识:HandlerAdapter

先获取某个HandlerAdapter,而获取的关键方法supports(判断是否支持适配此handler),它有三个实现:

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
    public final boolean supports(Object handler) {
        return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    }
	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		return true;
	}
	@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
				//ServletInvocableHandlerMethod下面讲
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// 根据HandlerMethod创建WebDataBinder和ServletInvocableHandlerMethod并执行ServletInvocableHandlerMethod
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}
		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}
}
  • HttpRequestHandlerAdapter,认为只要handler属于Controller类型(如:SimpleControllerHandlerAdapter),交由此处理
  • SimpleControllerHandlerAdapter,认为只要handler属于HttpRequestHandler类型,交由此处理
  • RequestMappingHandlerAdapter,认为只要handler属于HandlerMethod类型,交由此处理

注:handler是从HandlerExecutionChain中获取(前面讲过)

RequestMappingHandlerAdapter通过handleInternal处理用户的请求,它有内部有HandlerMethodReturnValueHandler(输入参数处理,有需要就集成HttpMessageConverter)、HandlerMethodArgumentResolver(输出参数处理,有需要就集成HttpMessageConverter)。而真正的请求时交由ServletInvocableHandlerMethodInvocableHandlerMethod的子类)处理的。

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
		implements BeanFactoryAware, InitializingBean {
	private List<HandlerMethodArgumentResolver> customArgumentResolvers;
	private HandlerMethodArgumentResolverComposite argumentResolvers;
	private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
	//处理请求
	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);
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			invocableMethod.setDataBinderFactory(binderFactory);
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);

			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			asyncManager.setTaskExecutor(this.taskExecutor);
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			if (asyncManager.hasConcurrentResult()) {
				Object result = asyncManager.getConcurrentResult();
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				asyncManager.clearConcurrentResult();
				if (logger.isDebugEnabled()) {
					logger.debug("Found concurrent result value [" + result + "]");
				}
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}
			//执行ServletInvocableHandlerMethod.invokeAndHandle
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}
}
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//InvocableHandlerMethod.invokeForRequest
		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);
		try {
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
			}
			throw ex;
		}
	}
}

基础知识:ServletInvocableHandlerMethod

它核心处理逻辑:

  • 输入参数处理,包括数据的转换
  • 调用 handler method,获取返回参数(使用反射的调用@RequestMapping注解的方法)
  • 处理返回参数,并包装成ModelAndView
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
    //MethodReturnValue的集合,也是由RequestMappingHandlerAdapter创建
	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//子类实现
		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);
		try {
			//handle method返回值处理
			this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
			}
			throw ex;
		}
	}
}
public class InvocableHandlerMethod extends HandlerMethod {
    // WebDataBinder是由RequestMappingHandlerAdapter.invokeHandlerMethod创建
    private WebDataBinderFactory dataBinderFactory;
    //MethodArgumentResolver的集合,也是由RequestMappingHandlerAdapter创建
    private HandlerMethodArgumentResolverComposite argumentResolvers = new HandlerMethodArgumentResolverComposite();

    public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(this.getMethod(), this.getBeanType()) + "' with arguments " + Arrays.toString(args));
        }

        Object returnValue = this.doInvoke(args);
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Method [" + ClassUtils.getQualifiedMethodName(this.getMethod(), this.getBeanType()) + "] returned [" + returnValue + "]");
        }

        return returnValue;
    }
    // 核心逻辑,从request中获取入参,然后解析成handler method中的参数
    private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        MethodParameter[] parameters = this.getMethodParameters();
        Object[] args = new Object[parameters.length];

        for(int i = 0; i < parameters.length; ++i) {
            MethodParameter parameter = parameters[i];
            parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
            args[i] = this.resolveProvidedArgument(parameter, providedArgs);
            if (args[i] == null) {
                if (this.argumentResolvers.supportsParameter(parameter)) {
                    try {
                        args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
                    } catch (Exception var9) {
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug(this.getArgumentResolutionErrorMessage("Failed to resolve", i), var9);
                        }

                        throw var9;
                    }
                } else if (args[i] == null) {
                    throw new IllegalStateException("Could not resolve method parameter at index " + parameter.getParameterIndex() + " in " + parameter.getMethod().toGenericString() + ": " + this.getArgumentResolutionErrorMessage("No suitable resolver for", i));
                }
            }
        }
        return args;
    }
}
//HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler的创建
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
	//由afterPropertiesSet调用
	private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
		// Annotation-based argument resolution
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());
		// Type-based argument resolution
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		resolvers.add(new ModelMethodProcessor());
		resolvers.add(new MapMethodProcessor());
		resolvers.add(new ErrorsMethodArgumentResolver());
		resolvers.add(new SessionStatusMethodArgumentResolver());
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
		// Custom arguments
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}
		// Catch-all
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		resolvers.add(new ServletModelAttributeMethodProcessor(true));
		return resolvers;
	}
	//由afterPropertiesSet调用
	private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
		List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();
		// Single-purpose return value types
		handlers.add(new ModelAndViewMethodReturnValueHandler());
		handlers.add(new ModelMethodProcessor());
		handlers.add(new ViewMethodReturnValueHandler());
		handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters()));
		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;
	}
}

基础知识:HandlerMethodArgumentResolver

spring对其支持情况

HandlerMethodArgumentResolver子类注解 or 类
RequestParamMapMethodArgumentResolver@RequestParam
RequestHeaderMapMethodArgumentResolver@RequestHeader
PathVariableMapMethodArgumentResolver@PathVariable
ModelAttributeMethodProcessor@ModelAttribute
RequestResponseBodyMethodProcessor@RequestBody
更多 

基础知识:HandlerMethodReturnValueHandler

spring对其支持情况

HandlerMethodReturnValueHandler子类注解 or 类
ModelAndViewMethodReturnValueHandlerModelAndView
ModelMethodProcessorModel
ViewMethodReturnValueHandlerView
ResponseBodyEmitterReturnValueHandlerResponseEntity
StreamingResponseBodyReturnValueHandlerStreamingResponseBody
HttpEntityMethodProcessorHttpEntity
HttpHeadersReturnValueHandlerHttpHeaders
CallableMethodReturnValueHandler异步Callable
DeferredResultMethodReturnValueHandler异步DeferredResult
AsyncTaskMethodReturnValueHandlerWebAsyncTask
ModelAttributeMethodProcessor@ModelAttribute
RequestResponseBodyMethodProcessor@ResponseBody
ViewNameMethodReturnValueHandlerCharSequence 、void
MapMethodProcessorMap

RequestResponseBodyMethodProcessor源码

比如以@RequestBody注解为例(@ResponseBody同理),最终使用到了RequestResponseBodyMethodProcessor,它先使用HttpMessageConverter序列化,然后使用WebDataBinder(之前讲过)进行验证,验证结果使用BindingResult获取。

public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		parameter = parameter.nestedIfOptional();
		//调用AbstractHttpMessageConverter.write
		Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
		String name = Conventions.getVariableNameForParameter(parameter);
  
		WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
		if (arg != null) {
			//验证
			validateIfApplicable(binder, parameter);
			if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
				throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
			}
		}
		mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
		return adaptArgumentIfNecessary(arg, parameter);
	}
}

HttpMessageConverter源码

对请求及响应进行序列化,看源码吧

public interface HttpMessageConverter<T> {
    //判断该转换器是否能将请求内容转换成 Java 对象
    boolean canRead(Class<?> var1, MediaType var2);
    //判断该转换器是否可以将 Java 对象转换成返回内容
    boolean canWrite(Class<?> var1, MediaType var2);
    //获得该转换器支持的 MediaType 类型
    List<MediaType> getSupportedMediaTypes();
    //读取请求内容并转换成 Java 对象
    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
    //将 Java 对象转换后写入返回内容
    void write(T var1, MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

总结

Spring 拦截器(Interceptor)关注执行HandlerAdapter以及渲染页面前后,HttpMessageConverter则关注的是消息的处理,像对 Json 进行加密这样的场景适合用HttpMessageConverter。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值