Skip to content

Commit 92759ed

Browse files
committed
Add exclude patterns for mapped interceptors
Add the ability provide exclude patterns for mapped interceptors in the MVC namespace and in the MVC Java config. Issue: SPR-6570
1 parent 5a36507 commit 92759ed

File tree

10 files changed

+236
-84
lines changed

10 files changed

+236
-84
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/InterceptorsBeanDefinitionParser.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
3131
/**
3232
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a {@code interceptors} element to register
3333
* a set of {@link MappedInterceptor} definitions.
34-
*
34+
*
3535
* @author Keith Donald
3636
* @since 3.0
3737
*/
@@ -40,37 +40,44 @@ class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
4040
public BeanDefinition parse(Element element, ParserContext parserContext) {
4141
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
4242
parserContext.pushContainingComponent(compDefinition);
43-
43+
4444
List<Element> interceptors = DomUtils.getChildElementsByTagName(element, new String[] { "bean", "ref", "interceptor" });
4545
for (Element interceptor : interceptors) {
4646
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
4747
mappedInterceptorDef.setSource(parserContext.extractSource(interceptor));
4848
mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
49-
50-
String[] pathPatterns;
49+
50+
String[] includePatterns = null;
51+
String[] excludePatterns = null;
5152
Object interceptorBean;
5253
if ("interceptor".equals(interceptor.getLocalName())) {
53-
List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, "mapping");
54-
pathPatterns = new String[paths.size()];
55-
for (int i = 0; i < paths.size(); i++) {
56-
pathPatterns[i] = paths.get(i).getAttribute("path");
57-
}
54+
includePatterns = getIncludePatterns(interceptor, "mapping");
55+
excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
5856
Element beanElem = DomUtils.getChildElementsByTagName(interceptor, new String[] { "bean", "ref"}).get(0);
5957
interceptorBean = parserContext.getDelegate().parsePropertySubElement(beanElem, null);
6058
}
6159
else {
62-
pathPatterns = null;
6360
interceptorBean = parserContext.getDelegate().parsePropertySubElement(interceptor, null);
6461
}
65-
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, pathPatterns);
66-
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, interceptorBean);
62+
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
63+
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
64+
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);
6765

6866
String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
6967
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
7068
}
71-
69+
7270
parserContext.popAndRegisterContainingComponent();
7371
return null;
7472
}
7573

74+
private String[] getIncludePatterns(Element interceptor, String elementName) {
75+
List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, elementName);
76+
String[] patterns = new String[paths.size()];
77+
for (int i = 0; i < paths.size(); i++) {
78+
patterns[i] = paths.get(i).getAttribute("path");
79+
}
80+
return patterns;
81+
}
82+
7683
}

spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistration.java

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,22 +21,24 @@
2121
import java.util.List;
2222

2323
import org.springframework.util.Assert;
24+
import org.springframework.util.CollectionUtils;
2425
import org.springframework.web.servlet.HandlerInterceptor;
2526
import org.springframework.web.servlet.handler.MappedInterceptor;
2627

