ability to have multiple path patterns per mapped interceptor definition

This commit is contained in:
Keith Donald 2009-11-30 07:51:29 +00:00
parent d4a21f1db8
commit c8d6360855
8 changed files with 92 additions and 64 deletions

View File

@ -37,16 +37,28 @@ import org.w3c.dom.Element;
class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "interceptor");
List<Element> interceptors = DomUtils.getChildElementsByTagName(element, new String[] { "bean", "interceptor" });
for (Element interceptor : interceptors) {
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, interceptor.getAttribute("path"));
RootBeanDefinition interceptorDef = new RootBeanDefinition(interceptor.getAttribute("class"));
BeanDefinitionHolder holder = new BeanDefinitionHolder(interceptorDef, parserContext.getReaderContext().generateBeanName(interceptorDef));
holder = parserContext.getDelegate().decorateBeanDefinitionIfRequired(interceptor, holder);
parserContext.getDelegate().parseConstructorArgElements(interceptor, interceptorDef);
parserContext.getDelegate().parsePropertyElements(interceptor, interceptorDef);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, holder);
mappedInterceptorDef.setSource(parserContext.extractSource(interceptor));
String[] pathPatterns;
BeanDefinitionHolder interceptorDef;
if ("interceptor".equals(interceptor.getLocalName())) {
List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, "path");
pathPatterns = new String[paths.size()];
for (int i = 0; i < paths.size(); i++) {
pathPatterns[i] = paths.get(i).getAttribute("value");
}
Element interceptorBean = DomUtils.getChildElementByTagName(interceptor, "bean");
interceptorDef = parserContext.getDelegate().parseBeanDefinitionElement(interceptorBean);
interceptorDef = parserContext.getDelegate().decorateBeanDefinitionIfRequired(interceptorBean, interceptorDef);
} else {
pathPatterns = null;
interceptorDef = parserContext.getDelegate().parseBeanDefinitionElement(interceptor);
interceptorDef = parserContext.getDelegate().decorateBeanDefinitionIfRequired(interceptor, interceptorDef);
}
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, pathPatterns);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, interceptorDef);
parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
}
return null;

View File

@ -25,7 +25,7 @@ import org.springframework.web.servlet.HandlerInterceptor;
*/
public final class MappedInterceptor {
private final String pathPattern;
private final String[] pathPatterns;
private final HandlerInterceptor interceptor;
@ -34,8 +34,8 @@ public final class MappedInterceptor {
* @param pathPattern the path pattern
* @param interceptor the interceptor
*/
public MappedInterceptor(String pathPattern, HandlerInterceptor interceptor) {
this.pathPattern = pathPattern;
public MappedInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) {
this.pathPatterns = pathPatterns;
this.interceptor = interceptor;
}
@ -44,16 +44,16 @@ public final class MappedInterceptor {
* @param pathPattern the path pattern
* @param interceptor the interceptor
*/
public MappedInterceptor(String pathPattern, WebRequestInterceptor interceptor) {
this.pathPattern = pathPattern;
public MappedInterceptor(String[] pathPatterns, WebRequestInterceptor interceptor) {
this.pathPatterns = pathPatterns;
this.interceptor = new WebRequestHandlerInterceptorAdapter(interceptor);
}
/**
* The path into the application the interceptor is mapped to.
*/
public String getPathPattern() {
return pathPattern;
public String[] getPathPatterns() {
return pathPatterns;
}
/**

View File

@ -4,7 +4,6 @@ import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
class MappedInterceptors {
@ -26,9 +25,14 @@ class MappedInterceptors {
}
private boolean matches(MappedInterceptor interceptor, String lookupPath, PathMatcher pathMatcher) {
String pathPattern = interceptor.getPathPattern();
if (StringUtils.hasText(pathPattern)) {
return pathMatcher.match(pathPattern, lookupPath);
String[] pathPatterns = interceptor.getPathPatterns();
if (pathPatterns != null) {
for (String pattern : pathPatterns) {
if (pathMatcher.match(pattern, lookupPath)) {
return true;
}
}
return false;
} else {
return true;
}

View File

@ -50,52 +50,54 @@
<xsd:element name="interceptors">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.servlet.HandlerInterceptor"><![CDATA[
<xsd:documentation><![CDATA[
The ordered set of interceptors that intercept HTTP Servlet Requests handled by Controllers.
Interceptors allow a request to be pre/post processed before/after handling.
Each inteceptor should be configured as an inner bean that implements either the org.springframework.web.servlet.HandlerInterceptor or org.springframework.web.context.request.WebRequestInterceptor interface.
The interceptors in this set are automatically configured on each registered HandlerMapping.
Interceptors allow requests to be pre/post processed before/after handling.
Each inteceptor must implement the org.springframework.web.servlet.HandlerInterceptor or org.springframework.web.context.request.WebRequestInterceptor interface.
The interceptors in this set are automatically configured on each registered HandlerMapping.
The URI paths each interceptor applies to are configurable.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="interceptor" maxOccurs="unbounded">
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.servlet.handler.MappedInterceptor"><![CDATA[
Registers a interceptor definition.
Registers an interceptor that intercepts every request regardless of its URI path.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="interceptor">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.web.servlet.handler.MappedInterceptor"><![CDATA[
Registers an interceptor that interceptors requests sent to one or more URI paths.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="beans:constructor-arg"/>
<xsd:element ref="beans:property"/>
</xsd:choice>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The path into the application intercepted by this interceptor.
Exact path mapping URIs (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**).
If not specified, the interceptor intercepts all paths ("/**").
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="class" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The interceptor class.
Must implement org.springframework.web.servlet.HandlerInterceptor or org.springframework.web.context.request.WebRequestInterceptor.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="direct">
<tool:expected-type type="java.lang.Class"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
<xsd:sequence>
<xsd:element name="path" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="value" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A path into the application intercepted by this interceptor.
Exact path mapping URIås (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element ref="beans:bean">
<xsd:annotation>
<xsd:documentation><![CDATA[
The interceptor's bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:choice>
</xsd:complexType>
</xsd:element>

View File

@ -35,7 +35,6 @@ import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.style.StylerUtils;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
@ -49,7 +48,6 @@ import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.Log4jNestedDiagnosticContextInterceptor;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.ModelAndView;
@ -170,6 +168,11 @@ public class MvcNamespaceTests {
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[3] instanceof WebRequestHandlerInterceptorAdapter);
request.setRequestURI("/foo/logged");
chain = mapping.getHandler(request);
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[3] instanceof WebRequestHandlerInterceptorAdapter);
}
@Test

View File

@ -9,10 +9,10 @@
<mvc:annotation-driven />
<mvc:interceptors>
<mvc:interceptor class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang" />
<mvc:interceptor class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang" />
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
<property name="paramName" value="style" />
</mvc:interceptor>
</bean>
</mvc:interceptors>
</beans>

View File

@ -8,9 +8,16 @@
<mvc:annotation-driven />
<mvc:interceptors>
<mvc:interceptor class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor path="/**" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
<mvc:interceptor path="/logged/**" class="org.springframework.web.context.request.Log4jNestedDiagnosticContextInterceptor" />
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor>
<mvc:path value="/**" />
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:path value="/logged/**" />
<mvc:path value="/foo/logged" />
<bean class="org.springframework.web.context.request.Log4jNestedDiagnosticContextInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>

View File

@ -12,8 +12,8 @@
<mvc:view-controller path="/bar" view-name="baz" />
<mvc:interceptors>
<mvc:interceptor class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
</mvc:interceptors>
</beans>