Программное чтение статических ресурсов из моего веб-приложения Java

В настоящее время у меня есть куча изображений в моем файле .war, подобных этому.

WAR-ROOT
  -WEB-INF
  -IMAGES
    -image1.jpg
    -image2.jpg
  -index.html

Когда я генерирую html через свои сервлеты/jsp/etc, я могу просто ссылаться на

http://host/contextroot/IMAGES/image1.jpg

и

http://host/contextroot/IMAGES/image1.jpg

Не я пишу сервлет, который должен получить ссылку файловой системы на эти изображения (в этом случае для рендеринга составного файла .pdf). Есть ли у кого-нибудь предложение о том, как получить ссылку файловой системы на файлы, размещенные в войне, подобно тому, как это происходит?

Возможно, это URL-адрес, который я хватаю при инициализации сервлета? Очевидно, у меня мог бы быть файл свойств, который явно указывает на установленный каталог, но я хотел бы избежать дополнительных конфигураций.


person benstpierre    schedule 06.05.2011    source источник
comment
Думал, что EAR заменило WAR... Рассматривали ли вы возможность использования отражения?   -  person OMG Ponies    schedule 06.05.2011
comment
Никакие военные файлы все еще не используются все время, это не EJB-приложение. Чем может помочь отражение?   -  person benstpierre    schedule 06.05.2011
comment
Отражение позволит вам искать местоположение без использования относительного пути   -  person OMG Ponies    schedule 06.05.2011
comment
@OMG слишком много выпил? ;)   -  person BalusC    schedule 06.05.2011
comment
@BalusC: Java заставляет меня пить hic :p   -  person OMG Ponies    schedule 06.05.2011


Ответы (4)


Если вы можете гарантировать расширение WAR, вы можете использовать ServletContext#getRealPath(), чтобы преобразовать относительный веб-путь в абсолютную дисковую файловую систему, которую вы можете в дальнейшем использовать в обычных операциях ввода-вывода Java.

String relativeWebPath = "/IMAGES/image1.jpg";
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);
InputStream input = new FileInputStream(file);
// ...

Однако, если вы не можете гарантировать, что WAR будет расширен (т. е. все ресурсы по-прежнему упакованы внутри WAR), и вас на самом деле не интересует абсолютный путь к файловой системе диска, и все, что вам на самом деле нужно, это просто InputStream из него, затем используйте getServletContext().getResourceAsStream() вместо этого.

String relativeWebPath = "/IMAGES/image1.jpg";
InputStream input = getServletContext().getResourceAsStream(relativeWebPath);
// ...

Смотрите также:

person BalusC    schedule 06.05.2011
comment
Что касается вашего второго пункта, в каком случае файл .war не будет расширен? Насколько я знаю, когда вы загружаете файл .war в обычные контейнеры сервлетов, он распаковывает их для вас в рабочий каталог. Вы знаете конкретный случай, на который следует обратить внимание? - person benstpierre; 06.05.2011
comment
Это настраивается на уровне сервера. Большинство контейнеров сервлетов по умолчанию распаковывает их. Но большинство, если не все сторонние хостинги настроены так, чтобы этого не делать. В таком случае getRealPath() вернет null. В конце концов, если вас на самом деле интересует только InputStream, вам следует избегать использования getRealPath() и использовать getResourceAsStream() на ServletContext. - person BalusC; 06.05.2011
comment
Это хорошее решение! - person Scarlett; 27.06.2012

Используйте метод getRealPath контекста сервлета.

Ex:

String path = getServletContext().getRealPath("WEB-INF/static/img/myfile.jpeg");
person Mike Thomsen    schedule 06.05.2011

Это относительно просто: вы просто используете загрузчик классов для извлечения файлов из таблицы классов. :

InputStream is =  YourServlet.class.getClassLoader().getResourceAsStream("IMAGES/img1.jpg");

Есть несколько других классов getResoruce, на которые стоит обратить внимание. Также вам не нужно извлекать загрузчик класса через переменную класса в вашем сервлете. Любой класс, который, как вы знаете, был загружен контейнером, должен работать.

person Karthik Ramachandran    schedule 06.05.2011
comment
К сожалению, веб-контент не является частью пути к классам. Только /WEB-INF/lib и /WEB-INF/classes есть. Так что этот метод не сработает. - person BalusC; 06.05.2011

Если вы знаете относительное расположение файлов, вы можете запросить среду выполнения о точном местоположении, используя

Thread.currentThread().getContextClassLoader().getResource(<relative-path>/<filename>)

Это даст вам URL-адрес места, где можно найти указанное изображение. Этот URL-адрес можно использовать для чтения указанного файла, или вы можете разделить его, чтобы использовать различные части URL-адреса для дальнейшей обработки.

person Osiris76    schedule 06.05.2011
comment
К сожалению, веб-контент не является частью пути к классам. Только /WEB-INF/lib и /WEB-INF/classes есть. Так что этот метод не сработает. - person BalusC; 06.05.2011