|
|
@ -50,6 +50,8 @@ import org.springframework.web.server.ServerWebExchange; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|
|
|
|
* Supports the invocation of {@code @RequestMapping} methods. |
|
|
|
|
|
|
|
* |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactoryAware, InitializingBean { |
|
|
|
public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactoryAware, InitializingBean { |
|
|
@ -57,9 +59,11 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory |
|
|
|
private static Log logger = LogFactory.getLog(RequestMappingHandlerAdapter.class); |
|
|
|
private static Log logger = LogFactory.getLog(RequestMappingHandlerAdapter.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(); |
|
|
|
private List<HandlerMethodArgumentResolver> customArgumentResolvers; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<HandlerMethodArgumentResolver> argumentResolvers; |
|
|
|
|
|
|
|
|
|
|
|
private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); |
|
|
|
private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(10); |
|
|
|
|
|
|
|
|
|
|
|
private ConversionService conversionService = new DefaultFormattingConversionService(); |
|
|
|
private ConversionService conversionService = new DefaultFormattingConversionService(); |
|
|
|
|
|
|
|
|
|
|
@ -75,13 +79,26 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Provide custom argument resolvers without overriding the built-in ones. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { |
|
|
|
|
|
|
|
this.customArgumentResolvers = argumentResolvers; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Return the custom argument resolvers. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() { |
|
|
|
|
|
|
|
return this.customArgumentResolvers; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Configure the complete list of supported argument types thus overriding |
|
|
|
* Configure the complete list of supported argument types thus overriding |
|
|
|
* the resolvers that would otherwise be configured by default. |
|
|
|
* the resolvers that would otherwise be configured by default. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { |
|
|
|
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { |
|
|
|
this.argumentResolvers.clear(); |
|
|
|
this.argumentResolvers = new ArrayList<>(resolvers); |
|
|
|
this.argumentResolvers.addAll(resolvers); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -91,22 +108,35 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory |
|
|
|
return this.argumentResolvers; |
|
|
|
return this.argumentResolvers; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Configure message converters to read the request body with. |
|
|
|
|
|
|
|
*/ |
|
|
|
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) { |
|
|
|
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) { |
|
|
|
this.messageConverters.clear(); |
|
|
|
this.messageConverters.clear(); |
|
|
|
this.messageConverters.addAll(messageConverters); |
|
|
|
this.messageConverters.addAll(messageConverters); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Provide the message converters to use for argument resolution. |
|
|
|
* Return the configured message converters. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public List<HttpMessageConverter<?>> getMessageConverters() { |
|
|
|
public List<HttpMessageConverter<?>> getMessageConverters() { |
|
|
|
return this.messageConverters; |
|
|
|
return this.messageConverters; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Configure a ConversionService for type conversion of controller method |
|
|
|
|
|
|
|
* arguments as well as for converting from different async types to |
|
|
|
|
|
|
|
* {@code Flux} and {@code Mono}. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* TODO: this may be replaced by DataBinder |
|
|
|
|
|
|
|
*/ |
|
|
|
public void setConversionService(ConversionService conversionService) { |
|
|
|
public void setConversionService(ConversionService conversionService) { |
|
|
|
this.conversionService = conversionService; |
|
|
|
this.conversionService = conversionService; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Return the configured ConversionService. |
|
|
|
|
|
|
|
*/ |
|
|
|
public ConversionService getConversionService() { |
|
|
|
public ConversionService getConversionService() { |
|
|
|
return this.conversionService; |
|
|
|
return this.conversionService; |
|
|
|
} |
|
|
|
} |
|
|
@ -123,43 +153,47 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public ConfigurableBeanFactory getBeanFactory() { |
|
|
|
public ConfigurableBeanFactory getBeanFactory() { |
|
|
|
return beanFactory; |
|
|
|
return this.beanFactory; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void afterPropertiesSet() throws Exception { |
|
|
|
public void afterPropertiesSet() throws Exception { |
|
|
|
if (ObjectUtils.isEmpty(this.argumentResolvers)) { |
|
|
|
if (this.argumentResolvers == null) { |
|
|
|
|
|
|
|
this.argumentResolvers = initArgumentResolvers(); |
|
|
|
// List<HttpMessageConverter<?>> converters = Arrays.asList(
|
|
|
|
|
|
|
|
// new CodecHttpMessageConverter<ByteBuffer>(new ByteBufferEncoder(), new ByteBufferDecoder()),
|
|
|
|
|
|
|
|
// new CodecHttpMessageConverter<String>(new StringEncoder(), new StringDecoder()),
|
|
|
|
|
|
|
|
// new CodecHttpMessageConverter<Object>(new Jaxb2Encoder(), new Jaxb2Decoder()),
|
|
|
|
|
|
|
|
// new CodecHttpMessageConverter<Object>(new JacksonJsonEncoder(),
|
|
|
|
|
|
|
|
// new JacksonJsonDecoder(new JsonObjectDecoder())));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Annotation-based argument resolution
|
|
|
|
|
|
|
|
ConversionService cs = getConversionService(); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestParamMethodArgumentResolver(cs, getBeanFactory(), false)); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestParamMapMethodArgumentResolver()); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new PathVariableMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new PathVariableMapMethodArgumentResolver()); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestBodyArgumentResolver(getMessageConverters(), cs)); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestHeaderMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestHeaderMapMethodArgumentResolver()); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new CookieValueMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new ExpressionValueMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new SessionAttributeMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestAttributeMethodArgumentResolver(cs , getBeanFactory())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Type-based argument resolution
|
|
|
|
|
|
|
|
this.argumentResolvers.add(new ModelArgumentResolver()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Catch-all
|
|
|
|
|
|
|
|
this.argumentResolvers.add(new RequestParamMethodArgumentResolver(cs, getBeanFactory(), true)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected List<HandlerMethodArgumentResolver> initArgumentResolvers() { |
|
|
|
|
|
|
|
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Annotation-based argument resolution
|
|
|
|
|
|
|
|
ConversionService cs = getConversionService(); |
|
|
|
|
|
|
|
resolvers.add(new RequestParamMethodArgumentResolver(cs, getBeanFactory(), false)); |
|
|
|
|
|
|
|
resolvers.add(new RequestParamMapMethodArgumentResolver()); |
|
|
|
|
|
|
|
resolvers.add(new PathVariableMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
resolvers.add(new PathVariableMapMethodArgumentResolver()); |
|
|
|
|
|
|
|
resolvers.add(new RequestBodyArgumentResolver(getMessageConverters(), cs)); |
|
|
|
|
|
|
|
resolvers.add(new RequestHeaderMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
resolvers.add(new RequestHeaderMapMethodArgumentResolver()); |
|
|
|
|
|
|
|
resolvers.add(new CookieValueMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
resolvers.add(new ExpressionValueMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
resolvers.add(new SessionAttributeMethodArgumentResolver(cs, getBeanFactory())); |
|
|
|
|
|
|
|
resolvers.add(new RequestAttributeMethodArgumentResolver(cs , getBeanFactory())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Type-based argument resolution
|
|
|
|
|
|
|
|
resolvers.add(new ModelArgumentResolver()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Custom resolvers
|
|
|
|
|
|
|
|
if (getCustomArgumentResolvers() != null) { |
|
|
|
|
|
|
|
resolvers.addAll(getCustomArgumentResolvers()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Catch-all
|
|
|
|
|
|
|
|
resolvers.add(new RequestParamMethodArgumentResolver(cs, getBeanFactory(), true)); |
|
|
|
|
|
|
|
return resolvers; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean supports(Object handler) { |
|
|
|
public boolean supports(Object handler) { |
|
|
|
return HandlerMethod.class.equals(handler.getClass()); |
|
|
|
return HandlerMethod.class.equals(handler.getClass()); |
|
|
@ -169,7 +203,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory |
|
|
|
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) { |
|
|
|
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) { |
|
|
|
HandlerMethod handlerMethod = (HandlerMethod) handler; |
|
|
|
HandlerMethod handlerMethod = (HandlerMethod) handler; |
|
|
|
InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod); |
|
|
|
InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod); |
|
|
|
invocable.setHandlerMethodArgumentResolvers(this.argumentResolvers); |
|
|
|
invocable.setHandlerMethodArgumentResolvers(getArgumentResolvers()); |
|
|
|
ModelMap model = new ExtendedModelMap(); |
|
|
|
ModelMap model = new ExtendedModelMap(); |
|
|
|
return invocable.invokeForRequest(exchange, model) |
|
|
|
return invocable.invokeForRequest(exchange, model) |
|
|
|
.map(result -> result.setExceptionHandler(ex -> handleException(ex, handlerMethod, exchange))) |
|
|
|
.map(result -> result.setExceptionHandler(ex -> handleException(ex, handlerMethod, exchange))) |
|
|
|