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 { class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) { 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) { for (Element interceptor : interceptors) {
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class); RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, interceptor.getAttribute("path")); mappedInterceptorDef.setSource(parserContext.extractSource(interceptor));
RootBeanDefinition interceptorDef = new RootBeanDefinition(interceptor.getAttribute("class")); String[] pathPatterns;
BeanDefinitionHolder holder = new BeanDefinitionHolder(interceptorDef, parserContext.getReaderContext().generateBeanName(interceptorDef)); BeanDefinitionHolder interceptorDef;
holder = parserContext.getDelegate().decorateBeanDefinitionIfRequired(interceptor, holder); if ("interceptor".equals(interceptor.getLocalName())) {
parserContext.getDelegate().parseConstructorArgElements(interceptor, interceptorDef); List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, "path");
parserContext.getDelegate().parsePropertyElements(interceptor, interceptorDef); pathPatterns = new String[paths.size()];
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, holder); 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); parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
} }
return null; return null;

View File

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

View File

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

View File

@ -50,52 +50,54 @@
<xsd:element name="interceptors"> <xsd:element name="interceptors">
<xsd:annotation> <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. 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. Interceptors allow requests 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. 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 interceptors in this set are automatically configured on each registered HandlerMapping.
The URI paths each interceptor applies to are configurable.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:choice maxOccurs="unbounded">
<xsd:element name="interceptor" maxOccurs="unbounded"> <xsd:element ref="beans:bean">
<xsd:annotation> <xsd:annotation>
<xsd:documentation source="java:org.springframework.web.servlet.handler.MappedInterceptor"><![CDATA[ <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:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:complexType> <xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:sequence>
<xsd:element ref="beans:constructor-arg"/> <xsd:element name="path" maxOccurs="unbounded">
<xsd:element ref="beans:property"/> <xsd:complexType>
</xsd:choice> <xsd:attribute name="value" type="xsd:string" use="required">
<xsd:attribute name="path" type="xsd:string"> <xsd:annotation>
<xsd:annotation> <xsd:documentation><![CDATA[
<xsd:documentation><![CDATA[ A path into the application intercepted by this interceptor.
The 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/**).
Exact path mapping URIs (such as "/myPath") are supported as well as Ant-stype path patterns (such as /myPath/**). ]]></xsd:documentation>
If not specified, the interceptor intercepts all paths ("/**"). </xsd:annotation>
]]></xsd:documentation> </xsd:attribute>
</xsd:annotation> </xsd:complexType>
</xsd:attribute> </xsd:element>
<xsd:attribute name="class" type="xsd:string" use="required"> <xsd:element ref="beans:bean">
<xsd:annotation> <xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[ <xsd:documentation><![CDATA[
The interceptor class. The interceptor's bean definition.
Must implement org.springframework.web.servlet.HandlerInterceptor or org.springframework.web.context.request.WebRequestInterceptor. ]]></xsd:documentation>
]]></xsd:documentation> </xsd:annotation>
<xsd:appinfo> </xsd:element>
<tool:annotation kind="direct"> </xsd:sequence>
<tool:expected-type type="java.lang.Class"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:sequence> </xsd:choice>
</xsd:complexType> </xsd:complexType>
</xsd:element> </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.ConversionFailedException;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.style.StylerUtils;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.support.FormattingConversionServiceFactoryBean; import org.springframework.format.support.FormattingConversionServiceFactoryBean;
@ -49,7 +48,6 @@ import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; 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.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@ -170,6 +168,11 @@ public class MvcNamespaceTests {
assertEquals(4, chain.getInterceptors().length); assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[3] instanceof WebRequestHandlerInterceptorAdapter); 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 @Test

View File

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

View File

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

View File

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