001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.reactive.result.method.annotation; 018 019import java.util.List; 020 021import reactor.core.publisher.Mono; 022 023import org.springframework.core.MethodParameter; 024import org.springframework.core.ReactiveAdapterRegistry; 025import org.springframework.core.annotation.AnnotatedElementUtils; 026import org.springframework.http.codec.HttpMessageWriter; 027import org.springframework.web.bind.annotation.ResponseBody; 028import org.springframework.web.reactive.HandlerResult; 029import org.springframework.web.reactive.HandlerResultHandler; 030import org.springframework.web.reactive.accept.RequestedContentTypeResolver; 031import org.springframework.web.server.ServerWebExchange; 032 033/** 034 * {@code HandlerResultHandler} that handles return values from methods annotated 035 * with {@code @ResponseBody} writing to the body of the request or response with 036 * an {@link HttpMessageWriter}. 037 * 038 * <p>By default the order for this result handler is set to 100. As it detects 039 * the presence of {@code @ResponseBody} it should be ordered after result 040 * handlers that look for a specific return type. Note however that this handler 041 * does recognize and explicitly ignores the {@code ResponseEntity} return type. 042 * 043 * @author Rossen Stoyanchev 044 * @author Stephane Maldini 045 * @author Sebastien Deleuze 046 * @author Arjen Poutsma 047 * @since 5.0 048 */ 049public class ResponseBodyResultHandler extends AbstractMessageWriterResultHandler implements HandlerResultHandler { 050 051 /** 052 * Basic constructor with a default {@link ReactiveAdapterRegistry}. 053 * @param writers the writers for serializing to the response body 054 * @param resolver to determine the requested content type 055 */ 056 public ResponseBodyResultHandler(List<HttpMessageWriter<?>> writers, RequestedContentTypeResolver resolver) { 057 this(writers, resolver, ReactiveAdapterRegistry.getSharedInstance()); 058 } 059 060 /** 061 * Constructor with an {@link ReactiveAdapterRegistry} instance. 062 * @param writers the writers for serializing to the response body 063 * @param resolver to determine the requested content type 064 * @param registry for adaptation to reactive types 065 */ 066 public ResponseBodyResultHandler(List<HttpMessageWriter<?>> writers, 067 RequestedContentTypeResolver resolver, ReactiveAdapterRegistry registry) { 068 069 super(writers, resolver, registry); 070 setOrder(100); 071 } 072 073 074 @Override 075 public boolean supports(HandlerResult result) { 076 MethodParameter returnType = result.getReturnTypeSource(); 077 Class<?> containingClass = returnType.getContainingClass(); 078 return (AnnotatedElementUtils.hasAnnotation(containingClass, ResponseBody.class) || 079 returnType.hasMethodAnnotation(ResponseBody.class)); 080 } 081 082 @Override 083 public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) { 084 Object body = result.getReturnValue(); 085 MethodParameter bodyTypeParameter = result.getReturnTypeSource(); 086 return writeBody(body, bodyTypeParameter, exchange); 087 } 088 089}