This commit is contained in:
Phillip Webb 2013-10-25 11:43:13 -07:00
parent 8bd480441e
commit 12e896ed8b
7 changed files with 30 additions and 50 deletions

View File

@ -726,6 +726,7 @@ project("spring-webmvc-tiles3") {
} }
optional("org.apache.tiles:tiles-extras:3.0.1") { optional("org.apache.tiles:tiles-extras:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j" exclude group: "org.slf4j", module: "jcl-over-slf4j"
exclude group: "org.springframework", module: "spring-web"
} }
optional("org.apache.tiles:tiles-el:3.0.1") { optional("org.apache.tiles:tiles-el:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j" exclude group: "org.slf4j", module: "jcl-over-slf4j"

View File

@ -24,17 +24,17 @@ import java.lang.annotation.Target;
/** /**
* Annotation that indicates a method parameter should be bound to a path template * Annotation that indicates a method parameter should be bound to a path template
* variable. Supported on message handling methods such as {@link MessageMapping * variable. Supported on message handling methods such as
* @MessageMapping} for messages with path-like destination semantics. * {@link MessageMapping @MessageMapping} for messages with path-like destination
* <p> * semantics.
* A {@code @PathVariable} template variable is always required and does not have a *
* <p>A {@code @PathVariable} template variable is always required and does not have a
* default value to fall back on. * default value to fall back on.
* *
* @author Brian Clozel * @author Brian Clozel
* @since 4.0
* @see org.springframework.messaging.handler.annotation.MessageMapping * @see org.springframework.messaging.handler.annotation.MessageMapping
* @see org.springframework.messaging.simp.handler.SimpAnnotationMethodMessageHandler * @see org.springframework.messaging.simp.handler.SimpAnnotationMethodMessageHandler
*
* @since 4.0
*/ */
@Target(ElementType.PARAMETER) @Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -28,17 +28,19 @@ import java.lang.annotation.Target;
* environments. * environments.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 3.0
* @see RequestMapping * @see RequestMapping
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter * @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
* @since 3.0
*/ */
@Target(ElementType.PARAMETER) @Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface PathVariable { public @interface PathVariable {
/** The URI template variable to bind to. */ /**
* The URI template variable to bind to.
*/
String value() default ""; String value() default "";
} }

View File

@ -63,8 +63,7 @@ public class DefaultMvcUrls implements MvcUrls {
* {@link HandlerMethodArgumentResolver}s. Since both of these tend to be implemented * {@link HandlerMethodArgumentResolver}s. Since both of these tend to be implemented
* by the same class, the most convenient option is to obtain the configured * by the same class, the most convenient option is to obtain the configured
* {@code HandlerMethodArgumentResolvers} in the {@code RequestMappingHandlerAdapter} * {@code HandlerMethodArgumentResolvers} in the {@code RequestMappingHandlerAdapter}
* and provide that to this contstructor. * and provide that to this constructor.
*
* @param uriComponentsContributors a collection of {@link UriComponentsContributor} * @param uriComponentsContributors a collection of {@link UriComponentsContributor}
* or {@link HandlerMethodArgumentResolver}s. * or {@link HandlerMethodArgumentResolver}s.
*/ */
@ -77,26 +76,22 @@ public class DefaultMvcUrls implements MvcUrls {
* {@link HandlerMethodArgumentResolver}s. Since both of these tend to be implemented * {@link HandlerMethodArgumentResolver}s. Since both of these tend to be implemented
* by the same class, the most convenient option is to obtain the configured * by the same class, the most convenient option is to obtain the configured
* {@code HandlerMethodArgumentResolvers} in the {@code RequestMappingHandlerAdapter} * {@code HandlerMethodArgumentResolvers} in the {@code RequestMappingHandlerAdapter}
* and provide that to this contstructor. * and provide that to this constructor.
* <p>
* If the {@link ConversionService} argument is {@code null},
* {@link DefaultFormattingConversionService} will be used by default.
* *
* <p>If the {@link ConversionService} argument is {@code null},
* {@link DefaultFormattingConversionService} will be used by default.
* @param uriComponentsContributors a collection of {@link UriComponentsContributor} * @param uriComponentsContributors a collection of {@link UriComponentsContributor}
* or {@link HandlerMethodArgumentResolver}s. * or {@link HandlerMethodArgumentResolver}s.
* @param conversionService a ConversionService to use when method argument values * @param conversionService a ConversionService to use when method argument values
* need to be formatted as Strings before being added to the URI * need to be formatted as Strings before being added to the URI
*/ */
public DefaultMvcUrls(Collection<?> uriComponentsContributors, ConversionService conversionService) { public DefaultMvcUrls(Collection<?> uriComponentsContributors, ConversionService conversionService) {
Assert.notNull(uriComponentsContributors, "'uriComponentsContributors' must not be null"); Assert.notNull(uriComponentsContributors, "'uriComponentsContributors' must not be null");
for (Object contributor : uriComponentsContributors) { for (Object contributor : uriComponentsContributors) {
if (contributor instanceof UriComponentsContributor) { if (contributor instanceof UriComponentsContributor) {
this.contributors.add((UriComponentsContributor) contributor); this.contributors.add((UriComponentsContributor) contributor);
} }
} }
this.conversionService = (conversionService != null) ? this.conversionService = (conversionService != null) ?
conversionService : new DefaultFormattingConversionService(); conversionService : new DefaultFormattingConversionService();
} }
@ -118,14 +113,12 @@ public class DefaultMvcUrls implements MvcUrls {
private UriComponents applyContributers(UriComponentsBuilder builder, Method method, private UriComponents applyContributers(UriComponentsBuilder builder, Method method,
Object[] argumentValues, Map<String, Object> uriVars) { Object[] argumentValues, Map<String, Object> uriVars) {
if (this.contributors.isEmpty()) { if (this.contributors.isEmpty()) {
return builder.buildAndExpand(uriVars); return builder.buildAndExpand(uriVars);
} }
int paramCount = method.getParameters().length; int paramCount = method.getParameters().length;
int argCount = argumentValues.length; int argCount = argumentValues.length;
Assert.isTrue(paramCount == argCount, "Number of method parameters " + paramCount + Assert.isTrue(paramCount == argCount, "Number of method parameters " + paramCount +
" does not match number of argument values " + argCount); " does not match number of argument values " + argCount);
@ -145,7 +138,6 @@ public class DefaultMvcUrls implements MvcUrls {
@Override @Override
public UriComponents linkToMethodOn(Object mockController) { public UriComponents linkToMethodOn(Object mockController) {
Assert.isInstanceOf(ControllerMethodValues.class, mockController); Assert.isInstanceOf(ControllerMethodValues.class, mockController);
ControllerMethodValues controllerMethodValues = (ControllerMethodValues) mockController; ControllerMethodValues controllerMethodValues = (ControllerMethodValues) mockController;
@ -162,7 +154,6 @@ public class DefaultMvcUrls implements MvcUrls {
} }
private void addTypeLevelUriVaris(ControllerMethodValues info, Map<String, Object> uriVariables) { private void addTypeLevelUriVaris(ControllerMethodValues info, Map<String, Object> uriVariables) {
Object[] values = info.getTypeLevelUriVariables(); Object[] values = info.getTypeLevelUriVariables();
if (!ObjectUtils.isEmpty(values)) { if (!ObjectUtils.isEmpty(values)) {

View File

@ -43,7 +43,6 @@ import org.springframework.web.util.UriComponents;
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*
* @since 4.0 * @since 4.0
*/ */
public class MvcUrlUtils { public class MvcUrlUtils {
@ -67,7 +66,6 @@ public class MvcUrlUtils {
logger.warn("Multiple class level mappings on " + controllerType.getName() + ", using the first one"); logger.warn("Multiple class level mappings on " + controllerType.getName() + ", using the first one");
} }
return annot.value()[0]; return annot.value()[0];
} }
/** /**
@ -97,7 +95,6 @@ public class MvcUrlUtils {
* invoked method and argument values are remembered, and a "mock" value is returned * invoked method and argument values are remembered, and a "mock" value is returned
* so it can be used to help prepare a {@link UriComponents} through * so it can be used to help prepare a {@link UriComponents} through
* {@link MvcUrls#linkToMethodOn(Object)}. * {@link MvcUrls#linkToMethodOn(Object)}.
*
* @param controllerType the type of controller to mock, must not be {@literal null}. * @param controllerType the type of controller to mock, must not be {@literal null}.
* @param typeLevelUriVariables URI variables to expand into the type-level mapping * @param typeLevelUriVariables URI variables to expand into the type-level mapping
* @return the created controller instance * @return the created controller instance
@ -109,7 +106,6 @@ public class MvcUrlUtils {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <T> T initProxy(Class<?> type, ControllerMethodInvocationInterceptor interceptor) { private static <T> T initProxy(Class<?> type, ControllerMethodInvocationInterceptor interceptor) {
if (type.isInterface()) { if (type.isInterface()) {
ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE); ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE);
factory.addInterface(type); factory.addInterface(type);
@ -192,7 +188,7 @@ public class MvcUrlUtils {
* <p> * <p>
* Instances of this interface are returned from * Instances of this interface are returned from
* {@link MvcUrlUtils#controller(Class, Object...) controller(Class, Object...)} and * {@link MvcUrlUtils#controller(Class, Object...) controller(Class, Object...)} and
* are needed for {@link MvcUrls#linkToMethodOn(ControllerMethodValues)}. * are needed for {@link MvcUrls#linkToMethodOn(Object)}.
*/ */
public interface ControllerMethodValues { public interface ControllerMethodValues {

View File

@ -27,19 +27,18 @@ import org.springframework.web.util.UriComponentsBuilder;
/** /**
* A contract for creating URLs by referencing Spring MVC controllers and methods. * A contract for creating URLs by referencing Spring MVC controllers and methods.
* <p> *
* The MVC Java config and the MVC namespace automatically create an instance of this * <p>The MVC Java config and the MVC namespace automatically create an instance of this
* contract for use in controllers and anywhere else during the processing of a request. * contract for use in controllers and anywhere else during the processing of a request.
* The best way for access it is to have it autowired, or otherwise injected either by * The best way for access it is to have it autowired, or otherwise injected either by
* type or also qualified by name ("mvcUrls") if necessary. * type or also qualified by name ("mvcUrls") if necessary.
* <p> *
* If not using either option, with explicit configuration it's easy to create an instance * <p>If not using either option, with explicit configuration it's easy to create an
* of {@link DefaultMvcUrls} in Java config or in XML configuration, use * instance of {@link DefaultMvcUrls} in Java config or in XML configuration, use
* {@link DefaultMvcUrlsFactoryBean}. * {@link DefaultMvcUrlsFactoryBean}.
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*
* @since 4.0 * @since 4.0
*/ */
public interface MvcUrls { public interface MvcUrls {
@ -50,9 +49,7 @@ public interface MvcUrls {
* the Servlet mapping as well as the portion of the path matching to the controller * the Servlet mapping as well as the portion of the path matching to the controller
* level request mapping. If the controller contains multiple mappings, the * level request mapping. If the controller contains multiple mappings, the
* {@link DefaultMvcUrls} will use the first one. * {@link DefaultMvcUrls} will use the first one.
*
* @param controllerType the controller type to create a URL to * @param controllerType the controller type to create a URL to
*
* @return a builder that can be used to further build the {@link UriComponents}. * @return a builder that can be used to further build the {@link UriComponents}.
*/ */
UriComponentsBuilder linkToController(Class<?> controllerType); UriComponentsBuilder linkToController(Class<?> controllerType);
@ -60,19 +57,15 @@ public interface MvcUrls {
/** /**
* Create a {@link UriComponents} by pointing to a controller method along with method * Create a {@link UriComponents} by pointing to a controller method along with method
* argument values. * argument values.
* <p> *
* Type and method-level mappings of the controller method are extracted and the * <p>Type and method-level mappings of the controller method are extracted and the
* resulting {@link UriComponents} is further enriched with method argument values from * resulting {@link UriComponents} is further enriched with method argument values from
* {@link PathVariable} and {@link RequestParam} parameters. Any other arguments not * {@link PathVariable} and {@link RequestParam} parameters. Any other arguments not
* relevant to the building of the URL can be provided as {@literal null} and will be * relevant to the building of the URL can be provided as {@literal null} and will be
* ignored. Support for additional custom arguments can be added through a * ignored. Support for additional custom arguments can be added through a
* {@link UriComponentsContributor}. * {@link UriComponentsContributor}.
*
* FIXME Type-level URI template variables?
*
* @param method the target controller method * @param method the target controller method
* @param argumentValues argument values matching to method parameters * @param argumentValues argument values matching to method parameters
*
* @return UriComponents instance, never {@literal null} * @return UriComponents instance, never {@literal null}
*/ */
UriComponents linkToMethod(Method method, Object... argumentValues); UriComponents linkToMethod(Method method, Object... argumentValues);
@ -88,10 +81,10 @@ public interface MvcUrls {
* class AddressController { * class AddressController {
* *
* &#064;RequestMapping("/{country}") * &#064;RequestMapping("/{country}")
* public HttpEntity<Void> getAddressesForCountry(&#064;PathVariable String country) { } * public HttpEntity&lt;Void&gt; getAddressesForCountry(&#064;PathVariable String country) { ... }
* *
* &#064;RequestMapping(value="/", method=RequestMethod.POST) * &#064;RequestMapping(value="/", method=RequestMethod.POST)
* public void addAddress(Address address) { } * public void addAddress(Address address) { ... }
* } * }
* *
* // short-hand style with static import of MvcUrlUtils.controller * // short-hand style with static import of MvcUrlUtils.controller
@ -104,16 +97,13 @@ public interface MvcUrls {
* controller.addAddress(null); * controller.addAddress(null);
* *
* mvcUrls.linkToMethodOn(controller); * mvcUrls.linkToMethodOn(controller);
*
* </pre> * </pre>
* *
* The above mechanism supports {@link PathVariable} and {@link RequestParam} method * The above mechanism supports {@link PathVariable} and {@link RequestParam} method
* arguments. Any other arguments can be provided as {@literal null} and will be * arguments. Any other arguments can be provided as {@literal null} and will be
* ignored. Additional custom arguments can be added through an implementation of * ignored. Additional custom arguments can be added through an implementation of
* {@link UriComponentsContributor}. * {@link UriComponentsContributor}.
*
* @param mockController created via {@link MvcUrlUtils#controller(Class, Object...)} * @param mockController created via {@link MvcUrlUtils#controller(Class, Object...)}
*
* @return UriComponents instance, never {@literal null} * @return UriComponents instance, never {@literal null}
*/ */
UriComponents linkToMethodOn(Object mockController); UriComponents linkToMethodOn(Object mockController);