From dba9c9028006749c19cfc7efaf683e41d9efd2d9 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 19 Mar 2019 14:17:02 -0400 Subject: [PATCH] Ordered WebMvcConfigurer interceptor registrations Closes gh-22434 --- .../annotation/InterceptorRegistration.java | 23 ++++++++++++++- .../annotation/InterceptorRegistry.java | 25 ++++++++++++++--- .../annotation/InterceptorRegistryTests.java | 28 ++++++++++++++++++- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistration.java index ce3071d5200..815d8474734 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.springframework.core.Ordered; import org.springframework.util.Assert; import org.springframework.util.PathMatcher; import org.springframework.util.StringUtils; @@ -43,6 +44,8 @@ public class InterceptorRegistration { private PathMatcher pathMatcher; + private int order = 0; + /** * Create an {@link InterceptorRegistration} instance. @@ -80,6 +83,15 @@ public class InterceptorRegistration { return this; } + /** + * Specify an order position to be used. Default is 0. + * @since 4.23 + */ + public InterceptorRegistration order(int order){ + this.order = order; + return this; + } + /** * Build the underlying interceptor. If URL patterns are provided, the returned * type is {@link MappedInterceptor}; otherwise {@link HandlerInterceptor}. @@ -98,4 +110,13 @@ public class InterceptorRegistration { return mappedInterceptor; } + Ordered toOrdered() { + return new Ordered() { + @Override + public int getOrder() { + return order; + } + }; + } + } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistry.java index 54aea4a4a4e..114c1103fd5 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistry.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,11 @@ package org.springframework.web.servlet.config.annotation; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import org.springframework.core.OrderComparator; import org.springframework.web.context.request.WebRequestInterceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter; @@ -64,11 +67,25 @@ public class InterceptorRegistry { * Return all registered interceptors. */ protected List getInterceptors() { - List interceptors = new ArrayList(this.registrations.size()); + Collections.sort(this.registrations, INTERCEPTOR_ORDER_COMPARATOR); + List result = new ArrayList(this.registrations.size()); for (InterceptorRegistration registration : this.registrations) { - interceptors.add(registration.getInterceptor()); + result.add(registration.getInterceptor()); } - return interceptors ; + return result; } + + private static final Comparator INTERCEPTOR_ORDER_COMPARATOR = + OrderComparator.INSTANCE.withSourceProvider(new OrderComparator.OrderSourceProvider() { + @Override + public Object getOrderSource(final Object object) { + if (object instanceof InterceptorRegistration) { + return ((InterceptorRegistration) object).toOrdered(); + } + return null; + } + }); + + } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/InterceptorRegistryTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/InterceptorRegistryTests.java index 4e49bc9cb4a..bcf3d7c84f2 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/InterceptorRegistryTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/InterceptorRegistryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.springframework.core.Ordered; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.ui.ModelMap; @@ -150,6 +151,30 @@ public class InterceptorRegistryTests { assertEquals(Collections.emptyList(), getInterceptorsForPath("/path1/secret")); } + @Test + public void orderedInterceptors() { + this.registry.addInterceptor(this.interceptor1).order(Ordered.LOWEST_PRECEDENCE); + this.registry.addInterceptor(this.interceptor2).order(Ordered.HIGHEST_PRECEDENCE); + + List interceptors = this.registry.getInterceptors(); + assertEquals(2, interceptors.size()); + + assertSame(this.interceptor2, interceptors.get(0)); + assertSame(this.interceptor1, interceptors.get(1)); + } + + @Test + public void nonOrderedInterceptors() { + this.registry.addInterceptor(this.interceptor1).order(0); + this.registry.addInterceptor(this.interceptor2).order(0); + + List interceptors = this.registry.getInterceptors(); + assertEquals(2, interceptors.size()); + + assertSame(this.interceptor1, interceptors.get(0)); + assertSame(this.interceptor2, interceptors.get(1)); + } + private List getInterceptorsForPath(String lookupPath) { PathMatcher pathMatcher = new AntPathMatcher(); @@ -177,6 +202,7 @@ public class InterceptorRegistryTests { assertTrue(webInterceptor.preHandleInvoked); } + private static class TestWebRequestInterceptor implements WebRequestInterceptor { private boolean preHandleInvoked = false;