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
This commit is contained in:
parent
2140648246
commit
6b129c52e3
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
* @RequestMapping("/people")
|
||||
* class PersonController {
|
||||
*
|
||||
* @RequestMapping("/{id}")
|
||||
* public HttpEntity<Void> getPerson(@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" %>
|
||||
*
|
||||
* <a href="${s:mvcUrl('PC#getPerson').arg(0,"123").build()}">Get Person</a>
|
||||
* </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 {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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…
Reference in New Issue