16
16
17
17
package org .springframework .boot .autoconfigure .web .servlet ;
18
18
19
+ import java .util .ArrayList ;
20
+ import java .util .Arrays ;
19
21
import java .util .Collection ;
20
22
import java .util .Collections ;
21
23
import java .util .Date ;
22
24
import java .util .List ;
23
25
import java .util .ListIterator ;
24
26
import java .util .Map ;
25
27
import java .util .Map .Entry ;
28
+ import java .util .Optional ;
26
29
27
30
import javax .servlet .Servlet ;
28
31
import javax .servlet .http .HttpServletRequest ;
54
57
import org .springframework .boot .web .servlet .filter .OrderedHiddenHttpMethodFilter ;
55
58
import org .springframework .boot .web .servlet .filter .OrderedHttpPutFormContentFilter ;
56
59
import org .springframework .boot .web .servlet .filter .OrderedRequestContextFilter ;
60
+ import org .springframework .context .ResourceLoaderAware ;
57
61
import org .springframework .context .annotation .Bean ;
58
62
import org .springframework .context .annotation .Configuration ;
59
63
import org .springframework .context .annotation .Import ;
62
66
import org .springframework .core .Ordered ;
63
67
import org .springframework .core .convert .converter .Converter ;
64
68
import org .springframework .core .convert .converter .GenericConverter ;
69
+ import org .springframework .core .io .ClassPathResource ;
65
70
import org .springframework .core .io .Resource ;
71
+ import org .springframework .core .io .ResourceLoader ;
66
72
import org .springframework .format .Formatter ;
67
73
import org .springframework .format .FormatterRegistry ;
68
74
import org .springframework .format .datetime .DateFormatter ;
@@ -140,6 +146,8 @@ public class WebMvcAutoConfiguration {
140
146
141
147
public static final String DEFAULT_SUFFIX = "" ;
142
148
149
+ private static final String [] SERVLET_LOCATIONS = { "/" };
150
+
143
151
@ Bean
144
152
@ ConditionalOnMissingBean (HiddenHttpMethodFilter .class )
145
153
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter () {
@@ -158,7 +166,7 @@ public OrderedHttpPutFormContentFilter httpPutFormContentFilter() {
158
166
@ Configuration
159
167
@ Import (EnableWebMvcConfiguration .class )
160
168
@ EnableConfigurationProperties ({ WebMvcProperties .class , ResourceProperties .class })
161
- public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
169
+ public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer , ResourceLoaderAware {
162
170
163
171
private static final Log logger = LogFactory .getLog (WebMvcConfigurer .class );
164
172
@@ -172,6 +180,8 @@ public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
172
180
173
181
final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer ;
174
182
183
+ private ResourceLoader resourceLoader ;
184
+
175
185
public WebMvcAutoConfigurationAdapter (ResourceProperties resourceProperties ,
176
186
WebMvcProperties mvcProperties , ListableBeanFactory beanFactory ,
177
187
@ Lazy HttpMessageConverters messageConverters ,
@@ -184,6 +194,11 @@ public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties,
184
194
.getIfAvailable ();
185
195
}
186
196
197
+ @ Override
198
+ public void setResourceLoader (ResourceLoader resourceLoader ) {
199
+ this .resourceLoader = resourceLoader ;
200
+ }
201
+
187
202
@ Override
188
203
public void configureMessageConverters (List <HttpMessageConverter <?>> converters ) {
189
204
converters .addAll (this .messageConverters .getConverters ());
@@ -302,18 +317,43 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
302
317
customizeResourceHandlerRegistration (
303
318
registry .addResourceHandler (staticPathPattern )
304
319
.addResourceLocations (
305
- this .resourceProperties .getStaticLocations ())
320
+ getResourceLocations ( this .resourceProperties .getStaticLocations () ))
306
321
.setCachePeriod (cachePeriod ));
307
322
}
308
323
}
309
324
310
325
@ Bean
311
- public WelcomePageHandlerMapping welcomePageHandlerMapping (
312
- ResourceProperties resourceProperties ) {
313
- return new WelcomePageHandlerMapping (resourceProperties .getWelcomePage (),
326
+ public WelcomePageHandlerMapping welcomePageHandlerMapping () {
327
+ return new WelcomePageHandlerMapping (getWelcomePage (),
314
328
this .mvcProperties .getStaticPathPattern ());
315
329
}
316
330
331
+ static String [] getResourceLocations (String [] staticLocations ) {
332
+ String [] locations = new String [staticLocations .length + SERVLET_LOCATIONS .length ];
333
+ System .arraycopy (staticLocations , 0 , locations , 0 , staticLocations .length );
334
+ System .arraycopy (SERVLET_LOCATIONS , 0 , locations ,
335
+ staticLocations .length , SERVLET_LOCATIONS .length );
336
+ return locations ;
337
+ }
338
+
339
+ private Optional <Resource > getWelcomePage () {
340
+ return Arrays .stream (getResourceLocations (this .resourceProperties .getStaticLocations ()))
341
+ .map (location -> this .resourceLoader .getResource (location + "index.html" ))
342
+ .filter (resource -> {
343
+ try {
344
+ if (resource .exists ()) {
345
+ resource .getURL ();
346
+ return true ;
347
+ }
348
+ }
349
+ catch (Exception ex ) {
350
+ // Ignore
351
+ }
352
+ return false ;
353
+ })
354
+ .findFirst ();
355
+ }
356
+
317
357
private void customizeResourceHandlerRegistration (
318
358
ResourceHandlerRegistration registration ) {
319
359
if (this .resourceHandlerRegistrationCustomizer != null ) {
@@ -331,14 +371,21 @@ public static RequestContextFilter requestContextFilter() {
331
371
332
372
@ Configuration
333
373
@ ConditionalOnProperty (value = "spring.mvc.favicon.enabled" , matchIfMissing = true )
334
- public static class FaviconConfiguration {
374
+ public static class FaviconConfiguration implements ResourceLoaderAware {
335
375
336
376
private final ResourceProperties resourceProperties ;
337
377
378
+ private ResourceLoader resourceLoader ;
379
+
338
380
public FaviconConfiguration (ResourceProperties resourceProperties ) {
339
381
this .resourceProperties = resourceProperties ;
340
382
}
341
383
384
+ @ Override
385
+ public void setResourceLoader (ResourceLoader resourceLoader ) {
386
+ this .resourceLoader = resourceLoader ;
387
+ }
388
+
342
389
@ Bean
343
390
public SimpleUrlHandlerMapping faviconHandlerMapping () {
344
391
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping ();
@@ -351,11 +398,19 @@ public SimpleUrlHandlerMapping faviconHandlerMapping() {
351
398
@ Bean
352
399
public ResourceHttpRequestHandler faviconRequestHandler () {
353
400
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler ();
354
- requestHandler
355
- .setLocations (this .resourceProperties .resolveFaviconLocations ());
401
+ requestHandler .setLocations (resolveFaviconLocations ());
356
402
return requestHandler ;
357
403
}
358
404
405
+ private List <Resource > resolveFaviconLocations () {
406
+ String [] resourceLocations = getResourceLocations (this .resourceProperties .getStaticLocations ());
407
+ List <Resource > locations = new ArrayList <>(resourceLocations .length + 1 );
408
+ Arrays .stream (resourceLocations )
409
+ .forEach (location -> locations .add (this .resourceLoader .getResource (location )));
410
+ locations .add (new ClassPathResource ("/" ));
411
+ return Collections .unmodifiableList (locations );
412
+ }
413
+
359
414
}
360
415
361
416
}
@@ -546,9 +601,9 @@ static final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {
546
601
private static final Log logger = LogFactory
547
602
.getLog (WelcomePageHandlerMapping .class );
548
603
549
- private WelcomePageHandlerMapping (Resource welcomePage ,
604
+ private WelcomePageHandlerMapping (Optional < Resource > welcomePage ,
550
605
String staticPathPattern ) {
551
- if (welcomePage != null && "/**" .equals (staticPathPattern )) {
606
+ if (welcomePage . isPresent () && "/**" .equals (staticPathPattern )) {
552
607
logger .info ("Adding welcome page: " + welcomePage );
553
608
ParameterizableViewController controller = new ParameterizableViewController ();
554
609
controller .setViewName ("forward:index.html" );
0 commit comments