Как обслуживать статический контент в веб-приложении Java с внутреннего сервера? - PullRequest
0 голосов
/ 11 июня 2019

Это стандартная (возможно, тривиальная) ситуация, но я не могу найти подробную информацию по теме.

Предположим, у нас есть веб-приложение A (http://my-webapp) и файловый сервер F (http://file-server).

Для ясности:

  • A работает на Jetty 9;
  • F виден для сервера Jetty и НЕ виден для клиента.

Что лучше всего показать в A изображение, хранящееся в F ?

Предположим, клиент делает запрос http://my-webapp/pictures/123, где 123 - любой идентификатор, который каким-либо образом указывает на изображение, хранящееся как http://file-server/storage/xxx123.jpg, и ожидаетпосмотреть картинку в браузере.

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Я предлагаю следующее решение в качестве минимального примера, который может быть хорошей отправной точкой.

Перенаправление на .htaccess, похоже, делает подобные вещи на низком уровне.

На самом делеЭта проблема должна решаться самим сервером веб-приложений без вмешательства внешних инструментов (таких как Apache httpd или Nginx).

1.Объявите сервлет в web.xml

<servlet>
    <servlet-name>pictures</servlet-name>
    <servlet-class>myapplication.servlets.HiddenFileServlet </servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>pictures</servlet-name>
    <url-pattern>/pictures/*</url-pattern>
</servlet-mapping>

2.Реализовать сервлет

public class HiddenFileServlet extends HttpServlet
{     
  @Inject
  MyService myService; // a service for paths finding on http://file-server

  @Override
  protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws IOException
  {        
    String requestedUri = req.getRequestURI();

    String fileName = myService.getFileName( requestedUri );

    String mime = getServletContext().getMimeType( fileName );

    if ( mime == null )
    {
      resp.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
      return;
    }
    else
    {
      resp.setContentType( mime );
    }

    // path on http://file-server/storage
    URL fileFullPath = myService.getInternalPath( requestedUri );

    URL file = new URL( fileFullPath );

    try (
        InputStream in = file.openStream();
        OutputStream out = resp.getOutputStream()
    )
    {
       org.apache.commons.compress.utils.IOUtils.copy( in, out );
    }
  }
}
0 голосов
/ 11 июня 2019

«Лучшая практика» охватывает лот земли.

Из соображений загрузки и производительности рекомендуется использовать веб-сервер (например, NGINX или Apache), а не сервер приложений для обслуживания статических ресурсов. Большинство производственных сред имеют такую ​​настройку, используя веб-сервер для прокси-запросов к серверу приложений, когда это необходимо.

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

Если это невозможно, поскольку логика имени файла не может быть записана в регулярном выражении или аналогичном, вы можете написать сервлет в A , чтобы выполнить перенаправление в «обычное» веб-местоположение. Что-то вроде:

Я настоятельно рекомендую вам , а не использовать сервлет, чтобы прочитать файл из F и затем передать его в браузер; это потребляет большие объемы памяти на сервере приложений и может замедляться или даже зависать в зависимости от условий вашей локальной сети. Производительность вашего приложения почти наверняка очень быстро ухудшится под нагрузкой.

...