AntPathMatcher
AntPathMatcher tests paths such as config/dev/app.properties against Ant-style patterns such as config/**/*.properties, and extracts values from them.
Why use it
Resource patterns (resources:mail/*.txt) and @PropertySource locations already use it, so most applications never create one. Use it directly when your own code must match paths or dotted names: which uploaded files are stylesheets, which keys belong to a group, which route pattern fits best.
The syntax:
?matches one character.*matches zero or more characters within one segment.**matches zero or more whole segments.{name}captures part of a segment;{name:regex}captures it only when the regular expression matches.
Example
import 'package:spring_core_dart/spring_core_dart.dart';
const log = SpringLog('neon.static');
final matcher = AntPathMatcher();
// Which requested files are stylesheets.
bool isStylesheet(String path) => matcher.match('/static/**/*.css', path);
void main() {
log.info(isStylesheet('/static/css/app.css')); // true
// Pull the variable out of a path.
final vars = matcher.extractUriTemplateVariables(
'/users/{id:[0-9]+}',
'/users/42',
);
log.info(vars['id']); // 42
// Pick the most specific of several matching patterns.
final patterns = ['/**', '/hotels/*', '/hotels/{id}']
..sort(matcher.getPatternComparator('/hotels/1'));
log.info(patterns.first); // /hotels/{id}
// The same matcher works for dotted names.
final dots = AntPathMatcher(pathSeparator: '.');
log.info(dots.match('app.*.enabled', 'app.cache.enabled')); // true
}
Parameters
Constructor parameters:
| Name | Type | Default | Meaning |
|---|---|---|---|
pathSeparator |
String |
'/' |
The text between segments. |
caseSensitive |
bool |
true |
Whether segments are compared case-sensitively. |
trimTokens |
bool |
false |
Whether whitespace around segments is ignored. |
Methods of PathMatcher:
| Name | Returns | Meaning |
|---|---|---|
isPattern(path) |
bool |
Whether the text contains *, ? or a {name} variable. |
match(pattern, path) |
bool |
Whether the whole path matches. |
matchStart(pattern, path) |
bool |
Whether the path matches the start of the pattern, so a longer path could match. |
extractPathWithinPattern(pattern, path) |
String |
The part matched by the wildcards: /docs/* and /docs/a/b.html give a/b.html. |
extractUriTemplateVariables(pattern, path) |
Map<String, String> |
The {name} values; throws StateError when the path does not match. |
getPatternComparator(path) |
Comparator<String> |
Sorts patterns from most to least specific for the path. |
combine(pattern1, pattern2) |
String |
Joins two patterns: /hotels and {hotel} give /hotels/{hotel}. |
In Spring (Java)
var matcher = new AntPathMatcher();
matcher.match("/static/**/*.css", "/static/css/app.css");
matcher.extractUriTemplateVariables("/users/{id:[0-9]+}", "/users/42");
var dots = new AntPathMatcher(".");
dots.match("app.*.enabled", "app.cache.enabled");
Differences that matter:
- Options are named constructor parameters instead of setters (
setCaseSensitive,setTrimTokens). {name:regex}uses Dart'sRegExpsyntax. In a resource location, a\is cleaned to/(as Spring does), so write character classes such as[0-9]instead of\dthere.