【问题标题】:Write an HTML page in the servlet response properly在 servlet 响应中正确编写 HTML 页面
【发布时间】:2011-11-14 21:06:35
【问题描述】:

我在http://ip:8080/simple下部署了一个servlet
servlet 位于包 a.b.c
我在a.b.resources 中有一个名为Test.html 的html 页面。

html 有一个图片的img 标签。

在我做的 servlet 中:

htmlFile = MyServlet.class.getResourceAsStream("/a/b/resources/Test.html");
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
byte[] bytes=new byte[htmlFile.available()];
htmlFile.read(bytes);
resp.setContentLength(bytes.length);
writer.print(new String(bytes));
writer.flush();
writer.close();

html 页面出现在浏览器上,但在图片的位置我看到了它的alt 描述。
我试过了:

<img alt="Company A" src="./CompanyLogo.jpg">

<img alt="Company A" src="/a/b/resources/CompanyLogo.jpg">

<img alt="Company A" src="CompanyLogo.jpg">

但这些都不起作用。
jpg 图像位于 /a/b/c/resources 下,即与 HTML 页面位于同一目录中。
我正在使用嵌入式码头。

我在搞什么鬼?

【问题讨论】:

    标签: java html servlets jetty embedded-jetty


    【解决方案1】:

    浏览器正在尝试解析与当前请求 URI 相关的资源(如您在浏览器地址栏中所见)。这些资源当然不存在于您的公共 Web 内容中,因为您似乎已将它们放在类路径中。

    为了解决这个问题,您真的需要解析 HTML 并更改&lt;a&gt;&lt;img&gt;、@ 的所有域相关src 和/或href 属性987654328@、&lt;link&gt;&lt;script&gt;&lt;iframe&gt; 等元素,让它们指向一个 servlet,将这些资源从类路径流式传输到 HTTP 响应。

    这有点麻烦,但Jsoup 让它变得简单。这是一个假设您的 servlet 映射到 /proxy/* 的 URL 模式的示例。

    String proxyURL = request.getContextPath() + "/proxy/";
    InputStream input = MyServlet.class.getResourceAsStream("/a/b/resources" + request.getPathInfo());
    
    if (request.getRequestURI().endsWith(".html")) { // A HTML page is been requested.
        Document document = Jsoup.parse(input, "UTF-8", null);
    
        for (Element element : document.select("[href]")) {
            element.attr("href", proxyURL + element.attr("href"));
        }
    
        for (Element element : document.select("[src]")) {
            element.attr("src", proxyURL + element.attr("src"));
        }
    
        response.setContentType("text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(document.html());
    }
    else { // Other resources like images, etc which have been proxied to this servlet.
        response.setContentType(getServletContext().getMimeType(request.getPathInfo()));
        OutputStream output = response.getOutputStream();
        byte[] buffer = new byte[8192];
    
        for (int length = 0; (length = input.read(buffer)) > 0;) {
            output.write(buffer, 0, length);
        }
    }
    
    input.close();
    

    通过http://yourdomain:yourport/contextname/proxy/test.html打开它。

    【讨论】:

    • +1。谢谢你的详细回答。说实话,我觉得自己像个白痴。我的目的是在一个特定的实例中发送一个带有徽标图像的禁止页面。我认为那是最快的方法(因为我认为在 Jetty 中需要更多的 jars 才能使用 jsp)。看来我走错路了
    • 无论如何,我宁愿将这些资源放在公共网络内容中。这一切都很笨拙:)
    • 在嵌入式码头中,不确定公共网络内容在哪里放置
    • 将其添加为WebAppContext。另见 Jetty 自己的教程:wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty
    【解决方案2】:

    如果不实现从资源文件中读取图像的 servlet,就无法做到这一点。试试这个:

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
      byte[] bbuf = new byte[8192];
      resp.setContentType(req.getSession().getServletContext().getMimeType( req.getPathInfo()));
      InputStream in = MyImageServlet.class.getResourceAsStream("/"+req.getPathInfo());
      OutputStream op = resp.getOutputStream();
      int length;
      while ((in != null) && ((length = in.read(bbuf)) != -1)){
          op.write(bbuf,0,length);
          op.flush();
      }
      in.close();
      op.close();  
    }
    

    然后像这样在你的web.xml注册它

    <servlet-mapping>
      <servlet-name>fetchimage</servlet-name>
      <url-pattern>/fetchimage/*</url-pattern>
    </servlet-mapping>
    

    然后像这样使用它

    <img alt="Company A" src="/fetchimage/a/b/resources/CompanyLogo.jpg">
    

    您将需要实现大量错误检查(A LOT OF ERROR CHECKING,只是为了澄清:)),过滤路径以确保有人不能只使用相同的技术读取您的类文件,但有些对此的变化应该适合你。

    【讨论】:

    • 真的吗?我认为这是一种快速的方式。但是浏览器得到一个html页面。浏览器不是使用src标签来请求图像吗?
    • 是的,但是标准的 servlet 文件处理程序不会内省到所有 jar 中寻找文件。如果您想快速将所有图像复制到项目的顶级目录中。
    【解决方案3】:

    request.getRequestDispatcher("/a/b/Test.html").forward(request, response);

    【讨论】:

    • download.oracle.com/docs/cd/E17802_01/products/products/servlet/…, javax.servlet.ServletResponse)。将请求从 servlet 转发到另一个资源(servlet、JSP 文件或 HTML 文件)。如果你的 html 页面被打包在你的 war 中的 /a/b/Test.html 位置,那么它将起作用。
    • 可能是Jetty的原因
    • 不是,这个我用过很多次了。我有一个 GAE/GWT 项目,其中还包括执行此操作的 servlet。我的 servlet 中的代码:request.getRequestDispatcher("/JavakataPage.html").forward(request, response);。 html文件在war中的位置:在war文件的根目录中。我正在使用 Servlet API 2.4 版执行此操作。在码头上试一下没问题。
    • 当我这样做时,它似乎进入了一个循环并不断向前调用。最终我得到一个异常。
    • 你可以试试 response.sendRedirect("full_public_url_of_Test.html"); 但这根本不是一回事......
    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    相关资源
    最近更新 更多