代码之家  ›  专栏  ›  技术社区  ›  skaffman

SiteMesh:更改响应的内容类型

  •  2
  • skaffman  · 技术社区  · 14 年前

    我试图说服一个SiteMesh装饰师改变响应的内容类型,但没有任何乐趣。内容类型最终总是与修饰过的JSP相同,而不是装饰器的类型。

    例如,假设我有一个带有头部的JSP

    <%@ page contentType="application/xhtml+xml" %>
    

    我还有一个SiteMesh Decorator JSP,它定义了以下内容:

    <%@ page contentType="application/vnd.wap.xhtml+xml" %>
    

    我想要的是让装饰响应具有装饰器的mime类型(这里使用的实际mime类型并不重要,这只是为了说明问题)。

    通过对SiteMesh 2.4.1源的深入研究,我们发现问题在于 ContentBufferingResponse 类,它负责捕获目标的输出。这将覆盖 setContentType() 方法,记录值供以后使用,但它还调用 super.setContentType() ,有效地将目标JSP的内容类型直接传递给响应。一旦这样做了,再多的哄骗也无法说服反应者去做其他的事情。

    有没有解决办法?目标JSP的内容类型是否可以被抑制,并从修饰符中获取?

    2 回复  |  直到 12 年前
        1
  •  1
  •   user159088    14 年前

    这个 ContentBufferingResponse.setContentType 将触发对 HttpServletResponseWrapper.setContentType . 稍后,使用 RequestDispatcher.include 无法更改状态代码或设置头(忽略任何更改尝试)。所以基本上,一旦你设置了内容类型,游戏结束,你就可以改变它。

    据我所见, SiteMeshFilter.obtainContent 方法是唯一 ContentBufferingResponse 类已实例化,因此 SiteMeshFilter 内容缓冲响应 会是寻找解决办法的地方。

    一个可能的解决方法是覆盖 obtainContent 在的子类中 站点过滤器 并在运行时使用多态性调用正确的方法。这有一个问题: 获取内容 标记为private,因此多态性将不起作用。打电话给其他人 获取内容 方法您必须在过滤器中覆盖比此方法多得多的内容,我担心这将包括 doFilter 方法本身。

    另一个解决方法是以某种方式调用 setContentType 方法,不调用的方法 super.setContentType 带有装饰页的mime类型。但是您可以在中更改对另一个方法的调用。 获取内容 _ 内容缓冲响应 使用__new__的实例。

    此时,您可以创建 内容缓冲响应 类(在同一个包声明下),其中 设置内容类型 方法调用 super.setContentType(超级.setContentType) 使用所需的mime类型,而不是装饰页中的mime类型。然后,通过使用类路径并确保在SiteMesh的jar中加载类之前加载类,您可以欺骗服务器加载类而不是原始类。这里的主要问题是,如果您有多个decorator(而且我确信您有:d),那么管理不同的mime类型。

    第三个(也是难看的)解决方法是黑客破解SiteMesh的代码,并按照自己的方式解决(不确定您是否会遇到许可证问题)。

    因此,在我看来,除非你愿意采取一些丑陋的解决方法,否则一旦设置好内容类型,你将无法更改它。

        2
  •  0
  •   Nathan buster    12 年前

    编写一个适用于您的页面的servlet过滤器,重写 setContentType() 不调用super,然后在decorator中,您可以将内容类型设置为您想要的任何类型。

    您需要再编写一个servlet过滤器来完成这项工作,但它应该非常简单。