This is in the spec in "Matching Requests to Resource Methods"
Sort E
using (1) the number of literal characters in each member as the primary key (descending order), (2) the number of capturing groups as a secondary key (descending order), (3) the number of capturing groups with non-default regular expressions (i.e. not ‘([^ /]+?)’) as the tertiary key (descending order), ...
What happens is the candidate methods are sorted by specified ordered "key". I highlight them in bold.
The first sort key is the number of literal characters. So for these three
@Path{"user/{name : [a-zA-Z]+}")
@Path("user/{id : \\d+}")
@Path("user/me")
if the requested URI is ../user/me
, the last one will always be chosen, as it has the most literal characters (7, /
counts). The others only have 5.
Aside from ../users/me
anything else ../users/..
will depend on the regex. In your case one matches only numbers and one matches only letters. There is no way for these two regexes to overlap. So it will match accordingly.
Now just for fun, let's say we have
@Path{"user/{name : .*}")
@Path("user/{id : \\d+}")
@Path("user/me")
If you look at the top two, we now have overlapping regexes. The first will match all numbers, as will the second one. So which one will be used? We can't make any assumptions. This is a level of ambiguity not specified and I've seen different behavior from different implementations. AFAIK, there is no concept of a "best matching" regex. Either it matches or it doesn't.
But what if we wanted the {id : \\d+}
to always be checked first. If it matches numbers then that should be selected. We can hack it based on the specification. The spec talks about "capturing groups" which are basically the {..}
s. The second sorting key is the number of capturing groups. The way we could hack it is to add another "optional" group
@Path{"user/{name : .*}")
@Path("user/{id : \\d+}{dummy: (/)?}")
Now the latter has more capturing groups so it will always be ahead in the sort. All it does is allow an optional /
, which doesn't really affect the API, but insures that if the request URI is all numbers, this path will always be chose.
You can see a discussion with some test cases in this answer