Introduce hints support in advices
This commit introduces RequestBodyAdvice#determineReadHints and ResponseBodyAdvice#determineWriteHints in order to be able to support SmartHttpMessageConverter hints, as well as related `@JsonView` support. See gh-33798
This commit is contained in:
@@ -17,10 +17,14 @@
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
@@ -29,7 +33,9 @@ import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.SmartHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
@@ -52,6 +58,7 @@ import static org.mockito.Mockito.mock;
|
||||
* Tests for {@link RequestResponseBodyAdviceChain}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sebastien Deleuze
|
||||
* @since 4.2
|
||||
*/
|
||||
class RequestResponseBodyAdviceChainTests {
|
||||
@@ -131,6 +138,20 @@ class RequestResponseBodyAdviceChainTests {
|
||||
assertThat(actual).isEqualTo(this.body);
|
||||
}
|
||||
|
||||
@Test
|
||||
void controllerAdviceWithHints() {
|
||||
Object fooAdviceBean = createControllerAdviceBean(FooHintControllerAdvice.class);
|
||||
Object barAdviceBean = createControllerAdviceBean(BarHintControllerAdvice.class);
|
||||
RequestResponseBodyAdviceChain chain = new RequestResponseBodyAdviceChain(List.of(fooAdviceBean, barAdviceBean));
|
||||
|
||||
Map<String, Object> readHints = chain.determineReadHints(this.paramType, this.paramType.getGenericParameterType(),
|
||||
JacksonJsonHttpMessageConverter.class);
|
||||
assertThat(readHints).containsExactlyInAnyOrderEntriesOf(Map.of("foo", "String", "bar", "String"));
|
||||
|
||||
Map<String, Object> writeHints = chain.determineWriteHints(this.body, this.returnType, this.contentType, this.converterType);
|
||||
assertThat(writeHints).containsExactlyInAnyOrderEntriesOf(Map.of("foo", "body", "bar", "body"));
|
||||
}
|
||||
|
||||
private ControllerAdviceBean createControllerAdviceBean(Class<?> beanType) {
|
||||
StaticApplicationContext applicationContext = new StaticApplicationContext();
|
||||
applicationContext.registerSingleton(beanType.getSimpleName(), beanType);
|
||||
@@ -174,6 +195,64 @@ class RequestResponseBodyAdviceChainTests {
|
||||
}
|
||||
}
|
||||
|
||||
@ControllerAdvice
|
||||
private static class FooHintControllerAdvice extends RequestBodyAdviceAdapter implements ResponseBodyAdvice<String> {
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String beforeBodyWrite(@Nullable String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> determineWriteHints(@Nullable String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType) {
|
||||
return Collections.singletonMap("foo", Objects.requireNonNull(body));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> determineReadHints(MethodParameter parameter, Type targetType, Class<? extends SmartHttpMessageConverter<?>> converterType) {
|
||||
return Collections.singletonMap("foo", parameter.getParameterType().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ControllerAdvice
|
||||
private static class BarHintControllerAdvice extends RequestBodyAdviceAdapter implements ResponseBodyAdvice<String> {
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String beforeBodyWrite(@Nullable String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> determineWriteHints(@Nullable String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType) {
|
||||
return Collections.singletonMap("bar", Objects.requireNonNull(body));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> determineReadHints(MethodParameter parameter, Type targetType, Class<? extends SmartHttpMessageConverter<?>> converterType) {
|
||||
return Collections.singletonMap("bar", parameter.getParameterType().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ResponseBody
|
||||
|
||||
Reference in New Issue
Block a user