Browse Source

Add "mvcUrl" function to Spring tag library

This commit adds a new function to the Spring tag library for preparing
links to @Controller methods. For more details see the Javadoc of
MvcUriComponentsBuilder.fromMappingName.

Issue: SPR-5779
pull/556/merge
Rossen Stoyanchev 11 years ago
parent
commit
6b129c52e3
  1. 15
      spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMethodMappingNamingStrategy.java
  2. 103
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java
  3. 7
      spring-webmvc/src/main/resources/META-INF/spring.tld

15
spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerMethodMappingNamingStrategy.java

@ -21,7 +21,20 @@ import org.springframework.web.method.HandlerMethod; @@ -21,7 +21,20 @@ import org.springframework.web.method.HandlerMethod;
import java.lang.reflect.Method;
/**
* A strategy for assigning a name to a controller method mapping.
* A strategy for assigning a name to a handler method's mapping.
*
* <p>The strategy can be configured on
* {@link org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
* AbstractHandlerMethodMapping}. It is used to assign a name to the mapping of
* every registered handler method. The names can then be queried via
* {@link org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerMethodsForMappingName(String)
* AbstractHandlerMethodMapping#getHandlerMethodsForMappingName}.
*
* <p>Applications can build a URL to a controller method by name with the help
* of the static method
* {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder#fromMappingName(String)
* MvcUriComponentsBuilder#fromMappingName} or in JSPs through the "mvcUrl"
* function registered by the Spring tag library.
*
* @author Rossen Stoyanchev
* @since 4.1

103
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java

@ -193,38 +193,62 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { @@ -193,38 +193,62 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
}
/**
* Create a {@link UriComponentsBuilder} from a request mapping identified
* by name. The configured
* Create a URL from the name of a Spring MVC controller method's request mapping.
*
* <p>The configured
* {@link org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
* HandlerMethodMappingNamingStrategy} assigns a default name to every
* {@code @RequestMapping} method but an explicit name may also be assigned
* through the {@code @RequestMapping} name attribute.
* <p>This is intended for use in EL expressions, typically in JSPs or other
* view templates, which can use the convenience method {@link #toUriString()}.
* <p>The default naming convention for mappings is based on the capital
* letters of the class name, followed by "#" as a separator, and the method
* name. For example "TC#getFoo" for a class named TestController with method
* getFoo. Use explicit names where the naming convention does not produce
* unique results.
* @param name the mapping name
* @param argumentValues argument values for the controller method; those values
* are important for {@code @RequestParam} and {@code @PathVariable} arguments
* but may be passed as {@code null} otherwise.
* @return the UriComponentsBuilder
* HandlerMethodMappingNamingStrategy} determines the names of controller
* method request mappings at startup. By default all mappings are assigned
* a name based on the capital letters of the class name, followed by "#" as
* separator, and then the method name. For example "PC#getPerson"
* for a class named PersonController with method getPerson. In case the
* naming convention does not produce unique results, an explicit name may
* be assigned through the name attribute of the {@code @RequestMapping}
* annotation.
*
* <p>This is aimed primarily for use in view rendering technologies and EL
* expressions. The Spring URL tag library registers this method as a function
* called "mvcUrl".
*
* <p>For example, given this controller:
* <pre class="code">
* &#064;RequestMapping("/people")
* class PersonController {
*
* &#064;RequestMapping("/{id}")
* public HttpEntity<Void> getPerson(&#064;PathVariable String id) { ... }
*
* }
* </pre>
*
* A JSP can prepare a URL to the controller method as follows:
*
* <pre class="code">
* <%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
*
* &lt;a href="${s:mvcUrl('PC#getPerson').arg(0,"123").build()}"&gt;Get Person&lt;/a&gt;
* </pre>
*
* <p>Note that it's not necessary to specify all arguments. Only the ones
* required to prepare the URL, mainly {@code @RequestParam} and {@code @PathVariable}).
*
* @param mappingName the mapping name
* @return a builder to to prepare the URI String
* @throws IllegalArgumentException if the mapping name is not found or
* if there is no unique match
* @since 4.1
*/
public static UriComponentsBuilder fromMappingName(String name, Object... argumentValues) {
RequestMappingInfoHandlerMapping hm = getRequestMappingInfoHandlerMapping();
List<HandlerMethod> handlerMethods = hm.getHandlerMethodsForMappingName(name);
public static MethodArgumentBuilder fromMappingName(String mappingName) {
RequestMappingInfoHandlerMapping handlerMapping = getRequestMappingInfoHandlerMapping();
List<HandlerMethod> handlerMethods = handlerMapping.getHandlerMethodsForMappingName(mappingName);
if (handlerMethods == null) {
throw new IllegalArgumentException("Mapping name not found: " + name);
throw new IllegalArgumentException("Mapping mappingName not found: " + mappingName);
}
if (handlerMethods.size() != 1) {
throw new IllegalArgumentException("No unique match for mapping name " + name + ": " + handlerMethods);
throw new IllegalArgumentException(
"No unique match for mapping mappingName " + mappingName + ": " + handlerMethods);
}
return fromMethod(handlerMethods.get(0).getMethod(), argumentValues);
return new MethodArgumentBuilder(handlerMethods.get(0).getMethod());
}
/**
@ -455,4 +479,37 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { @@ -455,4 +479,37 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
Object[] getArgumentValues();
}
public static class MethodArgumentBuilder {
private final Method method;
private final Object[] argumentValues;
public MethodArgumentBuilder(Method method) {
Assert.notNull(method, "'method' is required");
this.method = method;
this.argumentValues = new Object[method.getParameterTypes().length];
for (int i = 0; i < this.argumentValues.length; i++) {
this.argumentValues[i] = null;
}
}
public MethodArgumentBuilder arg(int index, Object value) {
this.argumentValues[index] = value;
return this;
}
public String build() {
return MvcUriComponentsBuilder.fromMethod(this.method, this.argumentValues)
.build(false).encode().toUriString();
}
public String buildAndExpand(Object... uriVariables) {
return MvcUriComponentsBuilder.fromMethod(this.method, this.argumentValues)
.build(false).expand(uriVariables).encode().toString();
}
}
}

7
spring-webmvc/src/main/resources/META-INF/spring.tld

@ -472,4 +472,11 @@ @@ -472,4 +472,11 @@
</attribute>
</tag>
<function>
<description>Helps to prepare a URL to a Spring MVC controller method.</description>
<name>mvcUrl</name>
<function-class>org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder</function-class>
<function-signature>org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.MethodArgumentBuilder fromMappingName(java.lang.String)</function-signature>
</function>
</taglib>

Loading…
Cancel
Save