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
- springMVC (六) @responseBody
- SpringMVC @ResponseBody
- @ResponseBody-------springMVC
- springMVC ResponseBody
- SpringMVC @responsebody
- SpringMVC的@ResponseBody乱码
- SpringMVC使用@ResponseBody
- SpringMVC@ResponseBody的心得
- SpringMVC 注解之@ResponseBody
- SpringMVC之@RequestBody, @ResponseBody
- SpringMVC中的@ResponseBody
- SpringMVC注解之@ResponseBody
- SpringMVC @ResponseBody 乱码
- springmvc @ResponseBody 乱码
- SpringMVC - @Responsebody与@RequestBody
- springMVC的@responsebody注解.
- SpringMVC中 注解@ResponseBody
- SpringMVC requestBody responseBody 详解
- NDK编译问题: Program "ndk-build" is not found in PATH 和 Unable to launch cygpath. Is Cygwin on the path?
- RecyclerView嵌套RecyclerView
- JDK环境变量配置
- light oj 1032(数位dp)
- AndroidUI——InputFilter的使用(2)
- springMVC (六) @responseBody
- js自动获得焦点
- 学习笔记----快速排序的java实现及其改良
- 解决:Maximum number of threads (200) created for connector with address null
- laravel 问题2 缓存view
- nodejs案例-HelloWorld
- 用PYTHON写一个应用程序并发布exe
- 安装 WINE
- Unity 5 中的全局光照技术详解