Support custom PathMatcher for MappedInterceptor's

Issue: SPR-11197
This commit is contained in:
Rossen Stoyanchev
2014-01-03 16:42:26 -05:00
parent abb8a93e2f
commit de280b01fe
8 changed files with 190 additions and 20 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.web.servlet.config;
import java.util.List;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -44,6 +45,11 @@ class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compDefinition);
RuntimeBeanReference pathMatcherRef = null;
if (element.hasAttribute("path-matcher")) {
pathMatcherRef = new RuntimeBeanReference(element.getAttribute("path-matcher"));
}
List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
for (Element interceptor : interceptors) {
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
@@ -66,6 +72,10 @@ class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);
if (pathMatcherRef != null) {
mappedInterceptorDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
}
String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
}

View File

@@ -16,12 +16,11 @@
package org.springframework.web.servlet.config.annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptor;
@@ -40,6 +39,9 @@ public class InterceptorRegistration {
private final List<String> excludePatterns = new ArrayList<String>();
private PathMatcher pathMatcher;
/**
* Creates an {@link InterceptorRegistration} instance.
*/
@@ -64,6 +66,17 @@ public class InterceptorRegistration {
return this;
}
/**
* A PathMatcher implementation to use with this interceptor. This is an optional,
* advanced property required only if using custom PathMatcher implementations
* that support mapping metadata other than the Ant path patterns supported
* by default.
*/
public InterceptorRegistration pathMatcher(PathMatcher pathMatcher) {
this.pathMatcher = pathMatcher;
return this;
}
/**
* Returns the underlying interceptor. If URL patterns are provided the returned type is
* {@link MappedInterceptor}; otherwise {@link HandlerInterceptor}.
@@ -72,7 +85,12 @@ public class InterceptorRegistration {
if (this.includePatterns.isEmpty()) {
return this.interceptor;
}
return new MappedInterceptor(toArray(this.includePatterns), toArray(this.excludePatterns), interceptor);
MappedInterceptor mappedInterceptor = new MappedInterceptor(
toArray(this.includePatterns), toArray(this.excludePatterns), interceptor);
if (this.pathMatcher != null) {
mappedInterceptor.setPathMatcher(this.pathMatcher);
}
return mappedInterceptor;
}
private static String[] toArray(List<String> list) {

View File

@@ -36,6 +36,8 @@ public final class MappedInterceptor {
private final HandlerInterceptor interceptor;
private PathMatcher pathMatcher;
/**
* Create a new MappedInterceptor instance.
@@ -58,6 +60,7 @@ public final class MappedInterceptor {
this.interceptor = interceptor;
}
/**
* Create a new MappedInterceptor instance.
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
@@ -77,6 +80,26 @@ public final class MappedInterceptor {
}
/**
* Configure a PathMatcher to use with this MappedInterceptor instead of the
* one passed by default to the {@link #matches(String, org.springframework.util.PathMatcher)}
* method. This is an advanced property that is only required when using custom
* PathMatcher implementations that support mapping metadata other than the
* Ant-style path patterns supported by default.
*
* @param pathMatcher the path matcher to use
*/
public void setPathMatcher(PathMatcher pathMatcher) {
this.pathMatcher = pathMatcher;
}
/**
* The configured PathMatcher, or {@code null}.
*/
public PathMatcher getPathMatcher() {
return this.pathMatcher;
}
/**
* The path into the application the interceptor is mapped to.
*/
@@ -97,9 +120,10 @@ public final class MappedInterceptor {
* @param pathMatcher a path matcher for path pattern matching
*/
public boolean matches(String lookupPath, PathMatcher pathMatcher) {
PathMatcher pathMatcherToUse = (this.pathMatcher != null) ? this.pathMatcher : pathMatcher;
if (this.excludePatterns != null) {
for (String pattern : this.excludePatterns) {
if (pathMatcher.match(pattern, lookupPath)) {
if (pathMatcherToUse.match(pattern, lookupPath)) {
return false;
}
}
@@ -109,7 +133,7 @@ public final class MappedInterceptor {
}
else {
for (String pattern : this.includePatterns) {
if (pathMatcher.match(pattern, lookupPath)) {
if (pathMatcherToUse.match(pattern, lookupPath)) {
return true;
}
}

View File

@@ -415,6 +415,20 @@
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:attribute name="path-matcher" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.util.PathMatcher"><![CDATA[
The bean name of a PathMatcher implementation to use with nested interceptors. This is an optional,
advanced property required only if using custom PathMatcher implementations that support mapping
metadata other than the Ant path patterns supported by default.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="java:org.springframework.util.PathMatcher" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>