Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
97c2de91
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
97c2de91
编写于
5月 14, 2019
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add RouteMatcher
Closes gh-22642
上级
afc0ae37
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
449 addition
and
83 deletion
+449
-83
spring-core/src/main/java/org/springframework/util/RouteMatcher.java
.../src/main/java/org/springframework/util/RouteMatcher.java
+100
-0
spring-core/src/main/java/org/springframework/util/SimpleRouteMatcher.java
...ain/java/org/springframework/util/SimpleRouteMatcher.java
+101
-0
spring-messaging/src/main/java/org/springframework/messaging/handler/DestinationPatternsMessageCondition.java
...essaging/handler/DestinationPatternsMessageCondition.java
+59
-31
spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java
...ler/annotation/reactive/MessageMappingMessageHandler.java
+29
-20
spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java
...ler/invocation/reactive/AbstractMethodMessageHandler.java
+12
-12
spring-messaging/src/main/java/org/springframework/messaging/rsocket/MessageHandlerAcceptor.java
...ngframework/messaging/rsocket/MessageHandlerAcceptor.java
+1
-0
spring-messaging/src/main/java/org/springframework/messaging/rsocket/MessagingRSocket.java
...g/springframework/messaging/rsocket/MessagingRSocket.java
+9
-2
spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketMessageHandler.java
...ingframework/messaging/rsocket/RSocketMessageHandler.java
+6
-5
spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandlerTests.java
...nnotation/reactive/MessageMappingMessageHandlerTests.java
+7
-4
spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/reactive/MethodMessageHandlerTests.java
...andler/invocation/reactive/MethodMessageHandlerTests.java
+19
-9
spring-web/src/main/java/org/springframework/web/util/pattern/PathPatternRouteMatcher.java
...ngframework/web/util/pattern/PathPatternRouteMatcher.java
+106
-0
未找到文件。
spring-core/src/main/java/org/springframework/util/RouteMatcher.java
0 → 100644
浏览文件 @
97c2de91
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.util
;
import
java.util.Comparator
;
import
java.util.Map
;
import
org.springframework.lang.Nullable
;
/**
* Contract for matching routes to patterns.
*
* <p>Equivalent to {@link PathMatcher}, but enables use of parsed
* representations of routes and patterns for efficiency reasons in scenarios
* where routes from incoming messages are continuously matched against a
* large number of message handler patterns.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
public
interface
RouteMatcher
{
/**
* Return a parsed representation of the given route.
* @param routeValue the route to parse
* @return the parsed representation of the route
*/
Route
parseRoute
(
String
routeValue
);
/**
* Whether the given {@code route} contains pattern syntax which requires
* the {@link #match(String, Route)} method, or if it is a regular String
* that could be compared directly to others.
* @param route the route to check
* @return {@code true} if the given {@code route} represents a pattern
*/
boolean
isPattern
(
String
route
);
/**
* Combines two patterns into a single pattern.
* @param pattern1 the first pattern
* @param pattern2 the second pattern
* @return the combination of the two patterns
* @throws IllegalArgumentException when the two patterns cannot be combined
*/
String
combine
(
String
pattern1
,
String
pattern2
);
/**
* Match the given route against the given pattern.
* @param pattern the pattern to try to match
* @param route the route to test against
* @return {@code true} if there is a match, {@code false} otherwise
*/
boolean
match
(
String
pattern
,
Route
route
);
/**
* Match the pattern to the route and extract template variables.
* @param pattern the pattern, possibly containing templates variables
* @param route the route to extract template variables from
* @return a map with template variables and values
*/
@Nullable
Map
<
String
,
String
>
matchAndExtract
(
String
pattern
,
Route
route
);
/**
* Given a route, return a {@link Comparator} suitable for sorting patterns
* in order of explicitness for that route, so that more specific patterns
* come before more generic ones.
* @param route the full path to use for comparison
* @return a comparator capable of sorting patterns in order of explicitness
*/
Comparator
<
String
>
getPatternComparator
(
Route
route
);
/**
* A parsed representation of a route.
*/
interface
Route
{
/**
* The original route value.
*/
String
value
();
}
}
spring-core/src/main/java/org/springframework/util/SimpleRouteMatcher.java
0 → 100644
浏览文件 @
97c2de91
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.util
;
import
java.util.Comparator
;
import
java.util.Map
;
import
org.springframework.lang.Nullable
;
/**
* {@code RouteMatcher} that delegates to a {@link PathMatcher}.
*
* <p><strong>Note:</strong> This implementation is not efficient since
* {@code PathMatcher} treats paths and patterns as Strings. For more optimized
* performance use the {@code PathPatternRouteMatcher} from {@code spring-web}
* which enables use of parsed routes and patterns.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
public
class
SimpleRouteMatcher
implements
RouteMatcher
{
private
final
PathMatcher
pathMatcher
;
public
SimpleRouteMatcher
(
PathMatcher
pathMatcher
)
{
Assert
.
notNull
(
pathMatcher
,
"PathMatcher is required"
);
this
.
pathMatcher
=
pathMatcher
;
}
public
PathMatcher
getPathMatcher
()
{
return
this
.
pathMatcher
;
}
@Override
public
Route
parseRoute
(
String
route
)
{
return
new
DefaultRoute
(
route
);
}
@Override
public
boolean
isPattern
(
String
route
)
{
return
this
.
pathMatcher
.
isPattern
(
route
);
}
@Override
public
String
combine
(
String
pattern1
,
String
pattern2
)
{
return
this
.
pathMatcher
.
combine
(
pattern1
,
pattern2
);
}
@Override
public
boolean
match
(
String
pattern
,
Route
route
)
{
return
this
.
pathMatcher
.
match
(
pattern
,
route
.
value
());
}
@Override
@Nullable
public
Map
<
String
,
String
>
matchAndExtract
(
String
pattern
,
Route
route
)
{
if
(!
match
(
pattern
,
route
))
{
return
null
;
}
return
this
.
pathMatcher
.
extractUriTemplateVariables
(
pattern
,
route
.
value
());
}
@Override
public
Comparator
<
String
>
getPatternComparator
(
Route
route
)
{
return
this
.
pathMatcher
.
getPatternComparator
(
route
.
value
());
}
private
static
class
DefaultRoute
implements
Route
{
private
final
String
path
;
DefaultRoute
(
String
path
)
{
this
.
path
=
path
;
}
@Override
public
String
value
()
{
return
this
.
path
;
}
}
}
\ No newline at end of file
spring-messaging/src/main/java/org/springframework/messaging/handler/DestinationPatternsMessageCondition.java
浏览文件 @
97c2de91
/*
/*
* Copyright 2002-201
8
the original author or authors.
* Copyright 2002-201
9
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -17,7 +17,6 @@
...
@@ -17,7 +17,6 @@
package
org.springframework.messaging.handler
;
package
org.springframework.messaging.handler
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.Comparator
;
...
@@ -29,12 +28,15 @@ import java.util.Set;
...
@@ -29,12 +28,15 @@ import java.util.Set;
import
org.springframework.lang.Nullable
;
import
org.springframework.lang.Nullable
;
import
org.springframework.messaging.Message
;
import
org.springframework.messaging.Message
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.util.RouteMatcher
;
import
org.springframework.util.SimpleRouteMatcher
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
/**
/**
*
A {@link MessageCondition} for matching the destination
of a Message
*
{@link MessageCondition} to match the destination header
of a Message
* against one or more
destination patterns using a {@link Path
Matcher}.
* against one or more
patterns through a {@link Route
Matcher}.
*
*
* @author Rossen Stoyanchev
* @author Rossen Stoyanchev
* @since 4.0
* @since 4.0
...
@@ -50,36 +52,41 @@ public class DestinationPatternsMessageCondition
...
@@ -50,36 +52,41 @@ public class DestinationPatternsMessageCondition
private
final
Set
<
String
>
patterns
;
private
final
Set
<
String
>
patterns
;
private
final
PathMatcher
path
Matcher
;
private
final
RouteMatcher
route
Matcher
;
/**
/**
* Creates a new instance with the given destination patterns.
* Constructor with patterns only. Creates and uses an instance of
* Each pattern that is not empty and does not start with "/" is prepended with "/".
* {@link AntPathMatcher} with default settings.
* @param patterns 0 or more URL patterns; if 0 the condition will match to every request.
* <p>Non-empty patterns that don't start with "/" are prepended with "/".
* @param patterns the URL patterns to match to, or if 0 then always match
*/
*/
public
DestinationPatternsMessageCondition
(
String
...
patterns
)
{
public
DestinationPatternsMessageCondition
(
String
...
patterns
)
{
this
(
patterns
,
null
);
this
(
patterns
,
(
PathMatcher
)
null
);
}
}
/**
/**
*
Alternative constructor accepting a custom PathMatcher
.
*
Constructor with patterns and a {@code PathMatcher} instance
.
* @param patterns the URL patterns to
use; if 0, the condition will match to every request.
* @param patterns the URL patterns to
match to, or if 0 then always match
* @param
pathMatcher the PathMatcher
to use
* @param
matcher the {@code PathMatcher}
to use
*/
*/
public
DestinationPatternsMessageCondition
(
String
[]
patterns
,
@Nullable
PathMatcher
pathM
atcher
)
{
public
DestinationPatternsMessageCondition
(
String
[]
patterns
,
@Nullable
PathMatcher
m
atcher
)
{
this
(
Arrays
.
asList
(
patterns
),
pathMatcher
);
this
(
patterns
,
new
SimpleRouteMatcher
(
matcher
!=
null
?
matcher
:
new
AntPathMatcher
())
);
}
}
private
DestinationPatternsMessageCondition
(
Collection
<
String
>
patterns
,
@Nullable
PathMatcher
pathMatcher
)
{
/**
this
.
pathMatcher
=
(
pathMatcher
!=
null
?
pathMatcher
:
new
AntPathMatcher
());
* Constructor with patterns and a {@code RouteMatcher} instance.
this
.
patterns
=
Collections
.
unmodifiableSet
(
prependLeadingSlash
(
patterns
,
this
.
pathMatcher
));
* @param patterns the URL patterns to match to, or if 0 then always match
* @param routeMatcher the {@code RouteMatcher} to use
* @since 5.2
*/
public
DestinationPatternsMessageCondition
(
String
[]
patterns
,
RouteMatcher
routeMatcher
)
{
this
(
Collections
.
unmodifiableSet
(
prependLeadingSlash
(
patterns
,
routeMatcher
)),
routeMatcher
);
}
}
private
static
Set
<
String
>
prependLeadingSlash
(
String
[]
patterns
,
RouteMatcher
routeMatcher
)
{
private
static
Set
<
String
>
prependLeadingSlash
(
Collection
<
String
>
patterns
,
PathMatcher
pathMatcher
)
{
boolean
slashSeparator
=
routeMatcher
.
combine
(
"a"
,
"a"
).
equals
(
"a/a"
);
boolean
slashSeparator
=
pathMatcher
.
combine
(
"a"
,
"a"
).
equals
(
"a/a"
);
Set
<
String
>
result
=
new
LinkedHashSet
<>(
patterns
.
length
);
Set
<
String
>
result
=
new
LinkedHashSet
<>(
patterns
.
size
());
for
(
String
pattern
:
patterns
)
{
for
(
String
pattern
:
patterns
)
{
if
(
slashSeparator
&&
StringUtils
.
hasLength
(
pattern
)
&&
!
pattern
.
startsWith
(
"/"
))
{
if
(
slashSeparator
&&
StringUtils
.
hasLength
(
pattern
)
&&
!
pattern
.
startsWith
(
"/"
))
{
pattern
=
"/"
+
pattern
;
pattern
=
"/"
+
pattern
;
...
@@ -89,6 +96,12 @@ public class DestinationPatternsMessageCondition
...
@@ -89,6 +96,12 @@ public class DestinationPatternsMessageCondition
return
result
;
return
result
;
}
}
private
DestinationPatternsMessageCondition
(
Set
<
String
>
patterns
,
RouteMatcher
routeMatcher
)
{
this
.
patterns
=
patterns
;
this
.
routeMatcher
=
routeMatcher
;
}
public
Set
<
String
>
getPatterns
()
{
public
Set
<
String
>
getPatterns
()
{
return
this
.
patterns
;
return
this
.
patterns
;
...
@@ -121,7 +134,7 @@ public class DestinationPatternsMessageCondition
...
@@ -121,7 +134,7 @@ public class DestinationPatternsMessageCondition
if
(!
this
.
patterns
.
isEmpty
()
&&
!
other
.
patterns
.
isEmpty
())
{
if
(!
this
.
patterns
.
isEmpty
()
&&
!
other
.
patterns
.
isEmpty
())
{
for
(
String
pattern1
:
this
.
patterns
)
{
for
(
String
pattern1
:
this
.
patterns
)
{
for
(
String
pattern2
:
other
.
patterns
)
{
for
(
String
pattern2
:
other
.
patterns
)
{
result
.
add
(
this
.
path
Matcher
.
combine
(
pattern1
,
pattern2
));
result
.
add
(
this
.
route
Matcher
.
combine
(
pattern1
,
pattern2
));
}
}
}
}
}
}
...
@@ -134,7 +147,7 @@ public class DestinationPatternsMessageCondition
...
@@ -134,7 +147,7 @@ public class DestinationPatternsMessageCondition
else
{
else
{
result
.
add
(
""
);
result
.
add
(
""
);
}
}
return
new
DestinationPatternsMessageCondition
(
result
,
this
.
path
Matcher
);
return
new
DestinationPatternsMessageCondition
(
result
,
this
.
route
Matcher
);
}
}
/**
/**
...
@@ -149,7 +162,7 @@ public class DestinationPatternsMessageCondition
...
@@ -149,7 +162,7 @@ public class DestinationPatternsMessageCondition
@Override
@Override
@Nullable
@Nullable
public
DestinationPatternsMessageCondition
getMatchingCondition
(
Message
<?>
message
)
{
public
DestinationPatternsMessageCondition
getMatchingCondition
(
Message
<?>
message
)
{
String
destination
=
(
String
)
message
.
getHeaders
().
get
(
LOOKUP_DESTINATION_HEADER
);
Object
destination
=
message
.
getHeaders
().
get
(
LOOKUP_DESTINATION_HEADER
);
if
(
destination
==
null
)
{
if
(
destination
==
null
)
{
return
null
;
return
null
;
}
}
...
@@ -157,18 +170,33 @@ public class DestinationPatternsMessageCondition
...
@@ -157,18 +170,33 @@ public class DestinationPatternsMessageCondition
return
this
;
return
this
;
}
}
List
<
String
>
matches
=
n
ew
ArrayList
<>()
;
List
<
String
>
matches
=
n
ull
;
for
(
String
pattern
:
this
.
patterns
)
{
for
(
String
pattern
:
this
.
patterns
)
{
if
(
pattern
.
equals
(
destination
)
||
this
.
pathMatcher
.
match
(
pattern
,
destination
))
{
if
(
pattern
.
equals
(
destination
)
||
matchPattern
(
pattern
,
destination
))
{
if
(
matches
==
null
)
{
matches
=
new
ArrayList
<>();
}
matches
.
add
(
pattern
);
matches
.
add
(
pattern
);
}
}
}
}
if
(
matches
.
isEmpty
(
))
{
if
(
CollectionUtils
.
isEmpty
(
matches
))
{
return
null
;
return
null
;
}
}
matches
.
sort
(
this
.
pathMatcher
.
getPatternComparator
(
destination
));
matches
.
sort
(
getPatternComparator
(
destination
));
return
new
DestinationPatternsMessageCondition
(
matches
,
this
.
pathMatcher
);
return
new
DestinationPatternsMessageCondition
(
new
LinkedHashSet
<>(
matches
),
this
.
routeMatcher
);
}
private
boolean
matchPattern
(
String
pattern
,
Object
destination
)
{
return
destination
instanceof
RouteMatcher
.
Route
?
this
.
routeMatcher
.
match
(
pattern
,
(
RouteMatcher
.
Route
)
destination
)
:
((
SimpleRouteMatcher
)
this
.
routeMatcher
).
getPathMatcher
().
match
(
pattern
,
(
String
)
destination
);
}
private
Comparator
<
String
>
getPatternComparator
(
Object
destination
)
{
return
destination
instanceof
RouteMatcher
.
Route
?
this
.
routeMatcher
.
getPatternComparator
((
RouteMatcher
.
Route
)
destination
)
:
((
SimpleRouteMatcher
)
this
.
routeMatcher
).
getPathMatcher
().
getPatternComparator
((
String
)
destination
);
}
}
/**
/**
...
@@ -183,12 +211,12 @@ public class DestinationPatternsMessageCondition
...
@@ -183,12 +211,12 @@ public class DestinationPatternsMessageCondition
*/
*/
@Override
@Override
public
int
compareTo
(
DestinationPatternsMessageCondition
other
,
Message
<?>
message
)
{
public
int
compareTo
(
DestinationPatternsMessageCondition
other
,
Message
<?>
message
)
{
String
destination
=
(
String
)
message
.
getHeaders
().
get
(
LOOKUP_DESTINATION_HEADER
);
Object
destination
=
message
.
getHeaders
().
get
(
LOOKUP_DESTINATION_HEADER
);
if
(
destination
==
null
)
{
if
(
destination
==
null
)
{
return
0
;
return
0
;
}
}
Comparator
<
String
>
patternComparator
=
this
.
pathMatcher
.
getPatternComparator
(
destination
);
Comparator
<
String
>
patternComparator
=
getPatternComparator
(
destination
);
Iterator
<
String
>
iterator
=
this
.
patterns
.
iterator
();
Iterator
<
String
>
iterator
=
this
.
patterns
.
iterator
();
Iterator
<
String
>
iteratorOther
=
other
.
patterns
.
iterator
();
Iterator
<
String
>
iteratorOther
=
other
.
patterns
.
iterator
();
while
(
iterator
.
hasNext
()
&&
iteratorOther
.
hasNext
())
{
while
(
iterator
.
hasNext
()
&&
iteratorOther
.
hasNext
())
{
...
...
spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java
浏览文件 @
97c2de91
...
@@ -56,7 +56,8 @@ import org.springframework.stereotype.Controller;
...
@@ -56,7 +56,8 @@ import org.springframework.stereotype.Controller;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.util.RouteMatcher
;
import
org.springframework.util.SimpleRouteMatcher
;
import
org.springframework.util.StringValueResolver
;
import
org.springframework.util.StringValueResolver
;
import
org.springframework.validation.Validator
;
import
org.springframework.validation.Validator
;
...
@@ -91,7 +92,7 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
...
@@ -91,7 +92,7 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
@Nullable
@Nullable
private
Validator
validator
;
private
Validator
validator
;
private
PathMatcher
path
Matcher
;
private
RouteMatcher
route
Matcher
;
private
ConversionService
conversionService
=
new
DefaultFormattingConversionService
();
private
ConversionService
conversionService
=
new
DefaultFormattingConversionService
();
...
@@ -100,8 +101,9 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
...
@@ -100,8 +101,9 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
public
MessageMappingMessageHandler
()
{
public
MessageMappingMessageHandler
()
{
this
.
pathMatcher
=
new
AntPathMatcher
();
AntPathMatcher
pathMatcher
=
new
AntPathMatcher
();
((
AntPathMatcher
)
this
.
pathMatcher
).
setPathSeparator
(
"."
);
pathMatcher
.
setPathSeparator
(
"."
);
this
.
routeMatcher
=
new
SimpleRouteMatcher
(
pathMatcher
);
}
}
...
@@ -187,20 +189,23 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
...
@@ -187,20 +189,23 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
}
}
/**
/**
* Set the PathMatcher implementation to use for matching destinations
* Set the {@code RouteMatcher} to use for mapping messages to handlers
* against configured destination patterns.
* based on the route patterns they're configured with.
* <p>By default, {@link AntPathMatcher} is used with separator set to ".".
* <p>By default, {@link SimpleRouteMatcher} is used, backed by
* {@link AntPathMatcher} with "." as separator. For greater
* efficiency consider using the {@code PathPatternRouteMatcher} from
* {@code spring-web} instead.
*/
*/
public
void
set
PathMatcher
(
PathMatcher
path
Matcher
)
{
public
void
set
RouteMatcher
(
RouteMatcher
route
Matcher
)
{
Assert
.
notNull
(
pathMatcher
,
"Path
Matcher must not be null"
);
Assert
.
notNull
(
routeMatcher
,
"Route
Matcher must not be null"
);
this
.
pathMatcher
=
path
Matcher
;
this
.
routeMatcher
=
route
Matcher
;
}
}
/**
/**
* Return the
PathMatcher implementation to use for matching destination
s.
* Return the
{@code RouteMatcher} used to map messages to handler
s.
*/
*/
public
PathMatcher
getPath
Matcher
()
{
public
RouteMatcher
getRoute
Matcher
()
{
return
this
.
path
Matcher
;
return
this
.
route
Matcher
;
}
}
/**
/**
...
@@ -289,14 +294,15 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
...
@@ -289,14 +294,15 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
.
map
(
s
->
this
.
valueResolver
.
resolveStringValue
(
s
))
.
map
(
s
->
this
.
valueResolver
.
resolveStringValue
(
s
))
.
toArray
(
String
[]::
new
);
.
toArray
(
String
[]::
new
);
}
}
return
new
CompositeMessageCondition
(
new
DestinationPatternsMessageCondition
(
destinations
,
this
.
pathMatcher
));
return
new
CompositeMessageCondition
(
new
DestinationPatternsMessageCondition
(
destinations
,
this
.
routeMatcher
));
}
}
@Override
@Override
protected
Set
<
String
>
getDirectLookupMappings
(
CompositeMessageCondition
mapping
)
{
protected
Set
<
String
>
getDirectLookupMappings
(
CompositeMessageCondition
mapping
)
{
Set
<
String
>
result
=
new
LinkedHashSet
<>();
Set
<
String
>
result
=
new
LinkedHashSet
<>();
for
(
String
pattern
:
mapping
.
getCondition
(
DestinationPatternsMessageCondition
.
class
).
getPatterns
())
{
for
(
String
pattern
:
mapping
.
getCondition
(
DestinationPatternsMessageCondition
.
class
).
getPatterns
())
{
if
(!
this
.
path
Matcher
.
isPattern
(
pattern
))
{
if
(!
this
.
route
Matcher
.
isPattern
(
pattern
))
{
result
.
add
(
pattern
);
result
.
add
(
pattern
);
}
}
}
}
...
@@ -304,8 +310,9 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
...
@@ -304,8 +310,9 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
}
}
@Override
@Override
protected
String
getDestination
(
Message
<?>
message
)
{
protected
RouteMatcher
.
Route
getDestination
(
Message
<?>
message
)
{
return
(
String
)
message
.
getHeaders
().
get
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
);
return
(
RouteMatcher
.
Route
)
message
.
getHeaders
()
.
get
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
);
}
}
@Override
@Override
...
@@ -324,13 +331,15 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
...
@@ -324,13 +331,15 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler<C
}
}
@Override
@Override
protected
Mono
<
Void
>
handleMatch
(
CompositeMessageCondition
mapping
,
HandlerMethod
handlerMethod
,
Message
<?>
message
)
{
protected
Mono
<
Void
>
handleMatch
(
CompositeMessageCondition
mapping
,
HandlerMethod
handlerMethod
,
Message
<?>
message
)
{
Set
<
String
>
patterns
=
mapping
.
getCondition
(
DestinationPatternsMessageCondition
.
class
).
getPatterns
();
Set
<
String
>
patterns
=
mapping
.
getCondition
(
DestinationPatternsMessageCondition
.
class
).
getPatterns
();
if
(!
CollectionUtils
.
isEmpty
(
patterns
))
{
if
(!
CollectionUtils
.
isEmpty
(
patterns
))
{
String
pattern
=
patterns
.
iterator
().
next
();
String
pattern
=
patterns
.
iterator
().
next
();
String
destination
=
getDestination
(
message
);
RouteMatcher
.
Route
destination
=
getDestination
(
message
);
Assert
.
state
(
destination
!=
null
,
"Missing destination header"
);
Assert
.
state
(
destination
!=
null
,
"Missing destination header"
);
Map
<
String
,
String
>
vars
=
get
PathMatcher
().
extractUriTemplateVariables
(
pattern
,
destination
);
Map
<
String
,
String
>
vars
=
get
RouteMatcher
().
matchAndExtract
(
pattern
,
destination
);
if
(!
CollectionUtils
.
isEmpty
(
vars
))
{
if
(!
CollectionUtils
.
isEmpty
(
vars
))
{
MessageHeaderAccessor
mha
=
MessageHeaderAccessor
.
getAccessor
(
message
,
MessageHeaderAccessor
.
class
);
MessageHeaderAccessor
mha
=
MessageHeaderAccessor
.
getAccessor
(
message
,
MessageHeaderAccessor
.
class
);
Assert
.
state
(
mha
!=
null
&&
mha
.
isMutable
(),
"Mutable MessageHeaderAccessor required"
);
Assert
.
state
(
mha
!=
null
&&
mha
.
isMutable
(),
"Mutable MessageHeaderAccessor required"
);
...
...
spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java
浏览文件 @
97c2de91
...
@@ -53,6 +53,7 @@ import org.springframework.util.CollectionUtils;
...
@@ -53,6 +53,7 @@ import org.springframework.util.CollectionUtils;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.util.RouteMatcher
;
/**
/**
* Abstract base class for reactive HandlerMethod-based message handling.
* Abstract base class for reactive HandlerMethod-based message handling.
...
@@ -393,8 +394,8 @@ public abstract class AbstractMethodMessageHandler<T>
...
@@ -393,8 +394,8 @@ public abstract class AbstractMethodMessageHandler<T>
private
Match
<
T
>
getHandlerMethod
(
Message
<?>
message
)
{
private
Match
<
T
>
getHandlerMethod
(
Message
<?>
message
)
{
List
<
Match
<
T
>>
matches
=
new
ArrayList
<>();
List
<
Match
<
T
>>
matches
=
new
ArrayList
<>();
String
destination
=
getDestination
(
message
);
RouteMatcher
.
Route
destination
=
getDestination
(
message
);
List
<
T
>
mappingsByUrl
=
destination
!=
null
?
this
.
destinationLookup
.
get
(
destination
)
:
null
;
List
<
T
>
mappingsByUrl
=
destination
!=
null
?
this
.
destinationLookup
.
get
(
destination
.
value
()
)
:
null
;
if
(
mappingsByUrl
!=
null
)
{
if
(
mappingsByUrl
!=
null
)
{
addMatchesToCollection
(
mappingsByUrl
,
message
,
matches
);
addMatchesToCollection
(
mappingsByUrl
,
message
,
matches
);
}
}
...
@@ -418,23 +419,21 @@ public abstract class AbstractMethodMessageHandler<T>
...
@@ -418,23 +419,21 @@ public abstract class AbstractMethodMessageHandler<T>
if
(
comparator
.
compare
(
bestMatch
,
secondBestMatch
)
==
0
)
{
if
(
comparator
.
compare
(
bestMatch
,
secondBestMatch
)
==
0
)
{
HandlerMethod
m1
=
bestMatch
.
handlerMethod
;
HandlerMethod
m1
=
bestMatch
.
handlerMethod
;
HandlerMethod
m2
=
secondBestMatch
.
handlerMethod
;
HandlerMethod
m2
=
secondBestMatch
.
handlerMethod
;
throw
new
IllegalStateException
(
"Ambiguous handler methods mapped for destination '"
+
throw
new
IllegalStateException
(
destination
+
"': {"
+
m1
.
getShortLogMessage
()
+
", "
+
m2
.
getShortLogMessage
()
+
"}"
);
"Ambiguous handler methods mapped for destination '"
+
destination
.
value
()
+
"': {"
+
m1
.
getShortLogMessage
()
+
", "
+
m2
.
getShortLogMessage
()
+
"}"
);
}
}
}
}
return
bestMatch
;
return
bestMatch
;
}
}
/**
/**
* Extract a String-based destination, if any, that can be used to perform
* Extract the destination from the given message.
* a direct look up into the registered mappings.
* <p><strong>Note:</strong> This is completely optional. The mapping
* metadata for a sub-class may support neither direct lookups, nor String
* based destinations.
* @see #getDirectLookupMappings(Object)
* @see #getDirectLookupMappings(Object)
*/
*/
@Nullable
@Nullable
protected
abstract
String
getDestination
(
Message
<?>
message
);
protected
abstract
RouteMatcher
.
Route
getDestination
(
Message
<?>
message
);
private
void
addMatchesToCollection
(
private
void
addMatchesToCollection
(
Collection
<
T
>
mappingsToCheck
,
Message
<?>
message
,
List
<
Match
<
T
>>
matches
)
{
Collection
<
T
>
mappingsToCheck
,
Message
<?>
message
,
List
<
Match
<
T
>>
matches
)
{
...
@@ -470,8 +469,9 @@ public abstract class AbstractMethodMessageHandler<T>
...
@@ -470,8 +469,9 @@ public abstract class AbstractMethodMessageHandler<T>
* @param destination the destination
* @param destination the destination
* @param message the message
* @param message the message
*/
*/
protected
void
handleNoMatch
(
@Nullable
String
destination
,
Message
<?>
message
)
{
protected
void
handleNoMatch
(
@Nullable
RouteMatcher
.
Route
destination
,
Message
<?>
message
)
{
logger
.
debug
(
"No handlers for destination '"
+
destination
+
"'"
);
logger
.
debug
(
"No handlers for destination '"
+
(
destination
!=
null
?
destination
.
value
()
:
""
)
+
"'"
);
}
}
/**
/**
...
...
spring-messaging/src/main/java/org/springframework/messaging/rsocket/MessageHandlerAcceptor.java
浏览文件 @
97c2de91
...
@@ -73,6 +73,7 @@ public final class MessageHandlerAcceptor extends RSocketMessageHandler
...
@@ -73,6 +73,7 @@ public final class MessageHandlerAcceptor extends RSocketMessageHandler
private
MessagingRSocket
createRSocket
(
RSocket
rsocket
)
{
private
MessagingRSocket
createRSocket
(
RSocket
rsocket
)
{
return
new
MessagingRSocket
(
this
::
handleMessage
,
return
new
MessagingRSocket
(
this
::
handleMessage
,
route
->
getRouteMatcher
().
parseRoute
(
route
),
RSocketRequester
.
wrap
(
rsocket
,
this
.
defaultDataMimeType
,
getRSocketStrategies
()),
RSocketRequester
.
wrap
(
rsocket
,
this
.
defaultDataMimeType
,
getRSocketStrategies
()),
this
.
defaultDataMimeType
,
this
.
defaultDataMimeType
,
getRSocketStrategies
().
dataBufferFactory
());
getRSocketStrategies
().
dataBufferFactory
());
...
...
spring-messaging/src/main/java/org/springframework/messaging/rsocket/MessagingRSocket.java
浏览文件 @
97c2de91
...
@@ -42,6 +42,7 @@ import org.springframework.messaging.support.MessageHeaderAccessor;
...
@@ -42,6 +42,7 @@ import org.springframework.messaging.support.MessageHeaderAccessor;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
import
org.springframework.util.MimeType
;
import
org.springframework.util.MimeType
;
import
org.springframework.util.MimeTypeUtils
;
import
org.springframework.util.MimeTypeUtils
;
import
org.springframework.util.RouteMatcher
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
/**
/**
...
@@ -56,6 +57,8 @@ class MessagingRSocket extends AbstractRSocket {
...
@@ -56,6 +57,8 @@ class MessagingRSocket extends AbstractRSocket {
private
final
Function
<
Message
<?>,
Mono
<
Void
>>
handler
;
private
final
Function
<
Message
<?>,
Mono
<
Void
>>
handler
;
private
final
Function
<
String
,
RouteMatcher
.
Route
>
routeParser
;
private
final
RSocketRequester
requester
;
private
final
RSocketRequester
requester
;
@Nullable
@Nullable
...
@@ -64,10 +67,13 @@ class MessagingRSocket extends AbstractRSocket {
...
@@ -64,10 +67,13 @@ class MessagingRSocket extends AbstractRSocket {
private
final
DataBufferFactory
bufferFactory
;
private
final
DataBufferFactory
bufferFactory
;
MessagingRSocket
(
Function
<
Message
<?>,
Mono
<
Void
>>
handler
,
RSocketRequester
requester
,
MessagingRSocket
(
Function
<
Message
<?>,
Mono
<
Void
>>
handler
,
Function
<
String
,
RouteMatcher
.
Route
>
routeParser
,
RSocketRequester
requester
,
@Nullable
MimeType
defaultDataMimeType
,
DataBufferFactory
bufferFactory
)
{
@Nullable
MimeType
defaultDataMimeType
,
DataBufferFactory
bufferFactory
)
{
this
.
routeParser
=
routeParser
;
Assert
.
notNull
(
handler
,
"'handler' is required"
);
Assert
.
notNull
(
handler
,
"'handler' is required"
);
Assert
.
notNull
(
routeParser
,
"'routeParser' is required"
);
Assert
.
notNull
(
requester
,
"'requester' is required"
);
Assert
.
notNull
(
requester
,
"'requester' is required"
);
this
.
handler
=
handler
;
this
.
handler
=
handler
;
this
.
requester
=
requester
;
this
.
requester
=
requester
;
...
@@ -181,7 +187,8 @@ class MessagingRSocket extends AbstractRSocket {
...
@@ -181,7 +187,8 @@ class MessagingRSocket extends AbstractRSocket {
private
MessageHeaders
createHeaders
(
String
destination
,
@Nullable
MonoProcessor
<?>
replyMono
)
{
private
MessageHeaders
createHeaders
(
String
destination
,
@Nullable
MonoProcessor
<?>
replyMono
)
{
MessageHeaderAccessor
headers
=
new
MessageHeaderAccessor
();
MessageHeaderAccessor
headers
=
new
MessageHeaderAccessor
();
headers
.
setLeaveMutable
(
true
);
headers
.
setLeaveMutable
(
true
);
headers
.
setHeader
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
destination
);
RouteMatcher
.
Route
route
=
this
.
routeParser
.
apply
(
destination
);
headers
.
setHeader
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
route
);
if
(
this
.
dataMimeType
!=
null
)
{
if
(
this
.
dataMimeType
!=
null
)
{
headers
.
setContentType
(
this
.
dataMimeType
);
headers
.
setContentType
(
this
.
dataMimeType
);
}
}
...
...
spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketMessageHandler.java
浏览文件 @
97c2de91
...
@@ -27,6 +27,7 @@ import org.springframework.messaging.MessageDeliveryException;
...
@@ -27,6 +27,7 @@ import org.springframework.messaging.MessageDeliveryException;
import
org.springframework.messaging.handler.annotation.reactive.MessageMappingMessageHandler
;
import
org.springframework.messaging.handler.annotation.reactive.MessageMappingMessageHandler
;
import
org.springframework.messaging.handler.invocation.reactive.HandlerMethodReturnValueHandler
;
import
org.springframework.messaging.handler.invocation.reactive.HandlerMethodReturnValueHandler
;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
import
org.springframework.util.RouteMatcher
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
/**
/**
...
@@ -110,16 +111,16 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler {
...
@@ -110,16 +111,16 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler {
}
}
@Override
@Override
protected
void
handleNoMatch
(
@Nullable
String
destination
,
Message
<?>
message
)
{
protected
void
handleNoMatch
(
@Nullable
RouteMatcher
.
Route
destination
,
Message
<?>
message
)
{
// MessagingRSocket will raise an error anyway if reply Mono is expected
// MessagingRSocket will raise an error anyway if reply Mono is expected
// Here we raise a more helpful message a destination is present
// Here we raise a more helpful message
if
a destination is present
// It is OK if some messages (ConnectionSetupPayload, metadataPush) are not handled
// It is OK if some messages (ConnectionSetupPayload, metadataPush) are not handled
//
We need a better way to avoid raising errors for thos
e
//
This works but would be better to have a more explicit way to differentiat
e
if
(
StringUtils
.
hasText
(
destination
))
{
if
(
destination
!=
null
&&
StringUtils
.
hasText
(
destination
.
value
()
))
{
throw
new
MessageDeliveryException
(
"No handler for destination '"
+
destination
+
"'"
);
throw
new
MessageDeliveryException
(
"No handler for destination '"
+
destination
.
value
()
+
"'"
);
}
}
}
}
...
...
spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandlerTests.java
浏览文件 @
97c2de91
...
@@ -47,6 +47,8 @@ import org.springframework.messaging.support.GenericMessage;
...
@@ -47,6 +47,8 @@ import org.springframework.messaging.support.GenericMessage;
import
org.springframework.messaging.support.MessageBuilder
;
import
org.springframework.messaging.support.MessageBuilder
;
import
org.springframework.messaging.support.MessageHeaderAccessor
;
import
org.springframework.messaging.support.MessageHeaderAccessor
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.SimpleRouteMatcher
;
import
static
java
.
nio
.
charset
.
StandardCharsets
.
UTF_8
;
import
static
java
.
nio
.
charset
.
StandardCharsets
.
UTF_8
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
...
@@ -117,11 +119,11 @@ public class MessageMappingMessageHandlerTests {
...
@@ -117,11 +119,11 @@ public class MessageMappingMessageHandlerTests {
public
void
unhandledExceptionShouldFlowThrough
()
{
public
void
unhandledExceptionShouldFlowThrough
()
{
GenericMessage
<?>
message
=
new
GenericMessage
<>(
new
Object
(),
GenericMessage
<?>
message
=
new
GenericMessage
<>(
new
Object
(),
Collections
.
singletonMap
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
"string"
));
Collections
.
singletonMap
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
new
SimpleRouteMatcher
(
new
AntPathMatcher
()).
parseRoute
(
"string"
)));
StepVerifier
.
create
(
initMesssageHandler
().
handleMessage
(
message
))
StepVerifier
.
create
(
initMesssageHandler
().
handleMessage
(
message
))
.
expectErrorSatisfies
(
ex
->
assertTrue
(
.
expectErrorSatisfies
(
ex
->
assertTrue
(
"Actual: "
+
ex
.
getMessage
(),
"Actual: "
+
ex
.
getMessage
(),
ex
.
getMessage
().
startsWith
(
"Could not resolve method parameter at index 0"
)))
ex
.
getMessage
().
startsWith
(
"Could not resolve method parameter at index 0"
)))
.
verify
(
Duration
.
ofSeconds
(
5
));
.
verify
(
Duration
.
ofSeconds
(
5
));
}
}
...
@@ -156,7 +158,8 @@ public class MessageMappingMessageHandlerTests {
...
@@ -156,7 +158,8 @@ public class MessageMappingMessageHandlerTests {
Flux
<
DataBuffer
>
payload
=
Flux
.
fromIterable
(
Arrays
.
asList
(
content
)).
map
(
parts
->
toDataBuffer
(
parts
));
Flux
<
DataBuffer
>
payload
=
Flux
.
fromIterable
(
Arrays
.
asList
(
content
)).
map
(
parts
->
toDataBuffer
(
parts
));
MessageHeaderAccessor
headers
=
new
MessageHeaderAccessor
();
MessageHeaderAccessor
headers
=
new
MessageHeaderAccessor
();
headers
.
setLeaveMutable
(
true
);
headers
.
setLeaveMutable
(
true
);
headers
.
setHeader
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
destination
);
headers
.
setHeader
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
new
SimpleRouteMatcher
(
new
AntPathMatcher
()).
parseRoute
(
destination
));
return
MessageBuilder
.
createMessage
(
payload
,
headers
.
getMessageHeaders
());
return
MessageBuilder
.
createMessage
(
payload
,
headers
.
getMessageHeaders
());
}
}
...
...
spring-messaging/src/test/java/org/springframework/messaging/handler/invocation/reactive/MethodMessageHandlerTests.java
浏览文件 @
97c2de91
...
@@ -44,6 +44,8 @@ import org.springframework.util.AntPathMatcher;
...
@@ -44,6 +44,8 @@ import org.springframework.util.AntPathMatcher;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.util.RouteMatcher
;
import
org.springframework.util.SimpleRouteMatcher
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
...
@@ -81,7 +83,8 @@ public class MethodMessageHandlerTests {
...
@@ -81,7 +83,8 @@ public class MethodMessageHandlerTests {
handler
.
afterPropertiesSet
();
handler
.
afterPropertiesSet
();
Message
<?>
message
=
new
GenericMessage
<>(
"body"
,
Collections
.
singletonMap
(
Message
<?>
message
=
new
GenericMessage
<>(
"body"
,
Collections
.
singletonMap
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
"/bestmatch/bar/path"
));
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
new
SimpleRouteMatcher
(
new
AntPathMatcher
()).
parseRoute
(
"/bestmatch/bar/path"
)));
handler
.
handleMessage
(
message
).
block
(
Duration
.
ofSeconds
(
5
));
handler
.
handleMessage
(
message
).
block
(
Duration
.
ofSeconds
(
5
));
...
@@ -102,7 +105,8 @@ public class MethodMessageHandlerTests {
...
@@ -102,7 +105,8 @@ public class MethodMessageHandlerTests {
TestController
.
class
);
TestController
.
class
);
Message
<?>
message
=
new
GenericMessage
<>(
"body"
,
Collections
.
singletonMap
(
Message
<?>
message
=
new
GenericMessage
<>(
"body"
,
Collections
.
singletonMap
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
"/handleMessageWithArgument"
));
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
new
SimpleRouteMatcher
(
new
AntPathMatcher
()).
parseRoute
(
"/handleMessageWithArgument"
)));
handler
.
handleMessage
(
message
).
block
(
Duration
.
ofSeconds
(
5
));
handler
.
handleMessage
(
message
).
block
(
Duration
.
ofSeconds
(
5
));
...
@@ -118,7 +122,8 @@ public class MethodMessageHandlerTests {
...
@@ -118,7 +122,8 @@ public class MethodMessageHandlerTests {
TestMethodMessageHandler
handler
=
initMethodMessageHandler
(
TestController
.
class
);
TestMethodMessageHandler
handler
=
initMethodMessageHandler
(
TestController
.
class
);
Message
<?>
message
=
new
GenericMessage
<>(
"body"
,
Collections
.
singletonMap
(
Message
<?>
message
=
new
GenericMessage
<>(
"body"
,
Collections
.
singletonMap
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
"/handleMessageWithError"
));
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
,
new
SimpleRouteMatcher
(
new
AntPathMatcher
()).
parseRoute
(
"/handleMessageWithError"
)));
handler
.
handleMessage
(
message
).
block
(
Duration
.
ofSeconds
(
5
));
handler
.
handleMessage
(
message
).
block
(
Duration
.
ofSeconds
(
5
));
...
@@ -238,22 +243,27 @@ public class MethodMessageHandlerTests {
...
@@ -238,22 +243,27 @@ public class MethodMessageHandlerTests {
@Override
@Override
@Nullable
@Nullable
protected
String
getDestination
(
Message
<?>
message
)
{
protected
RouteMatcher
.
Route
getDestination
(
Message
<?>
message
)
{
return
(
String
)
message
.
getHeaders
().
get
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
);
return
(
RouteMatcher
.
Route
)
message
.
getHeaders
().
get
(
DestinationPatternsMessageCondition
.
LOOKUP_DESTINATION_HEADER
);
}
}
@Override
@Override
protected
String
getMatchingMapping
(
String
mapping
,
Message
<?>
message
)
{
protected
String
getMatchingMapping
(
String
mapping
,
Message
<?>
message
)
{
String
destination
=
getDestination
(
message
);
RouteMatcher
.
Route
destination
=
getDestination
(
message
);
Assert
.
notNull
(
destination
,
"No destination"
);
Assert
.
notNull
(
destination
,
"No destination"
);
return
mapping
.
equals
(
destination
)
||
this
.
pathMatcher
.
match
(
mapping
,
destination
)
?
mapping
:
null
;
return
mapping
.
equals
(
destination
.
value
())
||
this
.
pathMatcher
.
match
(
mapping
,
destination
.
value
())
?
mapping
:
null
;
}
}
@Override
@Override
protected
Comparator
<
String
>
getMappingComparator
(
Message
<?>
message
)
{
protected
Comparator
<
String
>
getMappingComparator
(
Message
<?>
message
)
{
return
(
info1
,
info2
)
->
{
return
(
info1
,
info2
)
->
{
DestinationPatternsMessageCondition
cond1
=
new
DestinationPatternsMessageCondition
(
info1
);
SimpleRouteMatcher
routeMatcher
=
new
SimpleRouteMatcher
(
new
AntPathMatcher
());
DestinationPatternsMessageCondition
cond2
=
new
DestinationPatternsMessageCondition
(
info2
);
DestinationPatternsMessageCondition
cond1
=
new
DestinationPatternsMessageCondition
(
new
String
[]
{
info1
},
routeMatcher
);
DestinationPatternsMessageCondition
cond2
=
new
DestinationPatternsMessageCondition
(
new
String
[]
{
info2
},
routeMatcher
);
return
cond1
.
compareTo
(
cond2
,
message
);
return
cond1
.
compareTo
(
cond2
,
message
);
};
};
}
}
...
...
spring-web/src/main/java/org/springframework/web/util/pattern/PathPatternRouteMatcher.java
0 → 100644
浏览文件 @
97c2de91
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.web.util.pattern
;
import
java.util.Comparator
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
org.springframework.http.server.PathContainer
;
import
org.springframework.lang.Nullable
;
import
org.springframework.util.Assert
;
import
org.springframework.util.RouteMatcher
;
/**
* {@code RouteMatcher} built on {@link PathPatternParser} that uses
* {@link PathContainer} and {@link PathPattern} as parsed representations of
* routes and patterns.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
public
class
PathPatternRouteMatcher
implements
RouteMatcher
{
private
final
PathPatternParser
parser
;
private
final
Map
<
String
,
PathPattern
>
pathPatternCache
=
new
ConcurrentHashMap
<>();
public
PathPatternRouteMatcher
(
PathPatternParser
parser
)
{
Assert
.
notNull
(
parser
,
"PathPatternParser must not be null"
);
this
.
parser
=
parser
;
}
@Override
public
Route
parseRoute
(
String
routeValue
)
{
return
new
PathContainerRoute
(
PathContainer
.
parsePath
(
routeValue
));
}
@Override
public
boolean
isPattern
(
String
route
)
{
return
getPathPattern
(
route
).
hasPatternSyntax
();
}
@Override
public
String
combine
(
String
pattern1
,
String
pattern2
)
{
return
getPathPattern
(
pattern1
).
combine
(
getPathPattern
(
pattern2
)).
getPatternString
();
}
@Override
public
boolean
match
(
String
pattern
,
Route
route
)
{
return
getPathPattern
(
pattern
).
matches
(
getPathContainer
(
route
));
}
@Override
@Nullable
public
Map
<
String
,
String
>
matchAndExtract
(
String
pattern
,
Route
route
)
{
PathPattern
.
PathMatchInfo
info
=
getPathPattern
(
pattern
).
matchAndExtract
(
getPathContainer
(
route
));
return
info
!=
null
?
info
.
getUriVariables
()
:
null
;
}
@Override
public
Comparator
<
String
>
getPatternComparator
(
Route
route
)
{
return
Comparator
.
comparing
(
this
::
getPathPattern
);
}
private
PathPattern
getPathPattern
(
String
pattern
)
{
return
this
.
pathPatternCache
.
computeIfAbsent
(
pattern
,
this
.
parser
::
parse
);
}
private
PathContainer
getPathContainer
(
Route
route
)
{
Assert
.
isInstanceOf
(
PathContainerRoute
.
class
,
route
);
return
((
PathContainerRoute
)
route
).
pathContainer
;
}
private
static
class
PathContainerRoute
implements
Route
{
private
final
PathContainer
pathContainer
;
PathContainerRoute
(
PathContainer
pathContainer
)
{
this
.
pathContainer
=
pathContainer
;
}
@Override
public
String
value
()
{
return
this
.
pathContainer
.
value
();
}
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录