如何通过内部服务器在Java Web应用程序中提供静态内容?

时间:2019-06-11 11:37:10

标签: java http web-applications webserver static-content

这是标准情况(可能是微不足道的情况),但是我找不到有关该主题的详细信息。

假设我们有一个Web应用程序 A http://my-webapp)和一个文件服务器 F http://file-server)。

为清楚起见:

  • A 在Jetty 9上运行;
  • F 对Jetty服务器可见,对客户端不可见。

A 中显示存储在 F 中的图片的最佳做法是什么?

假设客户端发出一个请求http://my-webapp/pictures/123,其中123-任何ID,以某种方式指向存储为http://file-server/storage/xxx123.jpg的图片,并希望在浏览器中看到该图片。

2 个答案:

答案 0 :(得分:0)

“最佳实践”涵盖了很多背景。

出于负载和性能的原因,最好使用Web服务器(例如NGINX或Apache)而非应用程序服务器来提供静态资产。大多数生产环境都有此设置,必要时使用Web服务器将请求代理到应用程序服务器。

如果具有这样的设置,则可以将 F 上的映像驱动器映射为Web服务器上的驱动器,并使用.htaccess重写规则来处理文件名逻辑。

如果由于无法在正则表达式或类似文件中捕获文件名逻辑而无法执行此操作,则可以在 A 上编写servlet,以发布重定向到“常规”网站的位置。类似于:

我强烈建议您不要使用servlet从 F 读取文件,然后将其流式传输到浏览器;这会消耗您的应用程序服务器上的大量内存,并且可能会减慢甚至失败,具体取决于您的本地网络状况。在负载下,您的应用程序的性能几乎肯定会很快下降。

答案 1 :(得分:0)

我提出以下解决方案作为一个最小的示例,这可能是一个很好的起点。

通过.htaccess进行重定向似乎在底层上做了类似的事情。

实际上,该问题应该由Web应用程序服务器本身解决,而无需外部工具(例如Apache httpd或Nginx)的干预。

1。在web.xml中声明servlet

<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。实现servlet

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 );
    }
  }
}