Use WebMvcConfigurer to add resource handlers
Move resource handler auto-configuration logic back to the `WebMvcConfigurer` so that they also get applied to child contexts. Closes gh-25743
This commit is contained in:
parent
ee76d6038c
commit
004363ceaf
|
|
@ -17,11 +17,10 @@
|
|||
package org.springframework.boot.autoconfigure.web.servlet;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
|
|
@ -54,6 +53,7 @@ import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
|||
import org.springframework.boot.autoconfigure.web.ResourceProperties.Strategy;
|
||||
import org.springframework.boot.autoconfigure.web.format.DateTimeFormatters;
|
||||
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.AutoConfigurationResourceHandlerRegistry.RegistrationType;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.Format;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.convert.ApplicationConversionService;
|
||||
|
|
@ -76,6 +76,7 @@ import org.springframework.format.FormatterRegistry;
|
|||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.validation.DefaultMessageCodesResolver;
|
||||
|
|
@ -110,6 +111,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
|
|||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
|
||||
|
|
@ -184,6 +186,10 @@ public class WebMvcAutoConfiguration {
|
|||
@Order(0)
|
||||
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
|
||||
|
||||
private final ResourceProperties resourceProperties;
|
||||
|
||||
private final WebMvcProperties mvcProperties;
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
|
@ -194,13 +200,14 @@ public class WebMvcAutoConfiguration {
|
|||
|
||||
private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
|
||||
|
||||
final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
|
||||
private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
|
||||
|
||||
public WebMvcAutoConfigurationAdapter(WebMvcProperties mvcProperties, ListableBeanFactory beanFactory,
|
||||
ObjectProvider<HttpMessageConverters> messageConvertersProvider,
|
||||
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
|
||||
ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
|
||||
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
|
||||
ObjectProvider<DispatcherServletPath> dispatcherServletPath,
|
||||
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
|
||||
this.resourceProperties = resourceProperties;
|
||||
this.mvcProperties = mvcProperties;
|
||||
this.beanFactory = beanFactory;
|
||||
this.messageConvertersProvider = messageConvertersProvider;
|
||||
|
|
@ -321,6 +328,39 @@ public class WebMvcAutoConfiguration {
|
|||
ApplicationConversionService.addBeans(registry, this.beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
if (!this.resourceProperties.isAddMappings()) {
|
||||
logger.debug("Default resource handling disabled");
|
||||
return;
|
||||
}
|
||||
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
|
||||
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(),
|
||||
this.resourceProperties.getStaticLocations());
|
||||
}
|
||||
|
||||
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
|
||||
if (registry.hasMappingForPattern(pattern)) {
|
||||
return;
|
||||
}
|
||||
ResourceHandlerRegistration registration = AutoConfigurationResourceHandlerRegistry
|
||||
.addResourceHandler(registry, RegistrationType.AUTO_CONFIGURATION, pattern);
|
||||
registration.addResourceLocations(locations);
|
||||
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
|
||||
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
|
||||
customizeResourceHandlerRegistration(registration);
|
||||
}
|
||||
|
||||
private Integer getSeconds(Duration cachePeriod) {
|
||||
return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null;
|
||||
}
|
||||
|
||||
private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
|
||||
if (this.resourceHandlerRegistrationCustomizer != null) {
|
||||
this.resourceHandlerRegistrationCustomizer.customize(registration);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean({ RequestContextListener.class, RequestContextFilter.class })
|
||||
@ConditionalOnMissingFilterBean(RequestContextFilter.class)
|
||||
|
|
@ -336,31 +376,22 @@ public class WebMvcAutoConfiguration {
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
|
||||
|
||||
private final ResourceProperties resourceProperties;
|
||||
|
||||
private final WebMvcProperties mvcProperties;
|
||||
|
||||
private final WebMvcRegistrations mvcRegistrations;
|
||||
|
||||
private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
private final Set<String> autoConfiguredResourceHandlers = new HashSet<>();
|
||||
|
||||
public EnableWebMvcConfiguration(ResourceProperties resourceProperties,
|
||||
ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
|
||||
ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,
|
||||
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
|
||||
ListableBeanFactory beanFactory) {
|
||||
ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider, ListableBeanFactory beanFactory) {
|
||||
this.resourceProperties = resourceProperties;
|
||||
this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
|
||||
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
|
||||
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
|
@ -402,70 +433,28 @@ public class WebMvcAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@Override
|
||||
public HandlerMapping resourceHandlerMapping(UrlPathHelper urlPathHelper, PathMatcher pathMatcher,
|
||||
ContentNegotiationManager contentNegotiationManager, FormattingConversionService conversionService,
|
||||
ResourceUrlProvider resourceUrlProvider) {
|
||||
HandlerMapping mapping = super.resourceHandlerMapping(urlPathHelper, pathMatcher, contentNegotiationManager,
|
||||
conversionService, resourceUrlProvider);
|
||||
if (mapping instanceof SimpleUrlHandlerMapping) {
|
||||
addServletContextResourceHandlerMapping((SimpleUrlHandlerMapping) mapping);
|
||||
public HandlerMapping resourceHandlerMapping(@Qualifier("mvcUrlPathHelper") UrlPathHelper urlPathHelper,
|
||||
@Qualifier("mvcPathMatcher") PathMatcher pathMatcher,
|
||||
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
|
||||
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
|
||||
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
|
||||
Assert.state(getApplicationContext() != null, "No ApplicationContext set");
|
||||
Assert.state(getServletContext() != null, "No ServletContext set");
|
||||
AutoConfigurationResourceHandlerRegistry registry = new AutoConfigurationResourceHandlerRegistry(
|
||||
getApplicationContext(), getServletContext(), contentNegotiationManager, urlPathHelper,
|
||||
this.mvcProperties);
|
||||
addResourceHandlers(registry);
|
||||
AbstractHandlerMapping mapping = registry.getHandlerMapping();
|
||||
if (mapping == null) {
|
||||
return null;
|
||||
}
|
||||
mapping.setPathMatcher(pathMatcher);
|
||||
mapping.setUrlPathHelper(urlPathHelper);
|
||||
mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
|
||||
mapping.setCorsConfigurations(getCorsConfigurations());
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private void addServletContextResourceHandlerMapping(SimpleUrlHandlerMapping mapping) {
|
||||
Map<String, ?> urlMap = mapping.getUrlMap();
|
||||
String pattern = this.mvcProperties.getStaticPathPattern();
|
||||
Object handler = urlMap.get(pattern);
|
||||
if (handler instanceof ResourceHttpRequestHandler
|
||||
&& this.autoConfiguredResourceHandlers.contains(pattern)) {
|
||||
addServletContextResourceHandlerMapping((ResourceHttpRequestHandler) handler);
|
||||
}
|
||||
}
|
||||
|
||||
private void addServletContextResourceHandlerMapping(ResourceHttpRequestHandler handler) {
|
||||
ServletContext servletContext = getServletContext();
|
||||
if (servletContext != null) {
|
||||
List<Resource> locations = handler.getLocations();
|
||||
locations.add(new ServletContextResource(servletContext, SERVLET_LOCATION));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
super.addResourceHandlers(registry);
|
||||
if (!this.resourceProperties.isAddMappings()) {
|
||||
logger.debug("Default resource handling disabled");
|
||||
return;
|
||||
}
|
||||
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
|
||||
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(),
|
||||
this.resourceProperties.getStaticLocations());
|
||||
|
||||
}
|
||||
|
||||
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
|
||||
if (registry.hasMappingForPattern(pattern)) {
|
||||
return;
|
||||
}
|
||||
ResourceHandlerRegistration registration = registry.addResourceHandler(pattern);
|
||||
registration.addResourceLocations(locations);
|
||||
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
|
||||
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
|
||||
customizeResourceHandlerRegistration(registration);
|
||||
this.autoConfiguredResourceHandlers.add(pattern);
|
||||
}
|
||||
|
||||
private Integer getSeconds(Duration cachePeriod) {
|
||||
return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null;
|
||||
}
|
||||
|
||||
private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
|
||||
if (this.resourceHandlerRegistrationCustomizer != null) {
|
||||
this.resourceHandlerRegistrationCustomizer.customize(registration);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
|
||||
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
|
||||
|
|
@ -677,4 +666,84 @@ public class WebMvcAutoConfiguration {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ResourceHandlerRegistry} that tracks auto-configuration and when appropriate
|
||||
* adds the {@link ServletContextResource} for {@code /}.
|
||||
*/
|
||||
static class AutoConfigurationResourceHandlerRegistry
|
||||
extends org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final WebMvcProperties mvcProperties;
|
||||
|
||||
private final Map<String, RegistrationType> registrations = new LinkedHashMap<>();
|
||||
|
||||
AutoConfigurationResourceHandlerRegistry(ApplicationContext applicationContext, ServletContext servletContext,
|
||||
ContentNegotiationManager contentNegotiationManager, UrlPathHelper pathHelper,
|
||||
WebMvcProperties mvcProperties) {
|
||||
super(applicationContext, servletContext, contentNegotiationManager, pathHelper);
|
||||
this.servletContext = servletContext;
|
||||
this.mvcProperties = mvcProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceHandlerRegistration addResourceHandler(String... pathPatterns) {
|
||||
return addResourceHandler(RegistrationType.STANDARD, pathPatterns);
|
||||
}
|
||||
|
||||
ResourceHandlerRegistration addResourceHandler(RegistrationType type, String... pathPatterns) {
|
||||
for (String pathPattern : pathPatterns) {
|
||||
this.registrations.put(pathPattern, type);
|
||||
}
|
||||
return super.addResourceHandler(pathPatterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractHandlerMapping getHandlerMapping() {
|
||||
SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) super.getHandlerMapping();
|
||||
reconfigure(mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private void reconfigure(SimpleUrlHandlerMapping mapping) {
|
||||
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
|
||||
if (this.registrations.get(staticPathPattern) == RegistrationType.AUTO_CONFIGURATION) {
|
||||
addServletContextResourceHandlerMapping(mapping, staticPathPattern);
|
||||
}
|
||||
}
|
||||
|
||||
private void addServletContextResourceHandlerMapping(SimpleUrlHandlerMapping mapping,
|
||||
String staticPathPattern) {
|
||||
Object handler = mapping.getUrlMap().get(staticPathPattern);
|
||||
if (handler instanceof ResourceHttpRequestHandler) {
|
||||
addServletContextResourceHandlerMapping((ResourceHttpRequestHandler) handler);
|
||||
}
|
||||
}
|
||||
|
||||
private void addServletContextResourceHandlerMapping(ResourceHttpRequestHandler handler) {
|
||||
if (this.servletContext != null) {
|
||||
List<Resource> locations = handler.getLocations();
|
||||
locations.add(new ServletContextResource(this.servletContext, SERVLET_LOCATION));
|
||||
}
|
||||
}
|
||||
|
||||
static ResourceHandlerRegistration addResourceHandler(ResourceHandlerRegistry registry, RegistrationType type,
|
||||
String... pathPatterns) {
|
||||
if (registry instanceof AutoConfigurationResourceHandlerRegistry) {
|
||||
return ((AutoConfigurationResourceHandlerRegistry) registry).addResourceHandler(type, pathPatterns);
|
||||
}
|
||||
return registry.addResourceHandler(pathPatterns);
|
||||
}
|
||||
|
||||
enum RegistrationType {
|
||||
|
||||
STANDARD,
|
||||
|
||||
AUTO_CONFIGURATION
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import java.util.concurrent.Executor;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.ValidatorFactory;
|
||||
|
|
@ -50,9 +51,11 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio
|
|||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||
import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter;
|
||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
|
@ -81,6 +84,7 @@ import org.springframework.web.accept.ParameterContentNegotiationStrategy;
|
|||
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.FormContentFilter;
|
||||
import org.springframework.web.filter.HiddenHttpMethodFilter;
|
||||
|
|
@ -95,6 +99,7 @@ import org.springframework.web.servlet.ViewResolver;
|
|||
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
|
||||
|
|
@ -898,6 +903,25 @@ class WebMvcAutoConfigurationTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test // gh-25743
|
||||
void addResourceHandlersAppliesToChildAndParentContext() {
|
||||
try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext()) {
|
||||
context.register(WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
ResourceHandlersWithChildAndParentContextConfiguration.class);
|
||||
context.refresh();
|
||||
SimpleUrlHandlerMapping resourceHandlerMapping = context.getBean("resourceHandlerMapping",
|
||||
SimpleUrlHandlerMapping.class);
|
||||
DispatcherServlet extraDispatcherServlet = context.getBean("extraDispatcherServlet",
|
||||
DispatcherServlet.class);
|
||||
SimpleUrlHandlerMapping extraResourceHandlerMapping = extraDispatcherServlet.getWebApplicationContext()
|
||||
.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class);
|
||||
assertThat(resourceHandlerMapping).isNotSameAs(extraResourceHandlerMapping);
|
||||
assertThat(resourceHandlerMapping.getUrlMap()).containsKey("/**");
|
||||
assertThat(extraResourceHandlerMapping.getUrlMap()).containsKey("/**");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertCacheControl(AssertableWebApplicationContext context) {
|
||||
Map<String, Object> handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class));
|
||||
assertThat(handlerMap).hasSize(2);
|
||||
|
|
@ -1330,4 +1354,49 @@ class WebMvcAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ResourceHandlersWithChildAndParentContextConfiguration {
|
||||
|
||||
@Bean
|
||||
TomcatServletWebServerFactory webServerFactory() {
|
||||
return new TomcatServletWebServerFactory(0);
|
||||
}
|
||||
|
||||
@Bean
|
||||
ServletRegistrationBean<?> additionalDispatcherServlet(DispatcherServlet extraDispatcherServlet) {
|
||||
ServletRegistrationBean<?> registration = new ServletRegistrationBean<>(extraDispatcherServlet, "/extra/*");
|
||||
registration.setName("additionalDispatcherServlet");
|
||||
registration.setLoadOnStartup(1);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
private DispatcherServlet extraDispatcherServlet() throws ServletException {
|
||||
DispatcherServlet dispatcherServlet = new DispatcherServlet();
|
||||
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
|
||||
applicationContext.register(ResourceHandlersWithChildAndParentContextChildConfiguration.class);
|
||||
dispatcherServlet.setApplicationContext(applicationContext);
|
||||
return dispatcherServlet;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableWebMvc
|
||||
static class ResourceHandlersWithChildAndParentContextChildConfiguration {
|
||||
|
||||
@Bean
|
||||
WebMvcConfigurer myConfigurer() {
|
||||
return new WebMvcConfigurer() {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/testtesttest");
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue