springMVC (六) @responseBody

来源:互联网 发布:网络买彩票会坐牢吗 编辑:程序博客网 时间:2024/06/05 03:57

当controller中的方法使用@responseBody注解时的处理过程

首先DispatcherServlet方法中的doDispatch方法中的

// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

前面分析我们已经知道,ha(handlerAdapter)会由RequestMappingHandlerAdapter来处理,最终会找到RequestMappingHandlerAdapter中的方法

@Overrideprotected final ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {// Always prevent caching in case of session attribute management.checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);}else {// Uses configured default cacheSeconds setting.checkAndPrepare(request, response, true);}// 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) {return invokeHandleMethod(request, response, handlerMethod);}}}return invokeHandleMethod(request, response, handlerMethod);}/**     * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}     * if view resolution is required.     */    private ModelAndView invokeHandleMethod(HttpServletRequest request,            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {        ServletWebRequest webRequest = new ServletWebRequest(request, response);        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);        ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);//注意1         ModelAndViewContainer mavContainer = new ModelAndViewContainer();        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));        modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);        AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);        asyncWebRequest.setTimeout(this.asyncRequestTimeout);        final 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 + "]");            }            requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);        }        requestMappingMethod.invokeAndHandle(webRequest, mavContainer);//注意2         if (asyncManager.isConcurrentHandlingStarted()) {            return null;        }        return getModelAndView(mavContainer, modelFactory, webRequest);    }


注意1 创建ServletInvocableHandlerMethod调用了方法createRequestMappingMethod(handlerMethod, binderFactory)

private ServletInvocableHandlerMethod createRequestMappingMethod(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {ServletInvocableHandlerMethod requestMethod;requestMethod = new ServletInvocableHandlerMethod(handlerMethod);requestMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);requestMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);//传入了RequestMappingHandlerAdapter的returnValueHandlers,               requestMethod.setDataBinderFactory(binderFactory);                          //后面会分析Adapter的reternValueHandlers初始化requestMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);return requestMethod;}

注意2接着由ServletInvocableHandlerMethod调用:requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

/** * Invokes the method and handles the return value through a registered * {@link HandlerMethodReturnValueHandler}. * * @param webRequest the current request * @param mavContainer the ModelAndViewContainer for this request * @param providedArgs "given" arguments matched by type, not resolved */public final void invokeAndHandle(ServletWebRequest webRequest,ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);//得到返回结果setResponseStatus(webRequest);if (returnValue == null) {if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {mavContainer.setRequestHandled(true);return;}}else if (StringUtils.hasText(this.responseReason)) {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;}}
this.returnValueHandlers 指的是private HandlerMethodReturnValueHandlerComposite returnValueHandlers; 也即是上面创建ServletInvocableHandlerMethod时候传入的,

看看其handleReturnValue()方法

/** * Iterate over registered {@link HandlerMethodReturnValueHandler}s and invoke the one that supports it. * @throws IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found. */@Overridepublic void handleReturnValue(Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);}/** * Find a registered {@link HandlerMethodReturnValueHandler} that supports the given return type. */private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {if (logger.isTraceEnabled()) {logger.trace("Testing if return value handler [" + returnValueHandler + "] supports [" +returnType.getGenericParameterType() + "]");}if (returnValueHandler.supportsReturnType(returnType)) {return returnValueHandler;}}return null;}

getReturnValueHandler()方法遍历所有List<HandlerMethodReturnValueHandler> returnValueHandlers得到合适的HandlerMethodReturnValueHandler

在这里是由RequestResponseBodyMethodProcessor处理

public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {  @Override    public void handleReturnValue(Object returnValue, MethodParameter returnType,            ModelAndViewContainer mavContainer, NativeWebRequest webRequest)            throws IOException, HttpMediaTypeNotAcceptableException {        mavContainer.setRequestHandled(true);        if (returnValue != null || getAdviceChain().hasAdvice()) {            writeWithMessageConverters(returnValue, returnType, webRequest);        }    }}

