17
17
package org .springframework .boot .autoconfigure .web .servlet ;
18
18
19
19
import java .time .Duration ;
20
- import java .util .HashSet ;
20
+ import java .util .LinkedHashMap ;
21
21
import java .util .List ;
22
22
import java .util .ListIterator ;
23
23
import java .util .Map ;
24
- import java .util .Set ;
25
24
26
25
import javax .servlet .Servlet ;
27
26
import javax .servlet .ServletContext ;
54
53
import org .springframework .boot .autoconfigure .web .ResourceProperties .Strategy ;
55
54
import org .springframework .boot .autoconfigure .web .format .DateTimeFormatters ;
56
55
import org .springframework .boot .autoconfigure .web .format .WebConversionService ;
56
+ import org .springframework .boot .autoconfigure .web .servlet .WebMvcAutoConfiguration .AutoConfigurationResourceHandlerRegistry .RegistrationType ;
57
57
import org .springframework .boot .autoconfigure .web .servlet .WebMvcProperties .Format ;
58
58
import org .springframework .boot .context .properties .EnableConfigurationProperties ;
59
59
import org .springframework .boot .convert .ApplicationConversionService ;
76
76
import org .springframework .format .support .FormattingConversionService ;
77
77
import org .springframework .http .MediaType ;
78
78
import org .springframework .http .converter .HttpMessageConverter ;
79
+ import org .springframework .util .Assert ;
79
80
import org .springframework .util .ClassUtils ;
80
81
import org .springframework .util .PathMatcher ;
81
82
import org .springframework .validation .DefaultMessageCodesResolver ;
110
111
import org .springframework .web .servlet .config .annotation .WebMvcConfigurationSupport ;
111
112
import org .springframework .web .servlet .config .annotation .WebMvcConfigurer ;
112
113
import org .springframework .web .servlet .handler .AbstractHandlerExceptionResolver ;
114
+ import org .springframework .web .servlet .handler .AbstractHandlerMapping ;
113
115
import org .springframework .web .servlet .handler .SimpleUrlHandlerMapping ;
114
116
import org .springframework .web .servlet .i18n .AcceptHeaderLocaleResolver ;
115
117
import org .springframework .web .servlet .i18n .FixedLocaleResolver ;
@@ -184,6 +186,10 @@ public OrderedFormContentFilter formContentFilter() {
184
186
@ Order (0 )
185
187
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
186
188
189
+ private static final Log logger = LogFactory .getLog (WebMvcConfigurer .class );
190
+
191
+ private final ResourceProperties resourceProperties ;
192
+
187
193
private final WebMvcProperties mvcProperties ;
188
194
189
195
private final ListableBeanFactory beanFactory ;
@@ -194,13 +200,14 @@ public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
194
200
195
201
private final ObjectProvider <ServletRegistrationBean <?>> servletRegistrations ;
196
202
197
- final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer ;
203
+ private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer ;
198
204
199
- public WebMvcAutoConfigurationAdapter (WebMvcProperties mvcProperties , ListableBeanFactory beanFactory ,
200
- ObjectProvider <HttpMessageConverters > messageConvertersProvider ,
205
+ public WebMvcAutoConfigurationAdapter (ResourceProperties resourceProperties , WebMvcProperties mvcProperties ,
206
+ ListableBeanFactory beanFactory , ObjectProvider <HttpMessageConverters > messageConvertersProvider ,
201
207
ObjectProvider <ResourceHandlerRegistrationCustomizer > resourceHandlerRegistrationCustomizerProvider ,
202
208
ObjectProvider <DispatcherServletPath > dispatcherServletPath ,
203
209
ObjectProvider <ServletRegistrationBean <?>> servletRegistrations ) {
210
+ this .resourceProperties = resourceProperties ;
204
211
this .mvcProperties = mvcProperties ;
205
212
this .beanFactory = beanFactory ;
206
213
this .messageConvertersProvider = messageConvertersProvider ;
@@ -321,6 +328,39 @@ public void addFormatters(FormatterRegistry registry) {
321
328
ApplicationConversionService .addBeans (registry , this .beanFactory );
322
329
}
323
330
331
+ @ Override
332
+ public void addResourceHandlers (ResourceHandlerRegistry registry ) {
333
+ if (!this .resourceProperties .isAddMappings ()) {
334
+ logger .debug ("Default resource handling disabled" );
335
+ return ;
336
+ }
337
+ addResourceHandler (registry , "/webjars/**" , "classpath:/META-INF/resources/webjars/" );
338
+ addResourceHandler (registry , this .mvcProperties .getStaticPathPattern (),
339
+ this .resourceProperties .getStaticLocations ());
340
+ }
341
+
342
+ private void addResourceHandler (ResourceHandlerRegistry registry , String pattern , String ... locations ) {
343
+ if (registry .hasMappingForPattern (pattern )) {
344
+ return ;
345
+ }
346
+ ResourceHandlerRegistration registration = AutoConfigurationResourceHandlerRegistry
347
+ .addResourceHandler (registry , RegistrationType .AUTO_CONFIGURATION , pattern );
348
+ registration .addResourceLocations (locations );
349
+ registration .setCachePeriod (getSeconds (this .resourceProperties .getCache ().getPeriod ()));
350
+ registration .setCacheControl (this .resourceProperties .getCache ().getCachecontrol ().toHttpCacheControl ());
351
+ customizeResourceHandlerRegistration (registration );
352
+ }
353
+
354
+ private Integer getSeconds (Duration cachePeriod ) {
355
+ return (cachePeriod != null ) ? (int ) cachePeriod .getSeconds () : null ;
356
+ }
357
+
358
+ private void customizeResourceHandlerRegistration (ResourceHandlerRegistration registration ) {
359
+ if (this .resourceHandlerRegistrationCustomizer != null ) {
360
+ this .resourceHandlerRegistrationCustomizer .customize (registration );
361
+ }
362
+ }
363
+
324
364
@ Bean
325
365
@ ConditionalOnMissingBean ({ RequestContextListener .class , RequestContextFilter .class })
326
366
@ ConditionalOnMissingFilterBean (RequestContextFilter .class )
@@ -336,31 +376,22 @@ public static RequestContextFilter requestContextFilter() {
336
376
@ Configuration (proxyBeanMethods = false )
337
377
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
338
378
339
- private static final Log logger = LogFactory .getLog (WebMvcConfigurer .class );
340
-
341
379
private final ResourceProperties resourceProperties ;
342
380
343
381
private final WebMvcProperties mvcProperties ;
344
382
345
383
private final WebMvcRegistrations mvcRegistrations ;
346
384
347
- private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer ;
348
-
349
385
private ResourceLoader resourceLoader ;
350
386
351
387
private final ListableBeanFactory beanFactory ;
352
388
353
- private final Set <String > autoConfiguredResourceHandlers = new HashSet <>();
354
-
355
389
public EnableWebMvcConfiguration (ResourceProperties resourceProperties ,
356
390
ObjectProvider <WebMvcProperties > mvcPropertiesProvider ,
357
- ObjectProvider <WebMvcRegistrations > mvcRegistrationsProvider ,
358
- ObjectProvider <ResourceHandlerRegistrationCustomizer > resourceHandlerRegistrationCustomizerProvider ,
359
- ListableBeanFactory beanFactory ) {
391
+ ObjectProvider <WebMvcRegistrations > mvcRegistrationsProvider , ListableBeanFactory beanFactory ) {
360
392
this .resourceProperties = resourceProperties ;
361
393
this .mvcProperties = mvcPropertiesProvider .getIfAvailable ();
362
394
this .mvcRegistrations = mvcRegistrationsProvider .getIfUnique ();
363
- this .resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider .getIfAvailable ();
364
395
this .beanFactory = beanFactory ;
365
396
}
366
397
@@ -402,70 +433,28 @@ public RequestMappingHandlerMapping requestMappingHandlerMapping(
402
433
403
434
@ Bean
404
435
@ Override
405
- public HandlerMapping resourceHandlerMapping (UrlPathHelper urlPathHelper , PathMatcher pathMatcher ,
406
- ContentNegotiationManager contentNegotiationManager , FormattingConversionService conversionService ,
407
- ResourceUrlProvider resourceUrlProvider ) {
408
- HandlerMapping mapping = super .resourceHandlerMapping (urlPathHelper , pathMatcher , contentNegotiationManager ,
409
- conversionService , resourceUrlProvider );
410
- if (mapping instanceof SimpleUrlHandlerMapping ) {
411
- addServletContextResourceHandlerMapping ((SimpleUrlHandlerMapping ) mapping );
436
+ public HandlerMapping resourceHandlerMapping (@ Qualifier ("mvcUrlPathHelper" ) UrlPathHelper urlPathHelper ,
437
+ @ Qualifier ("mvcPathMatcher" ) PathMatcher pathMatcher ,
438
+ @ Qualifier ("mvcContentNegotiationManager" ) ContentNegotiationManager contentNegotiationManager ,
439
+ @ Qualifier ("mvcConversionService" ) FormattingConversionService conversionService ,
440
+ @ Qualifier ("mvcResourceUrlProvider" ) ResourceUrlProvider resourceUrlProvider ) {
441
+ Assert .state (getApplicationContext () != null , "No ApplicationContext set" );
442
+ Assert .state (getServletContext () != null , "No ServletContext set" );
443
+ AutoConfigurationResourceHandlerRegistry registry = new AutoConfigurationResourceHandlerRegistry (
444
+ getApplicationContext (), getServletContext (), contentNegotiationManager , urlPathHelper ,
445
+ this .mvcProperties );
446
+ addResourceHandlers (registry );
447
+ AbstractHandlerMapping mapping = registry .getHandlerMapping ();
448
+ if (mapping == null ) {
449
+ return null ;
412
450
}
451
+ mapping .setPathMatcher (pathMatcher );
452
+ mapping .setUrlPathHelper (urlPathHelper );
453
+ mapping .setInterceptors (getInterceptors (conversionService , resourceUrlProvider ));
454
+ mapping .setCorsConfigurations (getCorsConfigurations ());
413
455
return mapping ;
414
456
}
415
457
416
- private void addServletContextResourceHandlerMapping (SimpleUrlHandlerMapping mapping ) {
417
- Map <String , ?> urlMap = mapping .getUrlMap ();
418
- String pattern = this .mvcProperties .getStaticPathPattern ();
419
- Object handler = urlMap .get (pattern );
420
- if (handler instanceof ResourceHttpRequestHandler
421
- && this .autoConfiguredResourceHandlers .contains (pattern )) {
422
- addServletContextResourceHandlerMapping ((ResourceHttpRequestHandler ) handler );
423
- }
424
- }
425
-
426
- private void addServletContextResourceHandlerMapping (ResourceHttpRequestHandler handler ) {
427
- ServletContext servletContext = getServletContext ();
428
- if (servletContext != null ) {
429
- List <Resource > locations = handler .getLocations ();
430
- locations .add (new ServletContextResource (servletContext , SERVLET_LOCATION ));
431
- }
432
- }
433
-
434
- @ Override
435
- protected void addResourceHandlers (ResourceHandlerRegistry registry ) {
436
- super .addResourceHandlers (registry );
437
- if (!this .resourceProperties .isAddMappings ()) {
438
- logger .debug ("Default resource handling disabled" );
439
- return ;
440
- }
441
- addResourceHandler (registry , "/webjars/**" , "classpath:/META-INF/resources/webjars/" );
442
- addResourceHandler (registry , this .mvcProperties .getStaticPathPattern (),
443
- this .resourceProperties .getStaticLocations ());
444
-
445
- }
446
-
447
- private void addResourceHandler (ResourceHandlerRegistry registry , String pattern , String ... locations ) {
448
- if (registry .hasMappingForPattern (pattern )) {
449
- return ;
450
- }
451
- ResourceHandlerRegistration registration = registry .addResourceHandler (pattern );
452
- registration .addResourceLocations (locations );
453
- registration .setCachePeriod (getSeconds (this .resourceProperties .getCache ().getPeriod ()));
454
- registration .setCacheControl (this .resourceProperties .getCache ().getCachecontrol ().toHttpCacheControl ());
455
- customizeResourceHandlerRegistration (registration );
456
- this .autoConfiguredResourceHandlers .add (pattern );
457
- }
458
-
459
- private Integer getSeconds (Duration cachePeriod ) {
460
- return (cachePeriod != null ) ? (int ) cachePeriod .getSeconds () : null ;
461
- }
462
-
463
- private void customizeResourceHandlerRegistration (ResourceHandlerRegistration registration ) {
464
- if (this .resourceHandlerRegistrationCustomizer != null ) {
465
- this .resourceHandlerRegistrationCustomizer .customize (registration );
466
- }
467
- }
468
-
469
458
@ Bean
470
459
public WelcomePageHandlerMapping welcomePageHandlerMapping (ApplicationContext applicationContext ,
471
460
FormattingConversionService mvcConversionService , ResourceUrlProvider mvcResourceUrlProvider ) {
@@ -677,4 +666,84 @@ public List<MediaType> resolveMediaTypes(NativeWebRequest webRequest)
677
666
678
667
}
679
668
669
+ /**
670
+ * {@link ResourceHandlerRegistry} that tracks auto-configuration and when appropriate
671
+ * adds the {@link ServletContextResource} for {@code /}.
672
+ */
673
+ static class AutoConfigurationResourceHandlerRegistry
674
+ extends org .springframework .web .servlet .config .annotation .ResourceHandlerRegistry {
675
+
676
+ private final ServletContext servletContext ;
677
+
678
+ private final WebMvcProperties mvcProperties ;
679
+
680
+ private final Map <String , RegistrationType > registrations = new LinkedHashMap <>();
681
+
682
+ AutoConfigurationResourceHandlerRegistry (ApplicationContext applicationContext , ServletContext servletContext ,
683
+ ContentNegotiationManager contentNegotiationManager , UrlPathHelper pathHelper ,
684
+ WebMvcProperties mvcProperties ) {
685
+ super (applicationContext , servletContext , contentNegotiationManager , pathHelper );
686
+ this .servletContext = servletContext ;
687
+ this .mvcProperties = mvcProperties ;
688
+ }
689
+
690
+ @ Override
691
+ public ResourceHandlerRegistration addResourceHandler (String ... pathPatterns ) {
692
+ return addResourceHandler (RegistrationType .STANDARD , pathPatterns );
693
+ }
694
+
695
+ ResourceHandlerRegistration addResourceHandler (RegistrationType type , String ... pathPatterns ) {
696
+ for (String pathPattern : pathPatterns ) {
697
+ this .registrations .put (pathPattern , type );
698
+ }
699
+ return super .addResourceHandler (pathPatterns );
700
+ }
701
+
702
+ @ Override
703
+ protected AbstractHandlerMapping getHandlerMapping () {
704
+ SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping ) super .getHandlerMapping ();
705
+ reconfigure (mapping );
706
+ return mapping ;
707
+ }
708
+
709
+ private void reconfigure (SimpleUrlHandlerMapping mapping ) {
710
+ String staticPathPattern = this .mvcProperties .getStaticPathPattern ();
711
+ if (this .registrations .get (staticPathPattern ) == RegistrationType .AUTO_CONFIGURATION ) {
712
+ addServletContextResourceHandlerMapping (mapping , staticPathPattern );
713
+ }
714
+ }
715
+
716
+ private void addServletContextResourceHandlerMapping (SimpleUrlHandlerMapping mapping ,
717
+ String staticPathPattern ) {
718
+ Object handler = mapping .getUrlMap ().get (staticPathPattern );
719
+ if (handler instanceof ResourceHttpRequestHandler ) {
720
+ addServletContextResourceHandlerMapping ((ResourceHttpRequestHandler ) handler );
721
+ }
722
+ }
723
+
724
+ private void addServletContextResourceHandlerMapping (ResourceHttpRequestHandler handler ) {
725
+ if (this .servletContext != null ) {
726
+ List <Resource > locations = handler .getLocations ();
727
+ locations .add (new ServletContextResource (this .servletContext , SERVLET_LOCATION ));
728
+ }
729
+ }
730
+
731
+ static ResourceHandlerRegistration addResourceHandler (ResourceHandlerRegistry registry , RegistrationType type ,
732
+ String ... pathPatterns ) {
733
+ if (registry instanceof AutoConfigurationResourceHandlerRegistry ) {
734
+ return ((AutoConfigurationResourceHandlerRegistry ) registry ).addResourceHandler (type , pathPatterns );
735
+ }
736
+ return registry .addResourceHandler (pathPatterns );
737
+ }
738
+
739
+ enum RegistrationType {
740
+
741
+ STANDARD ,
742
+
743
+ AUTO_CONFIGURATION
744
+
745
+ }
746
+
747
+ }
748
+
680
749
}
0 commit comments