Skip to content

Commit

Permalink
Improve and update docs on MvcUriComponentsBuilder
Browse files Browse the repository at this point in the history
Issue: SPR-12617
  • Loading branch information
rstoyanchev committed May 7, 2015
1 parent 1cc042d commit 2b528bb
Showing 1 changed file with 52 additions and 22 deletions.
74 changes: 52 additions & 22 deletions src/asciidoc/web-mvc.adoc
Expand Up @@ -3055,12 +3055,7 @@ also have the literal part of the servlet mapping included:
[[mvc-links-to-controllers]]
=== Building URIs to Controllers and methods

Spring MVC provides another mechanism for building and encoding URIs that link to
Controllers and methods defined within an application.
{javadoc-baseurl}/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.html[`MvcUriComponentsBuilder`]
extends `UriComponentsBuilder` and provides such possibilities.

Given this Controller:
Spring MVC also provides a mechanism for building links to controller methods. For example, given:

[source,java,indent=0]
[subs="verbatim,quotes"]
Expand All @@ -3077,19 +3072,27 @@ Given this Controller:
}
----

and using the `MvcUriComponentsBuilder`, the previous example is now:
You can prepare a link by referring to the method by name:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
UriComponents uriComponents = MvcUriComponentsBuilder
.fromMethodName(BookingController.class, "getBooking",21).buildAndExpand(42);
.fromMethodName(BookingController.class, "getBooking", 21).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
----

The `MvcUriComponentsBuilder` can also create "mock Controllers", thus enabling to create
URIs by coding against the actual Controller's API:
In the above example we provided actual method argument values, in this case the long value 21,
to be used as a path variable and inserted into the URL. Furthermore, we provided the
value 42 in order to fill in any remaining URI variables such as the "hotel" variable inherited
from the type-level request mapping. If the method had more arguments you can supply null for
arguments not needed for the URL. In general only `@PathVariable` and `@RequestParam` arguments
are relevant for constructing the URL.

There are additional ways to use `MvcUriComponentsBuilder`. For example you can use a technique
akin to mock testing through proxies to avoid referring to the controller method by name
(the example assumes static import of `MvcUriComponentsBuilder.on`):

[source,java,indent=0]
[subs="verbatim,quotes"]
Expand All @@ -3100,19 +3103,44 @@ URIs by coding against the actual Controller's API:
URI uri = uriComponents.encode().toUri();
----

The above examples use static methods in `MvcUriComponentsBuilder`. Internally they rely
on `ServletUriComponentsBuilder` to prepare a base URL from the scheme, host, port,
context path and servlet path of the current request. This works well in most cases,
however sometimes it may be insufficient. For example you may be outside the context of
a request (e.g. a batch process that prepares links) or perhaps you need to insert a path
prefix (e.g. a locale prefix that was removed from the request path and needs to be
re-inserted into links).

For such cases you can use the static "fromXxx" overloaded methods that accept a
`UriComponentsBuilder` to use base URL. Or you can create an instance of `MvcUriComponentsBuilder`
with a base URL and then use the instance-based "withXxx" methods. For example:

[source,java,indent=0]
[subs="verbatim,quotes"]
----
UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath().path("/en");
MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);
builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
----


[[mvc-links-to-controllers-from-views]]
=== Building URIs to Controllers and methods from views

It is also useful to build links to annotated controllers from views (e.g. JSP).
This can be done through a method on `MvcUriComponentsBuilder` which refers to mappings
by name called `fromMappingName`.
You can also build links to annotated controllers from views such as JSP, Thymeleaf,
FreeMarker. This can be done using the `fromMappingName` method in `MvcUriComponentsBuilder`
which refers to mappings by name.

As of 4.1 every `@RequestMapping` is assigned a default name based on the
capital letters of the class and the full method name. For example, the method `getFoo` in class
`FooController` is assigned the name "FC#getFoo". This naming strategy is pluggable
by implementing `HandlerMethodMappingNamingStrategy` and configuring it on your
`RequestMappingHandlerMapping`. Furthermore the `@RequestMapping` annotation includes
a name attribute that can be used to override the default strategy.
Every `@RequestMapping` is assigned a default name based on the capital letters of the
class and the full method name. For example, the method `getFoo` in class `FooController`
is assigned the name "FC#getFoo". This strategy can be replaced or customized by creating
an instance of `HandlerMethodMappingNamingStrategy` and plugging it into your
`RequestMappingHandlerMapping`. The default strategy implementation also looks at the
name attribute on `@RequestMapping` and uses that if present. That means if the default
mapping name assigned conflicts with another (e.g. overloaded methods) you can assign
a name explicitly on the `@RequestMapping`.

[NOTE]
====
Expand All @@ -3135,7 +3163,7 @@ For example given:
}
----

The following JSP code can prepare a link:
You can prepare a link from a JSP as follows:

[source,jsp,indent=0]
[subs="verbatim,quotes"]
Expand All @@ -3145,8 +3173,10 @@ The following JSP code can prepare a link:
<a href="${s:mvcUrl(''PC#getPerson'').arg(0,''US'').buildAndExpand(''123'')}">Get Person</a>
----



The above example relies on the `mvcUrl` JSP function declared in the Spring tag library
(i.e. META-INF/spring.tld). For more advanced cases (e.g. a custom base URL as explained
in the previous section), it is easy to define your own function, or use a custom tag file,
in order to use a specific instance of `MvcUriComponentsBuilder` with a custom base URL.


[[mvc-localeresolver]]
Expand Down

0 comments on commit 2b528bb

Please sign in to comment.