public abstract class AbstractMessageConverterMethodProcessor extends AbstractMessageConverterMethodArgumentResolverimplements HandlerMethodReturnValueHandler {/**     * Writes the given return value to the given web request. Delegates to     * {@link #writeWithMessageConverters(Object, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)}     */    protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, NativeWebRequest webRequest)            throws IOException, HttpMediaTypeNotAcceptableException {        ServletServerHttpRequest inputMessage = createInputMessage(webRequest);        ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);        writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);    }    /**     * Writes the given return type to the given output message.     * @param returnValue the value to write to the output message     * @param returnType the type of the value     * @param inputMessage the input messages. Used to inspect the {@code Accept} header.     * @param outputMessage the output message to write to     * @throws IOException thrown in case of I/O errors     * @throws HttpMediaTypeNotAcceptableException thrown when the conditions indicated by {@code Accept} header on     * the request cannot be met by the message converters     */    @SuppressWarnings("unchecked")    protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType,            ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)            throws IOException, HttpMediaTypeNotAcceptableException {        Class<?> returnValueClass = getReturnValueType(returnValue, returnType);        HttpServletRequest servletRequest = inputMessage.getServletRequest();        List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest);        List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);        Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();        for (MediaType requestedType : requestedMediaTypes) {            for (MediaType producibleType : producibleMediaTypes) {                if (requestedType.isCompatibleWith(producibleType)) {                    compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType));                }            }        }        if (compatibleMediaTypes.isEmpty()) {            throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes);        }        List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);        MediaType.sortBySpecificityAndQuality(mediaTypes);        MediaType selectedMediaType = null;        for (MediaType mediaType : mediaTypes) {            if (mediaType.isConcrete()) {                selectedMediaType = mediaType;                break;            }            else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {                selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;                break;            }        }        if (selectedMediaType != null) {            selectedMediaType = selectedMediaType.removeQualityValue();            for (HttpMessageConverter<?> messageConverter : this.messageConverters) {                if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {                    returnValue = this.adviceChain.invoke(returnValue, returnType, selectedMediaType,                            (Class<HttpMessageConverter<?>>) messageConverter.getClass(), inputMessage, outputMessage);                    if (returnValue != null) {                        ((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);                        if (logger.isDebugEnabled()) {                            logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" +                                    messageConverter + "]");                        }                    }                    return;                }            }        }        throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);    }}

public interface HttpMessageConverter<T>


RequestMappingHandlerAdapter中关于private HandlerMethodReturnValueHandlerComposite returnValueHandlers 初始化

@Overridepublic void afterPropertiesSet() {// Do this first, it may add ResponseBody advice beansinitControllerAdviceCache();if (this.argumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.initBinderArgumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}}/**     * Return the list of return value handlers to use including built-in and     * custom handlers provided via {@link #setReturnValueHandlers}.     */    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 HttpEntityMethodProcessor(                getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));        handlers.add(new HttpHeadersReturnValueHandler());        handlers.add(new CallableMethodReturnValueHandler());        handlers.add(new DeferredResultMethodReturnValueHandler());        handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));        handlers.add(new ListenableFutureReturnValueHandler());        // Annotation-based return value types        handlers.add(new ModelAttributeMethodProcessor(false));        handlers.add(new RequestResponseBodyMethodProcessor(                getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));                //getMessageConverters()=this.messageConverters        // 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;    }/**     * Default constructor.     */    public RequestMappingHandlerAdapter() {        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();        stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316        this.messageConverters = new ArrayList<HttpMessageConverter<?>>();        this.messageConverters.add(new ByteArrayHttpMessageConverter());        this.messageConverters.add(stringHttpMessageConverter);        this.messageConverters.add(new SourceHttpMessageConverter<Source>());        this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());    }


0 0
原创粉丝点击