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;
|
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
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
|
|
@ -193,38 +193,62 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link UriComponentsBuilder} from a request mapping identified
|
* Create a URL from the name of a Spring MVC controller method's request mapping.
|
||||||
* by name. The configured
|
*
|
||||||
|
* <p>The configured
|
||||||
* {@link org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
|
* {@link org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
|
||||||
* HandlerMethodMappingNamingStrategy} assigns a default name to every
|
* HandlerMethodMappingNamingStrategy} determines the names of controller
|
||||||
* {@code @RequestMapping} method but an explicit name may also be assigned
|
* method request mappings at startup. By default all mappings are assigned
|
||||||
* through the {@code @RequestMapping} name attribute.
|
* a name based on the capital letters of the class name, followed by "#" as
|
||||||
* <p>This is intended for use in EL expressions, typically in JSPs or other
|
* separator, and then the method name. For example "PC#getPerson"
|
||||||
* view templates, which can use the convenience method {@link #toUriString()}.
|
* for a class named PersonController with method getPerson. In case the
|
||||||
* <p>The default naming convention for mappings is based on the capital
|
* naming convention does not produce unique results, an explicit name may
|
||||||
* letters of the class name, followed by "#" as a separator, and the method
|
* be assigned through the name attribute of the {@code @RequestMapping}
|
||||||
* name. For example "TC#getFoo" for a class named TestController with method
|
* annotation.
|
||||||
* getFoo. Use explicit names where the naming convention does not produce
|
*
|
||||||
* unique results.
|
* <p>This is aimed primarily for use in view rendering technologies and EL
|
||||||
* @param name the mapping name
|
* expressions. The Spring URL tag library registers this method as a function
|
||||||
* @param argumentValues argument values for the controller method; those values
|
* called "mvcUrl".
|
||||||
* are important for {@code @RequestParam} and {@code @PathVariable} arguments
|
*
|
||||||
* but may be passed as {@code null} otherwise.
|
* <p>For example, given this controller:
|
||||||
* @return the UriComponentsBuilder
|
* <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
|
* @throws IllegalArgumentException if the mapping name is not found or
|
||||||
* if there is no unique match
|
* if there is no unique match
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromMappingName(String name, Object... argumentValues) {
|
public static MethodArgumentBuilder fromMappingName(String mappingName) {
|
||||||
RequestMappingInfoHandlerMapping hm = getRequestMappingInfoHandlerMapping();
|
RequestMappingInfoHandlerMapping handlerMapping = getRequestMappingInfoHandlerMapping();
|
||||||
List<HandlerMethod> handlerMethods = hm.getHandlerMethodsForMappingName(name);
|
List<HandlerMethod> handlerMethods = handlerMapping.getHandlerMethodsForMappingName(mappingName);
|
||||||
if (handlerMethods == null) {
|
if (handlerMethods == null) {
|
||||||
throw new IllegalArgumentException("Mapping name not found: " + name);
|
throw new IllegalArgumentException("Mapping mappingName not found: " + mappingName);
|
||||||
}
|
}
|
||||||
if (handlerMethods.size() != 1) {
|
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();
|
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>
|
</attribute>
|
||||||
</tag>
|
</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>
|
</taglib>
|
||||||
|
|
Loading…
Reference in New Issue