mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 20:19:06 +00:00
Merge pull request #46605 from nosan
* gh-46605: Add support for the @FilterRegistration annotation with @WebMvcTest Closes gh-46605
This commit is contained in:
+39
-3
@@ -20,10 +20,13 @@ import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.annotation.WebInitParam;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -31,11 +34,13 @@ import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.web.servlet.AbstractFilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.FilterRegistration;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.RegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializerBeans;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultHandler;
|
||||
import org.springframework.test.web.servlet.result.PrintingResultHandler;
|
||||
@@ -330,18 +335,49 @@ public class SpringBootMockMvcBuilderCustomizer implements MockMvcBuilderCustomi
|
||||
|
||||
@Override
|
||||
protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
|
||||
addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
|
||||
addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter(beanFactory));
|
||||
}
|
||||
|
||||
private static final class FilterRegistrationBeanAdapter implements RegistrationBeanAdapter<Filter> {
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
private FilterRegistrationBeanAdapter(ListableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistrationBean createRegistrationBean(String name, Filter source, int totalNumberOfSourceBeans) {
|
||||
public RegistrationBean createRegistrationBean(String beanName, Filter source,
|
||||
int totalNumberOfSourceBeans) {
|
||||
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>(source);
|
||||
bean.setName(name);
|
||||
bean.setName(beanName);
|
||||
FilterRegistration registrationAnnotation = this.beanFactory.findAnnotationOnBean(beanName,
|
||||
FilterRegistration.class);
|
||||
if (registrationAnnotation != null) {
|
||||
// Supports @Order annotation on @Bean methods
|
||||
Order orderAnnotation = this.beanFactory.findAnnotationOnBean(beanName, Order.class);
|
||||
Assert.state(orderAnnotation != null, "'orderAnnotation' must not be null");
|
||||
configureFromAnnotation(bean, registrationAnnotation, orderAnnotation);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private void configureFromAnnotation(FilterRegistrationBean<Filter> bean,
|
||||
FilterRegistration registrationAnnotation, Order orderAnnotation) {
|
||||
bean.setEnabled(registrationAnnotation.enabled());
|
||||
bean.setOrder(orderAnnotation.value());
|
||||
if (StringUtils.hasText(registrationAnnotation.name())) {
|
||||
bean.setName(registrationAnnotation.name());
|
||||
}
|
||||
if (registrationAnnotation.dispatcherTypes().length > 0) {
|
||||
bean.setDispatcherTypes(EnumSet.copyOf(Arrays.asList(registrationAnnotation.dispatcherTypes())));
|
||||
}
|
||||
for (WebInitParam param : registrationAnnotation.initParameters()) {
|
||||
bean.addInitParameter(param.name(), param.value());
|
||||
}
|
||||
bean.setUrlPatterns(Arrays.asList(registrationAnnotation.urlPatterns()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2012-present 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.autoconfigure.web.servlet.mockmvc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.annotation.WebInitParam;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.boot.web.servlet.FilterRegistration;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.test.web.servlet.assertj.MockMvcTester;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link FilterRegistration} and {@link FilterRegistrationBean} with
|
||||
* {@link WebMvcTest @WebMvcTest}.
|
||||
*
|
||||
* @author Dmytro Nosan
|
||||
*/
|
||||
@WebMvcTest
|
||||
class WebMvcTestServletFilterRegistrationIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MockMvcTester mvc;
|
||||
|
||||
@Test
|
||||
void annotation() {
|
||||
assertThat(this.mvc.get().uri("/annotation")).headers()
|
||||
.hasValue("name", "annotation")
|
||||
.hasValue("param1", "value1")
|
||||
.hasValue("param2", "value2")
|
||||
.doesNotContainHeader("param3")
|
||||
.doesNotContainHeader("param4");
|
||||
}
|
||||
|
||||
@Test
|
||||
void registration() {
|
||||
assertThat(this.mvc.get().uri("/registration")).headers()
|
||||
.hasValue("name", "registration")
|
||||
.hasValue("param3", "value3")
|
||||
.hasValue("param4", "value4")
|
||||
.doesNotContainHeader("param1")
|
||||
.doesNotContainHeader("param2");
|
||||
}
|
||||
|
||||
@TestConfiguration(proxyBeanMethods = false)
|
||||
static class FilterRegistrationConfiguration {
|
||||
|
||||
@Bean
|
||||
@FilterRegistration(name = "annotation", urlPatterns = "/annotation",
|
||||
initParameters = { @WebInitParam(name = "param1", value = "value1"),
|
||||
@WebInitParam(name = "param2", value = "value2") })
|
||||
@Order(SecurityProperties.DEFAULT_FILTER_ORDER - 1)
|
||||
TestFilter testFilterAnnotationBean() {
|
||||
return new TestFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FilterRegistrationBean<TestFilter> testFilterRegistrationBean() {
|
||||
FilterRegistrationBean<TestFilter> registration = new FilterRegistrationBean<>(new TestFilter());
|
||||
registration.setName("registration");
|
||||
registration.addUrlPatterns("/registration");
|
||||
registration.setInitParameters(Map.of("param3", "value3", "param4", "value4"));
|
||||
registration.setOrder(SecurityProperties.DEFAULT_FILTER_ORDER - 1);
|
||||
return registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class TestFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
response.addHeader("name", getFilterName());
|
||||
FilterConfig config = getFilterConfig();
|
||||
if (config != null) {
|
||||
Collections.list(config.getInitParameterNames())
|
||||
.forEach((name) -> response.addHeader(name, config.getInitParameter(name)));
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+7
-1
@@ -330,7 +330,13 @@ public class ServletContextInitializerBeans extends AbstractCollection<ServletCo
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link RegistrationBeanAdapter} for {@link Filter} beans.
|
||||
* {@link RegistrationBeanAdapter} implementation for {@link Filter} beans.
|
||||
* <p>
|
||||
* <b>NOTE:</b> A similar implementation is used in
|
||||
* {@code SpringBootMockMvcBuilderCustomizer} for registering
|
||||
* {@code @FilterRegistration} beans with {@code @MockMvc}. If you modify this class,
|
||||
* please also update {@code SpringBootMockMvcBuilderCustomizer} if needed.
|
||||
* </p>
|
||||
*/
|
||||
private static class FilterRegistrationBeanAdapter implements RegistrationBeanAdapter<Filter> {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user