@ -178,27 +178,25 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@@ -178,27 +178,25 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@Override
public Mono < HandlerMethod > getHandlerInternal ( ServerWebExchange exchange ) {
if ( this . apiVersionStrategy ! = null ) {
Comparable < ? > requestV ersion = exchange . getAttribute ( API_VERSION_ATTRIBUTE ) ;
if ( requestV ersion = = null ) {
requestV ersion = getApiVersion ( exchange , this . apiVersionStrategy ) ;
if ( requestV ersion ! = null ) {
exchange . getAttributes ( ) . put ( API_VERSION_ATTRIBUTE , requestV ersion) ;
Comparable < ? > v ersion = exchange . getAttribute ( API_VERSION_ATTRIBUTE ) ;
if ( v ersion = = null ) {
v ersion = getApiVersion ( exchange , this . apiVersionStrategy ) ;
if ( v ersion ! = null ) {
exchange . getAttributes ( ) . put ( API_VERSION_ATTRIBUTE , v ersion) ;
}
}
}
return super . getHandlerInternal ( exchange ) ;
}
private static @Nullable Comparable < ? > getApiVersion (
ServerWebExchange exchange , ApiVersionStrategy versionStrategy ) {
String value = versionStrategy . resolveVersion ( exchange ) ;
private static @Nullable Comparable < ? > getApiVersion ( ServerWebExchange exchange , ApiVersionStrategy strategy ) {
String value = strategy . resolveVersion ( exchange ) ;
if ( value = = null ) {
return ver sionS trategy. getDefaultVersion ( ) ;
return strategy . getDefaultVersion ( ) ;
}
try {
Comparable < ? > version = ver sionS trategy. parseVersion ( value ) ;
ver sionS trategy. validateVersion ( version , exchange ) ;
Comparable < ? > version = strategy . parseVersion ( value ) ;
strategy . validateVersion ( version , exchange ) ;
return version ;
}
catch ( Exception ex ) {
@ -242,42 +240,43 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@@ -242,42 +240,43 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
}
private @Nullable RequestMappingInfo createRequestMappingInfo ( AnnotatedElement element ) {
RequestMappingInfo requestMappingInfo = null ;
List < AnnotationDescriptor > descriptors =
MergedAnnotations . from ( element , SearchStrategy . TYPE_HIERARCHY , RepeatableContainers . none ( ) ) . stream ( )
. filter ( MergedAnnotationPredicates . typeIn ( RequestMapping . class , HttpExchange . class ) )
. filter ( MergedAnnotationPredicates . firstRunOf ( MergedAnnotation : : getAggregateIndex ) )
. map ( AnnotationDescriptor : : new )
. distinct ( )
. toList ( ) ;
RequestMappingInfo info = null ;
RequestCondition < ? > customCondition = ( element instanceof Class < ? > clazz ?
getCustomTypeCondition ( clazz ) : getCustomMethodCondition ( ( Method ) element ) ) ;
List < AnnotationDescriptor > descriptors = getAnnotationDescriptors ( element ) ;
List < AnnotationDescriptor > mappingDescriptors =
descriptors . stream ( ) . filter ( desc - > desc . annotation instanceof RequestMapping ) . toList ( ) ;
List < AnnotationDescriptor > requestMappings = descriptors . stream ( )
. filter ( desc - > desc . annotation instanceof RequestMapping ) . toList ( ) ;
if ( ! requestMappings . isEmpty ( ) ) {
if ( requestMappings . size ( ) > 1 & & logger . isWarnEnabled ( ) ) {
logger . warn ( "Multiple @RequestMapping annotations found on %s, but only the first will be used: %s"
. formatted ( element , requestMappings ) ) ;
}
requestMappingInfo = createRequestMappingInfo ( ( RequestMapping ) requestMappings . get ( 0 ) . annotation , customCondition ) ;
if ( ! mappingDescriptors . isEmpty ( ) ) {
checkMultipleAnnotations ( element , mappingDescriptors ) ;
info = createRequestMappingInfo ( ( RequestMapping ) mappingDescriptors . get ( 0 ) . annotation , customCondition ) ;
}
List < AnnotationDescriptor > httpExchanges = descriptors . stream ( )
. filter ( desc - > desc . annotation instanceof HttpExchange ) . toList ( ) ;
if ( ! httpExchanges . isEmpty ( ) ) {
Assert . state ( requestMappingInfo = = null ,
( ) - > "%s is annotated with @RequestMapping and @HttpExchange annotations, but only one is allowed: %s"
. formatted ( element , Stream . of ( requestMappings , httpExchanges ) . flatMap ( List : : stream ) . toList ( ) ) ) ;
Assert . state ( httpExchanges . size ( ) = = 1 ,
( ) - > "Multiple @HttpExchange annotations found on %s, but only one is allowed: %s"
. formatted ( element , httpExchanges ) ) ;
requestMappingInfo = createRequestMappingInfo ( ( HttpExchange ) httpExchanges . get ( 0 ) . annotation , customCondition ) ;
List < AnnotationDescriptor > exchangeDescriptors =
descriptors . stream ( ) . filter ( desc - > desc . annotation instanceof HttpExchange ) . toList ( ) ;
if ( ! exchangeDescriptors . isEmpty ( ) ) {
checkMultipleAnnotations ( element , info , mappingDescriptors , exchangeDescriptors ) ;
info = createRequestMappingInfo ( ( HttpExchange ) exchangeDescriptors . get ( 0 ) . annotation , customCondition ) ;
}
if ( requestMapp ingI nfo ! = null & & this . apiVersionStrategy instanceof DefaultApiVersionStrategy davs ) {
String version = requestMapp ingI nfo. getVersionCondition ( ) . getVersion ( ) ;
if ( info ! = null & & this . apiVersionStrategy instanceof DefaultApiVersionStrategy davs ) {
String version = info . getVersionCondition ( ) . getVersion ( ) ;
if ( version ! = null ) {
davs . addMappedVersion ( version ) ;
}
}
return requestMapp ingI nfo;
return info ;
}
/ * *
@ -316,6 +315,28 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@@ -316,6 +315,28 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
return null ;
}
private void checkMultipleAnnotations (
AnnotatedElement element , List < AnnotationDescriptor > mappingDescriptors ) {
if ( logger . isWarnEnabled ( ) & & mappingDescriptors . size ( ) > 1 ) {
logger . warn ( "Multiple @RequestMapping annotations found on %s, but only the first will be used: %s"
. formatted ( element , mappingDescriptors ) ) ;
}
}
private static void checkMultipleAnnotations (
AnnotatedElement element , @Nullable RequestMappingInfo info ,
List < AnnotationDescriptor > mappingDescriptors , List < AnnotationDescriptor > exchangeDescriptors ) {
Assert . state ( info = = null ,
( ) - > "%s is annotated with @RequestMapping and @HttpExchange annotations, but only one is allowed: %s"
. formatted ( element , Stream . of ( mappingDescriptors , exchangeDescriptors ) . flatMap ( List : : stream ) . toList ( ) ) ) ;
Assert . state ( exchangeDescriptors . size ( ) = = 1 ,
( ) - > "Multiple @HttpExchange annotations found on %s, but only one is allowed: %s"
. formatted ( element , exchangeDescriptors ) ) ;
}
/ * *
* Create a { @link RequestMappingInfo } from the supplied
* { @link RequestMapping @RequestMapping } annotation , meta - annotation ,
@ -510,24 +531,16 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@@ -510,24 +531,16 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
}
}
private static List < AnnotationDescriptor > getAnnotationDescriptors ( AnnotatedElement element ) {
return MergedAnnotations . from ( element , SearchStrategy . TYPE_HIERARCHY , RepeatableContainers . none ( ) )
. stream ( )
. filter ( MergedAnnotationPredicates . typeIn ( RequestMapping . class , HttpExchange . class ) )
. filter ( MergedAnnotationPredicates . firstRunOf ( MergedAnnotation : : getAggregateIndex ) )
. map ( AnnotationDescriptor : : new )
. distinct ( )
. toList ( ) ;
}
private static class AnnotationDescriptor {
private final Annotation annotation ;
private final MergedAnnotation < ? > root ;
AnnotationDescriptor ( MergedAnnotation < Annotation > mergedA nnotation) {
this . annotation = mergedA nnotation. synthesize ( ) ;
this . root = mergedA nnotation. getRoot ( ) ;
AnnotationDescriptor ( MergedAnnotation < Annotation > annotation ) {
this . annotation = annotation . synthesize ( ) ;
this . root = a nnotation. getRoot ( ) ;
}
@Override