2016-09-02 1 views
0

Большинство веб-серверов могут быть настроены для доставки специального файла, если запрашивается только справочник. Обычно файл «index.html» или аналогичный файл поставляется в этом случае.Spring <mvc: resources>: Как сделать серверным сервером индексный файл/приветственный файл, если запрашивается каталог?

Я использую <mvc:resources> для доставки статических ресурсов в приложении весны, и я хочу сделать то же самое: если запрашивается каталог, предварительно заданный файл внутри этого каталога должен быть доставлен клиенту. Моя конфигурация до сих пор выглядит так:

public class CoreWebMvcConfig extends WebMvcConfigurerAdapter { 
    @Override 
    public void addResourceHandlers(final ResourceHandlerRegistry registry) { 
     registry 
      .addResourceHandler("/static/**/*") 
      .addResourceLocations("/www/"); 
    } 
} 

ответ

0

К моему удивлению, я не нашел ничего связанного с весной, которое решает эту проблему. В конце концов, это кажется довольно нормальным.

Возможное решение

Один из способов я нашел, чтобы написать собственный путь распознаватель так:

public class CoreWebMvcConfig extends WebMvcConfigurerAdapter { 
    @Override 
    public void addResourceHandlers(final ResourceHandlerRegistry registry) { 
     registry 
      .addResourceHandler("/static/**/*") 
      .addResourceLocations("/www/") 
      .resourceChain(true).addResolver(new WelcomeFilePathResolver()); 
    } 

    /** 
    * An extension to Spring's {@link PathResourceResolver} which checks if the requested resource is a directory. 
    * If it is, it attempts to deliver a file "index.html" within this directory rather than failing. 
    */ 
    private static class WelcomeFilePathResolver extends PathResourceResolver { 
     @Override 
     protected Resource getResource(final String resourcePath, final Resource location) throws IOException { 
      Resource resource = location.createRelative(resourcePath); 
      if (resource.getFile().isDirectory()) { 
       return super.getResource(resourcePath + "/index.html", location); 
      } 
      return super.getResource(resourcePath, location); 
     } 
    } 
} 

Заметим, однако, что это не работает для корневого каталога, но только для подкаталогов. Для корневой директории добавьте следующую строку в расширение WebMvcConfigurerAdapter:

@Override 
public void addViewControllers(ViewControllerRegistry registry) { 
    registry.addViewController("/").setViewName("forward:/index.html"); 
} 

Фоновая объяснение

Обычно, если вы не зарегистрировать resourceChain, то весна будет решать ресурсы, используя PathResourceResolver. Оригинальный метод PathResourceResolver.getResource начинается так:

protected Resource getResource(String resourcePath, Resource location) throws IOException { 
    Resource resource = location.createRelative(resourcePath); 
    if (resource.exists() && resource.isReadable()) { 

Там каталог найден, resource.exists() возвращает истину, но resource.isReadable() возвращает ложь, потому что сам каталог не доступен для чтения и, таким образом, это будет в конечном итоге в 404.

Пользовательский ResourceResolver перехватывает вызовы этого метода и проверяет, является ли запрошенный ресурс каталогом. Если это не просто делегирует оригинал getResource-метод. Однако, если это так, он изменяет путь и ищет файл index.html в этом каталоге.

Причина, по которой необходима дополнительная настройка для корня, заключается в том, что the ResourceHttpRequestHandler checks for non empty paths (не уверен, почему он диктует это и не оставляет это до ResourceResolve ...).

Ограничения

Поскольку я называю resource.getFile() я полагаю, что существует целый ряд случаев, когда это не будет работать. Я тестирую файлы, доставленные из военного файла в Tomcat. Однако, если ресурсы читаются непосредственно из файла jar, это, вероятно, не сработает. В качестве альтернативы может быть использована адаптация, где не .getFile().isDirectory(), а скорее resource.isReadable().

Смежные вопросы