2728
/**
28-
* Encapsulates a {@link HandlerInterceptor} and an optional list of URL patterns.
29-
* Results in the creation of a {@link MappedInterceptor} if URL patterns are provided.
30-
*
29+
* Assists with the creation of a {@link MappedInterceptor}.
30+
*
3131
* @author Rossen Stoyanchev
3232
* @author Keith Donald
3333
* @since 3.1
3434
*/
3535
public class InterceptorRegistration {
3636

3737
private final HandlerInterceptor interceptor;
38-
39-
private final List<String> pathPatterns = new ArrayList<String>();
38+
39+
private final List<String> includePatterns = new ArrayList<String>();
40+
41+
private final List<String> excludePatterns = new ArrayList<String>();
4042

4143
/**
4244
* Creates an {@link InterceptorRegistration} instance.
@@ -47,22 +49,39 @@ public InterceptorRegistration(HandlerInterceptor interceptor) {
4749
}
4850

4951
/**
50-
* Adds one or more URL patterns to which the registered interceptor should apply to.
51-
* If no URL patterns are provided, the interceptor applies to all paths.
52+
* Add URL patterns to which the registered interceptor should apply to.
5253
*/
53-
public void addPathPatterns(String... pathPatterns) {
54-
this.pathPatterns.addAll(Arrays.asList(pathPatterns));
54+
public InterceptorRegistration addPathPatterns(String... patterns) {
55+
this.includePatterns.addAll(Arrays.asList(patterns));
56+
return this;
5557
}
5658

5759
/**
58-
* Returns the underlying interceptor. If URL patterns are provided the returned type is
60+
* Add URL patterns to which the registered interceptor should not apply to.
61+
*/
62+
public InterceptorRegistration excludePathPatterns(String... patterns) {
63+
this.excludePatterns.addAll(Arrays.asList(patterns));
64+
return this;
65+
}
66+
67+
/**
68+
* Returns the underlying interceptor. If URL patterns are provided the returned type is
5969
* {@link MappedInterceptor}; otherwise {@link HandlerInterceptor}.
6070
*/
6171
protected Object getInterceptor() {
62-
if (pathPatterns.isEmpty()) {
63-
return interceptor;
72+
if (this.includePatterns.isEmpty()) {
73+
return this.interceptor;
74+
}
75+
return new MappedInterceptor(toArray(this.includePatterns), toArray(this.excludePatterns), interceptor);
76+
}
77+
78+
private static String[] toArray(List<String> list) {
79+
if (CollectionUtils.isEmpty(list)) {
80+
return null;
81+
}
82+
else {
83+
return list.toArray(new String[list.size()]);
6484
}
65-
return new MappedInterceptor(pathPatterns.toArray(new String[pathPatterns.size()]), interceptor);
6685
}
6786

6887
}

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

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,38 +29,58 @@
2929
* @since 3.0
3030
*/
3131
public final class MappedInterceptor {
32-
33-
private final String[] pathPatterns;
34-
32+
33+
private final String[] includePatterns;
34+
35+
private final String[] excludePatterns;
36+
3537
private final HandlerInterceptor interceptor;
3638

3739

40+
/**
41+
* Create a new MappedInterceptor instance.
42+
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
43+
* @param interceptor the HandlerInterceptor instance to map to the given patterns
44+
*/
45+
public MappedInterceptor(String[] includePatterns, HandlerInterceptor interceptor) {
46+
this(includePatterns, null, interceptor);
47+
}
48+
3849
/**
3950
* Create a new MappedInterceptor instance.
4051
* @param pathPatterns the path patterns to map with a {@code null} value matching to all paths
4152
* @param interceptor the HandlerInterceptor instance to map to the given patterns
4253
*/
43-
public MappedInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) {
44-
this.pathPatterns = pathPatterns;
54+
public MappedInterceptor(String[] includePatterns, String[] excludePatterns, HandlerInterceptor interceptor) {
55+
this.includePatterns = includePatterns;
56+
this.excludePatterns = excludePatterns;
4557
this.interceptor = interceptor;
4658
}
4759

4860
/**
4961
* Create a new MappedInterceptor instance.
50-
* @param pathPatterns the path patterns to map with a {@code null} value matching to all paths
62+
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
5163
* @param interceptor the WebRequestInterceptor instance to map to the given patterns
5264
*/
53-
public MappedInterceptor(String[] pathPatterns, WebRequestInterceptor interceptor) {
54-
this.pathPatterns = pathPatterns;
55-
this.interceptor = new WebRequestHandlerInterceptorAdapter(interceptor);
65+
public MappedInterceptor(String[] includePatterns, WebRequestInterceptor interceptor) {
66+
this(includePatterns, null, interceptor);
67+
}
68+
69+
/**
70+
* Create a new MappedInterceptor instance.
71+
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
72+
* @param interceptor the WebRequestInterceptor instance to map to the given patterns
73+
*/
74+
public MappedInterceptor(String[] includePatterns, String[] excludePatterns, WebRequestInterceptor interceptor) {
75+
this(includePatterns, excludePatterns, new WebRequestHandlerInterceptorAdapter(interceptor));
5676
}
5777

5878

5979
/**
6080
* The path into the application the interceptor is mapped to.
6181
*/
6282
public String[] getPathPatterns() {
63-
return this.pathPatterns;
83+
return this.includePatterns;
6484
}
6585

6686
/**
@@ -69,19 +89,26 @@ public String[] getPathPatterns() {
6989
public HandlerInterceptor getInterceptor() {
7090
return this.interceptor;
7191
}
72-
92+
7393
/**
74-
* Returns {@code true} if the interceptor applies to the given request path.
94+
* Returns {@code true} if the interceptor applies to the given request path.
7595
* @param lookupPath the current request path
7696
* @param pathMatcher a path matcher for path pattern matching
7797
*/
7898
public boolean matches(String lookupPath, PathMatcher pathMatcher) {
79-
if (pathPatterns == null) {
99+
if (this.excludePatterns != null) {
100+
for (String pattern : this.excludePatterns) {
101+
if (pathMatcher.match(pattern, lookupPath)) {
102+
return false;
103+
}
104+
}
105+
}
106+
if (this.includePatterns == null) {
80107
return true;
81108
}
82109
else {
83-
for (String pathPattern : pathPatterns) {
84-
if (pathMatcher.match(pathPattern, lookupPath)) {
110+
for (String pattern : this.includePatterns) {
111+
if (pathMatcher.match(pattern, lookupPath)) {
85112
return true;
86113
}
87114
}

spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,18 @@
273273
</xsd:attribute>
274274
</xsd:complexType>
275275
</xsd:element>
276+
<xsd:element name="exclude-mapping" minOccurs="0" maxOccurs="unbounded">
277+
<xsd:complexType>
278+
<xsd:attribute name="path" type="xsd:string" use="required">
279+
<xsd:annotation>
280+
<xsd:documentation><![CDATA[
281+
A path into the application that should not be intercepted by this interceptor.
282+
Exact path mapping URIs (such as "/admin") are supported as well as Ant-stype path patterns (such as /admin/**).
283+
]]></xsd:documentation>
284+
</xsd:annotation>
285+
</xsd:attribute>
286+
</xsd:complexType>
287+
</xsd:element>
276288
<xsd:choice>
277289
<xsd:element ref="beans:bean">
278290
<xsd:annotation>

0 commit comments

Comments
 (0)